如何为“选择”框制作占位符?

Posted

技术标签:

【中文标题】如何为“选择”框制作占位符?【英文标题】:How do I make a placeholder for a 'select' box? 【发布时间】:2011-08-13 21:16:49 【问题描述】:

我正在为文本输入使用占位符,效果很好。但我也想为我的选择框使用占位符。当然我可以直接使用这段代码:

<select>
    <option value="">Select your option</option>
    <option value="hurr">Durr</option>
</select>

但“选择您的选项”是黑色而不是浅灰色。所以我的解决方案可能是基于 CSS 的。 jQuery 也不错。

这只会使下拉菜单中的选项变为灰色(因此在单击箭头后):

option:first 
    color: #999;

问题是:人们如何在选择框中创建占位符?但它已经得到了回答,干杯。

使用此选项会导致所选值始终为灰色(即使在选择了实物期权之后):

select 
    color: #999;

【问题讨论】:

以防万一有人读到这个 ​​- 我发布了一个更常见的现代浏览器解决方案,其中包含浏览器的内置验证。欢迎来到 2020 年 ;) 【参考方案1】:

非 CSS - 没有 javascript/jQuery 答案:

<select>
    <option value="" disabled selected>Select your option</option>
    <option value="hurr">Durr</option>
</select>

更新(2021 年 12 月):

这适用于最新的 Firefox、Chrome 和 Safari。正如 cmets 所指出的,它过去在许多浏览器中都不起作用。

【讨论】:

Firefox (10) 不显示禁用选项作为默认选择(占位符)。它默认显示下一个,在本例中为“Durr”。 一旦用户选择了一个值,他就不能再次取消选择(即使选择的值是可选的)! @PoulBak 我认为在大多数用户体验环境中这实际上是首选。 在 Chrome 95 中测试,它也不会将禁用的项目显示为占位符。鉴于 Firefox 和 Chrome 是当今浏览器使用的主要份额,这对我来说不是解决方案。 2021 年 12 月,使用最新的 chrome 和 safari,我无法让框中显示的文本像初始占位符一样变灰(在弹出菜单中只有灰色)。这种技术不起作用【参考方案2】:

我只是偶然发现了这个问题,这就是在 Firefox 和 Chrome 中有效的方法(至少):

<style>
select:invalid  color: gray; 
</style>
<form>
<select required>
    <option value="" disabled selected hidden>Please Choose...</option>
    <option value="0">Open when powered (most valves do this)</option>
    <option value="1">Closed when powered, auto-opens when power is cut</option>
</select>
</form>

Disabled 选项停止使用鼠标和键盘选择&lt;option&gt;,而仅使用'display:none' 允许用户仍然通过键盘箭头进行选择。 'display:none' 样式只是让列表框看起来“不错”。

注意:在“占位符”选项上使用空的value 属性允许验证(必需属性)解决“占位符”,因此如果该选项未更改,但需要,浏览器应提示用户从列表中选择一个选项。

更新(2015 年 7 月):

确认此方法在以下浏览器中有效:

谷歌浏览器 - v.43.0.2357.132 Mozilla Firefox - v.39.0 Safari - v.8.0.7(占位符在下拉菜单中可见,但不可选择) Microsoft Internet Explorer - v.11(占位符在下拉列表中可见,但不可选择) Project Spartan - v.15.10130(占位符在下拉菜单中可见,但不可选择)

更新(2015 年 10 月):

我删除了 style="display: none" 以支持 html5 属性 hidden,它得到了广泛的支持。 hidden 元素与 Safari、Internet Explorer 中的 display: none 具有相似的特征(Project Spartan 需要检查),其中 option 在下拉列表中可见,但不可选择。

更新(2016 年 1 月):

select 元素是required 时,它允许使用:invalid CSS 伪类,它允许您在select 元素处于“占位符”状态时为其设置样式。 :invalid 在这里有效,因为占位符 option 中的值为空。

一旦设置了一个值,:invalid 伪类将被删除。如果您愿意,您也可以选择使用:valid

大多数浏览器都支持这个伪类。 Internet Explorer 10 及更高版本。这最适用于自定义样式的 select 元素;在某些情况下,即(Chrome / Safari 中的 Mac),您需要更改 select 框的默认外观,以便显示某些样式,即 background-colorcolor。您可以在developer.mozilla.org 找到一些示例和更多关于兼容性的信息。

Chrome 中 Mac 的原生元素外观:

在 Chrome 中使用更改的边框元素 Mac:

【讨论】:

这个确实有效(2021 年 12 月,chrome/safari)。甚至可以在 sn-p 中工作,这与接受的答案的 sn-p 不同。【参考方案3】:

对于必填字段,现代浏览器中有纯 CSS 解决方案:

select:required:invalid 
  color: gray;

option[value=""][disabled] 
  display: none;

option 
  color: black;
<select required>
  <option value="" disabled selected>Select something...</option>
  <option value="1">One</option>
  <option value="2">Two</option>
</select>

【讨论】:

【参考方案4】:

类似这样的:

HTML:

<select id="choice">
    <option value="0" selected="selected">Choose...</option>
    <option value="1">Something</option>
    <option value="2">Something else</option>
    <option value="3">Another choice</option>
</select>

CSS:

#choice option  color: black; 
.empty  color: gray; 

JavaScript:

$("#choice").change(function () 
    if($(this).val() == "0") $(this).addClass("empty");
    else $(this).removeClass("empty")
);

$("#choice").change();

工作示例:http://jsfiddle.net/Zmf6t/

【讨论】:

This works fine, when the select value is optional, the user can deselect again.【参考方案5】:

我刚刚在option 中添加了一个隐藏属性,如下所示。它对我来说很好用。

<select>
  <option hidden>Sex</option>
  <option>Male</option>
  <option>Female</option>
</select>

【讨论】:

厉害,最简单的一个! 一旦用户选择了一个值,他就不能再次取消选择(即使选择的值是可选的)! 我知道为什么,但这让我兴奋。【参考方案6】:

以下解决方案也适用于 Firefox,无需任何 JavaScript:

option[default] 
  display: none;
<select>
  <option value="" default selected>Select Your Age</option>
  <option value="1">1</option>
  <option value="2">2</option>
  <option value="3">3</option>
  <option value="4">4</option>
</select>

【讨论】:

一旦用户选择了一个值,他就不能再次取消选择(即使选择的值是可选的)!【参考方案7】:

我遇到了同样的问题,在搜索时遇到了这个问题,在找到适合我的好解决方案后,我想与大家分享一下,以防有人从中受益。

这里是:

HTML:

<select class="place_holder dropdown">
    <option selected="selected" style=" display: none;">Sort by</option>
    <option>two</option>
    <option>something</option>
    <option>4</option>
    <option>5</option>
</select>

CSS:

.place_holder 
    color: gray;

option 
    color: #000000;

JavaScript:

jQuery(".dropdown").change(function () 
    jQuery(this).removeClass("place_holder");
);

客户进行第一次选择后,不再需要灰色,因此 JavaScript 代码删除了 place_holder 类。

感谢@user1096901,作为 Internet Explorer 浏览器的解决方法,您可以再次添加 place_holder 类,以防再次选择第一个选项 :)

【讨论】:

【参考方案8】:

不需要任何 JavaScript 或 CSS,只需要三个属性:

<select>
    <option selected disabled hidden>Default Value</option>
    <option>Value 1</option>
    <option>Value 2</option>
    <option>Value 3</option>
    <option>Value 4</option>
</select>

它根本不显示选项;它只是将选项的值设置为默认值。

但是,如果您只是不喜欢与其他颜色相同的占位符,您可以像这样内联修复它:

<!DOCTYPE html>
<html>
    <head>
        <title>Placeholder for select tag drop-down menu</title>
    </head>

    <body onload="document.getElementById('mySelect').selectedIndex = 0">
        <select id="mySelect" onchange="document.getElementById('mySelect').style.color = 'black'"     style="color: gray;    width: 150px;">
          <option value="" hidden>Select your beverage</option> <!-- placeholder -->
          <option value="water" style="color:black" >Water</option>
          <option value="milk" style="color:black" >Milk</option>
          <option value="soda" style="color:black" >Soda</option>
        </select>
    </body>
</html>

显然,您可以将函数和至少选择的 CSS 分离到单独的文件中。

注意: onload 函数修正了刷新错误。

【讨论】:

【参考方案9】:

用户不应在选择选项中看到占位符。我建议对占位符选项使用hidden 属性,并且您不需要此选项的selected 属性。你可以把它放在第一位。

select:not(:valid) 
  color: #999;
<select required>
    <option value="" hidden>Select your option</option>
    <option value="0">First option</option>
    <option value="1">Second option</option>
</select>

【讨论】:

一旦用户选择了一个值,他就不能再次取消选择(即使选择的值是可选的)!【参考方案10】:

这里我修改了David's answer(接受的答案)。在他的回答中,他在option 标签上添加了 disabled 和 selected 属性,但是当我们也添加隐藏标签时,它看起来会更好。

通过在option 标签上添加一个额外的隐藏属性,它将防止在选择“Durr”选项后重新选择“选择您的选项”选项。

<select>
    <option value="" disabled selected hidden>Select your option</option>
    <option value="hurr">Durr</option>
</select>

【讨论】:

【参考方案11】:

select:focus option.holder 
  display: none;
<select>
    <option selected="selected" class="holder">Please select</option>
    <option value="1">Option #1</option>
    <option value="2">Option #2</option>

</select>

【讨论】:

【参考方案12】:

我看到了正确答案的迹象,但要将所有这些结合在一起,这将是我的解决方案:

select 
  color: grey;


option 
  color: black;


option[default] 
   display: none;
<select>
    <option value="" default selected>Select your option</option>
    <option value="hurr">Durr</option>
</select>

【讨论】:

【参考方案13】:
    selected 在页面加载时选择特定选项 disabled 确保在表单提交中排除该选项 hidden 视觉上隐藏了下拉列表中的选项

    <select>
        <option selected disabled hidden>Choose an Option</option>
        <option>One</option>
        <option>Two</option>
        <option>Three</option>
</select>

【讨论】:

您应该提供一些上下文来解释您的答案与接受的答案有何不同 它只使用一个选择标签,没有任何 JQuery 和 CSS 。使用属性 Disabled , selected & hidden 重点是帮助那些不了解这些属性的人。通常在 Stack Overflow 上并不能很好地接受一个只转储代码而没有解释的答案。【参考方案14】:

如果您使用的是 Angular,请这样做:

<select>
    <option [ngValue]="undefined"  disabled selected>Select your option</option>
    <option [ngValue]="hurr">Durr</option>
</select>

【讨论】:

【参考方案15】:

这个 HTML + CSS 解决方案对我有用:

form select:invalid 
  color: gray;


form select option:first-child 
  color: gray;


form select:invalid option:not(:first-child) 
  color: black;
<form>
  <select required>
    <option value="">Select Planet...</option>
    <option value="earth">Earth</option>
    <option value="pandora">Pandora</option>
  </select>
</form>

【讨论】:

【参考方案16】:

这对我很有效:

<select class="form-control">
    <option value="" readonly="true" hidden="true" selected>Select your option</option>
    <option value="1">Something</option>
    <option value="2">Something else</option>
    <option value="3">Another choice</option>
</select>

【讨论】:

【参考方案17】:

JavaScript 中的另一种可能性:

 $('body').on('change', 'select', function (ev)
    if($(this).find('option:selected').val() == "")
        $(this).css('color', '#999');
        $(this).children().css('color', 'black');
    
    else 
        $(this).css('color', 'black');
        $(this).children().css('color', 'black');
    
);

JSFiddle

【讨论】:

【参考方案18】:

在MattW's answer 的基础上,您可以在做出有效选择后使选择占位符选项在下拉菜单中可见,方法是仅在占位符保持选中状态时有条件地隐藏它(因此选择是:无效) .

select:required:invalid 
  color: gray;

select:invalid > option[value=""][disabled] 
  display: none;

option 
  color: black;
<select required>
    <option value="" disabled selected>Select something...</option>
    <option value="1">One</option>
    <option value="2">Two</option>
</select>

【讨论】:

【参考方案19】:

您可以将第一个选项的颜色设置为gray,将其显示设置为none,将select 的颜色设置为gray,并为其添加一个input 事件监听器来设置它的颜色到black

select > option:not(:first-of-type) 
  color: black;
<select style='color:gray' oninput='style.color="black"'>
  <option style='display:none'>
    Choose an option
  </option>
  <option>
    1
  </option>
  <option>
    2
  </option>
  <option>
    3
  </option>
</select>

使用customElement API:

class placeholderSelect extends HTMLElement 
  connectedCallback() 
    this.innerHTML = `<select style='color:gray' oninput='style.color="black"'>
  <option style='display:none'>
    $this.getAttribute('data-placeholder')
  </option>
  $this.innerHTML
</select>`;

    Array.from(this.children[0].children).forEach(function(el, i) 
        el.style.color = 'black';
    );
  


customElements.define('placeholder-select', placeholderSelect);
<placeholder-select data-placeholder='Choose an option'>
  <option>
    1
  </option>
  <option>
    2
  </option>
  <option>
    3
  </option>
</placeholder-select>

【讨论】:

【参考方案20】:

我喜欢 the accepted solution,它在没有 JavaScript 的情况下也能很好地工作。

我只是想补充一下我是如何为 受控选择 React 组件采用这个答案的,因为我花了几次尝试才弄明白。合并react-select 并完成它真的很简单,但是除非您需要这个存储库提供的惊人功能,我不针对有问题的项目,没有必要在我的包中添加更多的千字节.请注意,react-select 通过各种 inputshtml 元素的复杂系统处理选择中的占位符。

在 React 中,对于 controlled component,您不能将 selected 属性添加到您的选项中。 React 通过 select 本身的 value 属性以及更改处理程序来处理 select 的状态,其中值应与选项本身中的值属性之一匹配。

例如,例如

<select value=this.state.selectValue onChange=this.handleChange required=true>
    options
</select>

既然将selected 属性添加到其中一个选项是不合适的,而且实际上会引发错误,那么该怎么办?

想一想,答案很简单。既然我们希望我们的第一个 optionselected 以及 disabledhidden,我们需要做三件事:

    hiddendisabled 属性添加到第一个定义的option。 将第一个option的值设置为空字符串。 将select 的值初始化为空字符串。
state =  selectValue = ""  // State or props or their equivalent

// In the render function
<select value=this.state.selectValue onChange=this.handleChange required=true>
    <option key="someKey" value="" disabled="disabled" hidden="hidden">Select from Below</option>
    renderOptions()
</select>

现在您可以按照上面的说明设置选择的样式(如果您愿意,也可以通过 className 设置)。

select:invalid  color: gray; 

【讨论】:

【参考方案21】:

您需要表单验证,现代浏览器从头开始提供此功能。

因此,您无需担心用户无法选择该字段。因为当他这样做时,浏览器验证会告诉他,这是一个错误的选择。

浏览器内置验证功能checkValidity()。

Bootstrap 也有一个很好的例子。

HTML

<form class="needs-validation">
  <select required>
    <option value="">Please select an option</option>
    <option value="1">Foo</option>
    <option value="2">Bar</option>
  </select>
<form>

Javascript

form = document.getElementByClassName('needs-validation');
if(form.checkValidity() === true) 
  //form validation succeeded
 else 
  //form validation failed

【讨论】:

【参考方案22】:

由于此线程中提供的答案之间的样式和功能不同,下表阐明了所提供的每种 HTML、HTML+CSS 和 HTML+CSS+Javascript 解决方案的样式和适用的表单逻辑。

由于某种原因,我不得不使用代码格式,因为 tables aren't permitted 在标记中。 将使用代码 sn-p 提供一个 HTML 表格来解决表格限制。

我已将此帖子标记为 community wiki,因此任何人都可以详细介绍新帖子,但请在备用帖子中添加 JQuery、React、Angular、CoffeeScript 等以保持此表的简单性。

         | Technologies |                                                                Styling                                                                |
  Post   | CSS | Java-  | Select: Placeholder |  Select: valid option  |                  Option: placeholder                    |     Option: valid option     |
   ID    |     | script | Color |  Validation | Color |    Required    | Visibility | Selectable | Color |   Cond. formatting    | Color |   Cond. formatting   |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
41167307 | No  |   No   | Black |   Invalid   | Black |      Yes       |  Visible   |     No     | Grey  |          No           | Black |          No          |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
50200912 | No  |   No   | Black |    Valid    | Black |       No       | Invisible  |    N/A     |  N/A  |          No           | Black |          No          |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
5859221  | No  |   No   | Black |    Valid    | Black |       No       |  Visible   |     No     | Grey  |          No           | Black |          No          |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
38120777 | No  |   No   | Black |    Valid    | Black |       No       | Invisible  |    N/A     |  N/A  |          No           | Black |          No          |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
54860799 | Yes |   No   | Grey  |   Invalid   | Black |      Yes       | Invisible  |    N/A     |  N/A  |          No           | Black |          No          |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
52661024 | Yes |   No   | Grey  |   Invalid   | Black |      Yes       | Invisible  |    N/A     |  N/A  |          No           | Black | select:invalidGrey |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
8442831  | Yes |   No   | Grey  |   Invalid   | Black |      Yes       | Invisible  |    N/A     |  N/A  |          No           | Black | select:invalidGrey |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
29806043 | Yes |   No   | Grey  |   Invalid   | Black |      Yes       | Invisible  |    N/A     |  N/A  |          No           | Black |          No          |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
61966461 | Yes |   No   | Grey  |   Invalid   | Black |      Yes       | Invisible  |    N/A     |  N/A  | select:validvisible | Black |          No          |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
44406771 | Yes |   No   | Grey  |   Invalid   | Grey  |      No        |  Visible   |     No     | Grey  |          No           | Black | select:invalidGrey |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
40603035 | Yes |   No   | Black |    Valid    | Black |      No        | Invisible  |    N/A     |  N/A  |          No           | Black |          No          |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
22994211 | Yes |   No   | Grey  |    Valid    | Black |      No        | Invisible  |    N/A     |  N/A  |          No           | Black |          No          |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
21722343 | Yes |   No   | Grey  |    Valid    | Grey  |      No        | Invisible  |    N/A     |  N/A  |          No           | Black |          No          |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
48960650 | Yes |  Yes   | Grey  |   Invalid   | Black |      No        | Invisible  |    N/A     |  N/A  |          No           | Black |          No          |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
5805194  | Yes |  Yes   | Grey  |    Valid    | Black |      No        |  Visible   |    Yes     | Black |          No           | Black |          No          |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
50840409 | Yes |  Yes   | Grey  |    Valid    | Black |      Yes       |  Visible   |    Yes     | Grey  |          No           | Black |          No          |

【讨论】:

【参考方案23】:

输入[type="text"] 选择元素的样式占位符

以下解决方案模拟与input[type="text"] 元素相关的占位符:

$('.example').change(function () 
  $(this).css('color', $(this).val() === '' ? '#999' : '#555');
);
.example 
  color: #999;


.example > option 
  color: #555;


.example > option[value=""] 
  color: #999;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<select class="example">
  <option value="">Select Option</option>
  <option>Option 1</option>
  <option>Option 2</option>
  <option>Option 3</option>
</select>

【讨论】:

【参考方案24】:

我希望 SELECT 在被选中之前是灰色的,因此对于这段 HTML:

<select>
  <option value="" disabled selected>Select your option</option>
  <option value="hurr">Durr</option>
</select>

我添加了这些 CSS 定义:

select  color: grey; 
select:valid  color: black; 

它在 Chrome / Safari 和其他浏览器中按预期工作,但我没有检查。

【讨论】:

【参考方案25】:

这是一个很好用的 CSS 解决方案。内容被添加(并且相对于容器绝对定位)在包含元素之后(通过:after伪类)。

它从我使用指令(attr(placeholder))定义的占位符属性中获取其文本。另一个关键因素是 pointer-events: none - 这允许点击占位符文本传递给选择。否则用户点击文本不会下拉。

我自己在我的选择指令中添加了 .empty 类,但通常我发现 Angular 会为我添加/删除 .ng-empty (我认为这是因为我我在我的代码示例中注入了 Angular 1.2 版)。

(该示例还演示了如何在 AngularJS 中包装 HTML 元素以创建您自己的自定义输入)

var app = angular.module("soDemo", []);
app.controller("soDemoController", function($scope) 
  var vm = ;
  vm.names = [
      id: 1,
      name: 'Jon'
    ,
    
      id: 2,
      name: 'Joe'
    , 
      id: 3,
      name: 'Bob'
    , 
      id: 4,
      name: 'Jane'
    
  ];
  vm.nameId;
  $scope.vm = vm;
);

app.directive('soSelect', function soSelect() 
  var directive = 
    restrict: 'E',
    require: 'ngModel',
    scope: 
      'valueProperty': '@',
      'displayProperty': '@',
      'modelProperty': '=',
      'source': '=',
    ,
    link: link,
    template: getTemplate
  ;
  return directive;


  /////////////////////////////////
  function link(scope, element, attrs, ngModelController) 
    init();
    return;


    ///////////// IMPLEMENTATION

    function init() 
      initDataBinding();
    


    function initDataBinding() 
      ngModelController.$render = function() 
        if (scope.model === ngModelController.$viewValue) return;
        scope.model = ngModelController.$viewValue;
      

      scope.$watch('model', function(newValue) 
        if (newValue === undefined) 
          element.addClass('empty');
          return;
        
        element.removeClass('empty');
        ngModelController.$setViewValue(newValue);
      );
    
  


  function getTemplate(element, attrs) 
    var attributes = [
      'ng-model="model"',
      'ng-required="true"'
    ];

    if (angular.isDefined(attrs.placeholder)) 
      attributes.push('placeholder="placeholder"');
    

    var ngOptions = '';

    if (angular.isDefined(attrs.valueProperty)) 
      ngOptions += 'item.' + attrs.valueProperty + ' as ';
    

    ngOptions += 'item.' + attrs.displayProperty + ' for item in source';
    ngOptions += '"';
    attributes.push('ng-options="' + ngOptions + '"');

    var html = '<select ' + attributes.join(' ') + '></select>';

    return html;
  
);
so-select 
  position: relative;


so-select select 
  font-family: 'Helvetica';
  display: inline-block;
  height: 24px;
  width: 200px;
  padding: 0 1px;
  font-size: 12px;
  color: #222;
  border: 1px solid #c7c7c7;
  border-radius: 4px;


so-select.empty:before 
  font-family: 'Helvetica';
  font-size: 12px;
  content: attr(placeholder);
  position: absolute;
  pointer-events: none;
  left: 6px;
  top: 3px;
  z-index: 0;
  color: #888;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="soDemo" ng-controller="soDemoController">
  <so-select value-property="id" display-property="name" source="vm.names" ng-model="vm.nameId" placeholder="(select name)"></so-select>
</div>

【讨论】:

【参考方案26】:

我目前无法让其中任何一个工作,因为对我来说,(1) 不需要并且 (2) 需要返回默认可选的选项。因此,如果您使用的是 jQuery,这里是一个笨拙的选择:

var $selects = $('select');
$selects.change(function () 
  var option = $('option:default', this);
  if(option && option.is(':selected')) 
    $(this).css('color', '#999');
  
  else 
    $(this).css('color', '#555');
  
);

$selects.each(function() 
  $(this).change();
);
option 
    color: #555;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select name="in-op">
    <option default selected>Select Option</option>
    <option>Option 1</option>
    <option>Option 2</option>
    <option>Option 3</option>
</select>

【讨论】:

【参考方案27】:

我不满足于仅使用 HTML/CSS 的解决方案,因此我决定使用 JavaScript 创建自定义 select

这是我在过去 30 分钟内写的东西,因此可以进一步改进。

您所要做的就是创建一个包含少量数据属性的简单列表。该代码会自动将列表转换为可选择的下拉列表。它还添加了一个隐藏的input 来保存选定的值,因此可以在表单中使用。

输入:

<ul class="select" data-placeholder="Role" data-name="role">
  <li data-value="admin">Administrator</li>
  <li data-value="mod">Moderator</li>
  <li data-value="user">User</li>
</ul>

输出:

<div class="ul-select-container">
    <input type="hidden" name="role" class="hidden">
    <div class="selected placeholder">
        <span class="text">Role</span>
        <span class="icon">▼</span>
    </div>
    <ul class="select" data-placeholder="Role" data-name="role">
        <li class="placeholder">Role</li>
        <li data-value="admin">Administrator</li>
        <li data-value="mod">Moderator</li>
        <li data-value="user">User</li>
    </ul>
</div>

应该是占位符的项目的文本显示为灰色。占位符是可选择的,以防用户想要恢复他/她的选择。同样使用 CSS,select 的所有缺点都可以克服(例如,无法设置选项的样式)。

// Helper function to create elements faster/easier
// https://github.com/akinuri/js-lib/blob/master/element.js
var elem = function(tagName, attributes, children, isHTML) 
  let parent;
  if (typeof tagName == "string") 
    parent = document.createElement(tagName);
   else if (tagName instanceof HTMLElement) 
    parent = tagName;
  
  if (attributes) 
    for (let attribute in attributes) 
      parent.setAttribute(attribute, attributes[attribute]);
    
  
  var isHTML = isHTML || null;
  if (children || children == 0) 
    elem.append(parent, children, isHTML);
  
  return parent;
;
elem.append = function(parent, children, isHTML) 
  if (parent instanceof HTMLTextAreaElement || parent instanceof HTMLInputElement) 
    if (children instanceof Text || typeof children == "string" || typeof children == "number") 
      parent.value = children;
     else if (children instanceof Array) 
      children.forEach(function(child) 
        elem.append(parent, child);
      );
     else if (typeof children == "function") 
      elem.append(parent, children());
    
   else 
    if (children instanceof HTMLElement || children instanceof Text) 
      parent.appendChild(children);
     else if (typeof children == "string" || typeof children == "number") 
      if (isHTML) 
        parent.innerHTML += children;
       else 
        parent.appendChild(document.createTextNode(children));
      
     else if (children instanceof Array) 
      children.forEach(function(child) 
        elem.append(parent, child);
      );
     else if (typeof children == "function") 
      elem.append(parent, children());
    
  
;


// Initialize all selects on the page
$("ul.select").each(function() 
  var parent    = this.parentElement;
  var refElem   = this.nextElementSibling;
  var container = elem("div", "class": "ul-select-container");
  var hidden    = elem("input", "type": "hidden", "name": this.dataset.name, "class": "hidden");
  var selected  = elem("div", "class": "selected placeholder", [
    elem("span", "class": "text", this.dataset.placeholder),
    elem("span", "class": "icon", "&#9660;", true),
  ]);
  var placeholder = elem("li", "class": "placeholder", this.dataset.placeholder);
  this.insertBefore(placeholder, this.children[0]);
  container.appendChild(hidden);
  container.appendChild(selected);
  container.appendChild(this);
  parent.insertBefore(container, refElem);
);

// Update necessary elements with the selected option
$(".ul-select-container ul li").on("click", function() 
  var text     = this.innerText;
  var value    = this.dataset.value || "";
  var selected = this.parentElement.previousElementSibling;
  var hidden   = selected.previousElementSibling;
  hidden.value = selected.dataset.value = value;
  selected.children[0].innerText = text;
  if (this.classList.contains("placeholder")) 
    selected.classList.add("placeholder");
   else 
    selected.classList.remove("placeholder");
  
  selected.parentElement.classList.remove("visible");
);

// Open select dropdown
$(".ul-select-container .selected").on("click", function() 
  if (this.parentElement.classList.contains("visible")) 
    this.parentElement.classList.remove("visible");
   else 
    this.parentElement.classList.add("visible");
  
);

// Close select when focus is lost
$(document).on("click", function(e) 
  var container = $(e.target).closest(".ul-select-container");
  if (container.length == 0) 
    $(".ul-select-container.visible").removeClass("visible");
  
);
.ul-select-container 
  width: 200px;
  display: table;
  position: relative;
  margin: 1em 0;

.ul-select-container.visible ul 
  display: block;
  padding: 0;
  list-style: none;
  margin: 0;

.ul-select-container ul 
  background-color: white;
  border: 1px solid hsla(0, 0%, 60%);
  border-top: none;
  -webkit-user-select: none;
  display: none;
  position: absolute;
  width: 100%;
  z-index: 999;

.ul-select-container ul li 
  padding: 2px 5px;

.ul-select-container ul li.placeholder 
  opacity: 0.5;

.ul-select-container ul li:hover 
  background-color: dodgerblue;
  color: white;

.ul-select-container ul li.placeholder:hover 
  background-color: rgba(0, 0, 0, .1);
  color: initial;

.ul-select-container .selected 
  background-color: white;
  padding: 3px 10px 4px;
  padding: 2px 5px;
  border: 1px solid hsla(0, 0%, 60%);
  -webkit-user-select: none;

.ul-select-container .selected 
  display: flex;
  justify-content: space-between;

.ul-select-container .selected.placeholder .text 
  color: rgba(0, 0, 0, .5);

.ul-select-container .selected .icon 
  font-size: .7em;
  display: flex;
  align-items: center;
  opacity: 0.8;

.ul-select-container:hover .selected 
  border: 1px solid hsla(0, 0%, 30%);

.ul-select-container:hover .selected .icon 
  opacity: 1;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<ul class="select" data-placeholder="Role" data-name="role">
  <li data-value="admin">Administrator</li>
  <li data-value="mod">Moderator</li>
  <li data-value="user">User</li>
</ul>

<ul class="select" data-placeholder="Sex" data-name="sex">
  <li data-value="male">Male</li>
  <li data-value="female">Female</li>
</ul>

更新:我对此进行了改进(使用向上/向下/回车键选择),稍微整理了输出,并将其变成了一个对象。当前输出:

<div class="li-select-container">
    <input type="text" readonly="" placeholder="Role" title="Role">
    <span class="arrow">▼</span>
    <ul class="select">
        <li class="placeholder">Role</li>
        <li data-value="admin">Administrator</li>
        <li data-value="mod">Moderator</li>
        <li data-value="user">User</li>
    </ul>
</div>

初始化:

new Liselect(document.getElementsByTagName("ul")[0]);

进一步检查:JSFiddle、GitHub(重命名)。


更新:我又重写了一遍。我们可以只使用选择,而不是使用列表。这样即使没有 JavaScript 也可以工作(以防它被禁用)。

输入:

<select name="role" data-placeholder="Role" required title="Role">
    <option value="admin">Administrator</option>
    <option value="mod">Moderator</option>
    <option>User</option>
</select>

new Advancelect(document.getElementsByTagName("select")[0]);

输出:

<div class="advanced-select">
    <input type="text" readonly="" placeholder="Role" title="Role" required="" name="role">
    <span class="arrow">▼</span>
    <ul>
        <li class="placeholder">Role</li>
        <li data-value="admin">Administrator</li>
        <li data-value="mod">Moderator</li>
        <li>User</li>
    </ul>
</div>

JSFiddle, GitHub.

【讨论】:

【参考方案28】:

看到这个答案:

<select>
        <option style="display: none;" value="" selected>SelectType</option>
        <option value="1">Type 1</option>
        <option value="2">Type 2</option>
        <option value="3">Type 3</option>
        <option value="4">Type 4</option>
</select>

【讨论】:

【参考方案29】:

您可以在不使用 JavaScript 并且仅使用 HTML 的情况下执行此操作 您需要设置默认选择选项 disabled=""selected="" 并选择标签 required="". 浏览器不允许用户在未选择选项的情况下提交表单.

<form action="" method="POST">
    <select name="in-op" required="">
        <option disabled="" selected="">Select Option</option>
        <option>Option 1</option>
        <option>Option 2</option>
        <option>Option 3</option>
    </select>
    <input type="submit" value="Submit">
</form>

【讨论】:

【参考方案30】:

Angular 中,我们可以添加一个选项作为占位符,可以在选项下拉列表中隐藏。 我们甚至可以添加一个自定义下拉图标作为替换浏览器下拉图标图标的背景。

技巧启用占位符仅在未选择值时

/**我的组件模板*/

 <div class="dropdown">
      <select [ngClass]="'placeholder': !myForm.value.myField"
 class="form-control" formControlName="myField">
        <option value="" hidden >Select a Gender</option>
        <option value="Male">Male</option>
        <option value="Female">Female</option>
      </select>
    </div>

/**我的组件.TS */

constructor(fb: FormBuilder) 
  this.myForm = this.fb.build(
    myField: ''
  );

/**global.scss*/

.dropdown 
  width: 100%;
  height: 30px;
  overflow: hidden;
  background: no-repeat white;
  background-image:url('angle-arrow-down.svg');
  background-position: center right;
  select 
    background: transparent;
    padding: 3px;
    font-size: 1.2em;
    height: 30px;
    width: 100%;
    overflow: hidden;

    /*For moz*/
    -moz-appearance: none;
    /* IE10 */
    &::-ms-expand 
      display: none;
    
    /*For chrome*/
    -webkit-appearance:none;
    &.placeholder 
      opacity: 0.7;
      color: theme-color('mutedColor');
    
    option 
      color: black;
    
  

【讨论】:

以上是关于如何为“选择”框制作占位符?的主要内容,如果未能解决你的问题,请参考以下文章

如何为select2添加占位符?

是否可以在文本框 ASP.NET 中使用多行占位符?

如何为 DIV 创建一个类似于文本字段的“占位符”?

如何为 YouTube 视频添加启动画面/占位符图像 [关闭]

如何为设置包的文本字段提供占位符(Root.plist)

PowerPoint2010占位符