首页 文章

如何为'select'框创建占位符?

提问于
浏览
1207

我正在使用占位符进行文本输入,这很好 . 但是我也想为我的选择框使用占位符 . 当然我可以使用这段代码:

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

但是“选择你的选项”是黑色而不是光泽 . 所以我的解决方案可能是基于CSS的 . jQuery也很好 .

这只会使下拉列表中的选项变为灰色(因此点击箭头后):

option:first {
    color: #999;
}

编辑:问题是:人们如何在选择框中创建占位符?但它已经得到了回答,欢呼 .

使用此选项会导致所选值始终为灰色(即使选择了实际选项后):

select {
    color:#999;
}

23 回答

  • 37

    这是我的

    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>
    
  • 1

    这是一个非常有效的 CSS 解决方案 . 在包含元素( via :after pseudo-class )之后添加内容(并相对于容器绝对定位) . 它从我定义的占位符属性获取其文本,我使用该指令( attr(placeholder) ) . 另一个关键因素是 pointer-events: none - 这允许对占位符文本的点击传递给选择 . 否则,如果用户单击文本,则不会下拉 .

    我在我的select指令中自己添加了 .empty 类,但通常我发现angular为我添加/删除 .ng-empty (我假设它在我的代码示例中注入了Angular 1.2版本's b/c I')

    (该示例还演示了如何在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>
    
  • 0

    我'm not content with HTML/CSS only solutions, so I'已决定使用JS创建自定义 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>
    

    Update :我对此进行了改进(使用上/下/输入键进行选择) . 稍微整理输出并将其转换为对象 . 当前输出:

    <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,_ 2009993(重命名) .


    Update: 再次改写 . 我们可以使用select而不是列表 . 这样它'll work even without JS (in case it' s禁用) .

    输入:

    <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>
    

    JSFiddleGitHub .

  • 21

    我希望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中可以正常工作,也可能在其他浏览器中使用,但我还没有检查过 .

  • 663

    对于上面的所有解决方案,但由于HTML规范,这个似乎最有效:

    <select>
      <optgroup label="Your placeholder">
        <option value="value">Label</option>
      </optgroup>
    </select>
    

    UPDATE: 请原谅我这个错误答案,这绝对不是 select 元素的占位符解决方案,而是打开的 select 元素列表下的分组选项的 Headers .

  • 4

    输入[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>
    
  • 191

    我看到了正确答案的迹象,但要将它们整合在一起,这将是我的解决方案 .

    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>
    
  • -6

    对于必填字段,现代浏览器中有一个纯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>
    
  • -2

    如果你使用角度就像这样

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

    JS的另一种可能性:

    $('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

  • 13

    试试这个改变

    $("select").css("color","#757575");
    $(document).on("change","select",function(){
        if ($(this).val() != "") {
            $(this).css("color","");
        } else {
            $(this).css("color","#757575");
        }
    });
    
  • 0

    这是我的贡献 . HAML Coffeescript SCSS
    HAML

    =f.collection_select :country_id, [us] + Country.all, :id, :name, {prompt: t('user.country')}, class: 'form-control'
    

    Coffeescript

    $('select').on 'change', ->
        if $(this).val()
          $(this).css('color', 'black')
        else
          $(this).css('color', 'gray')
      $('select').change()
    

    SCSS

    select option {
      color: black;
    }
    

    通过更改服务器代码并仅根据属性的当前值设置类样式,可以仅使用CSS,但这种方式似乎更简单,更清晰 .

    $('select').on('change', function() {
      if ($(this).val()) {
        return $(this).css('color', 'black');
      } else {
        return $(this).css('color', 'gray');
      }
    });
    
    $('select').change();
    
    select option {
          color: black;
        }
    
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <select class="form-control" name="user[country_id]" id="user_country_id">
      <option value="">Country</option>
                          <option value="231">United States</option>
                          <option value="1">Andorra</option>
                          <option value="2">Afghanistan</option>
                          <option value="248">Zimbabwe</option></select>
    

    您可以添加更多CSS( select option:first-child )以在占位符打开时保持灰色,但我并不关心 .

  • 2

    在这里我修改了大卫的答案(接受了答案) . 在他的回答中,他在选项标签上放置了禁用和选择的属性,但是当我们也放置隐藏标签时,它看起来会更好 . 通过在选项标签上添加额外的隐藏属性,将阻止在选择“Durr”选项后重新选择“选择您的选项”选项 .

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

    该解决方案也适用于FireFox:
    没有任何JS .

    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>
    
  • 2

    我遇到了同样的问题,在搜索时遇到了这个问题,在我找到好的解决方案之后,我想与你们分享,以防有人可以从中受益 . 这是: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;
    }
    

    JS:

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

    客户首先选择后不需要灰色,因此JS删除了类 place_holder . 我希望这可以帮助别人 :)

    Update: 感谢@ user1096901,作为IE浏览器的解决方案,你可以再次添加 place_holder class,以防再次选择第一个选项:)

  • 24

    用户不应在选择选项中看到占位符 . 我建议使用 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>
    
  • 95

    只是偶然发现了这个问题,这里有什么适用于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>
    

    “禁用”选项会停止使用鼠标和键盘选择 <option> ,而只使用 'display:none' 允许用户仍然通过键盘箭头进行选择 . 'display:none' 样式只使列表框看起来像'nice' .

    注意:在"placeholder"选项上使用空 value 属性允许验证(必需属性)解决"placeholder",因此如果选项未更改但需要;浏览器应提示用户从列表中选择一个选项 .

    Update (July 2015):

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

    • 谷歌浏览器 - 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(占位符在下拉列表中可见,但不可选)

    Update (October 2015):

    删除了 style="display: none" ,转而支持广泛支持的HTML5属性 hidden . hidden 元素与Safari,IE中的 display: none 具有相似的特征(Project Spartan需要检查),其中 option 在下拉列表中可见但不可选 .

    Update (January 2016):

    select 元素是 required 时,它允许使用 :invalid CSS伪类,它允许您在 select 元素处于"placeholder"状态时设置样式 . 由于占位符 option 中的空值, :invalid 在这里工作 .

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

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

    Chrome中的原生元素外观Mac:

    Select box native Mac in Chrome

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

    Altered select box Mac in Chrome

  • 12

    我刚刚在下面的选项中添加了隐藏属性,它对我来说很好 .

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

    不需要任何JS或CSS,只需要3个属性:

    <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>
    

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

    但是,如果你只是 don't like a placeholder that's the same color as the rest ,你可以像这样内联修复它:

    <!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>
    

    显然,您可以将函数和至少select的CSS分离为单独的文件 .

    Note: onload函数纠正了刷新错误 .

  • 1

    非CSS怎么样 - 没有javascript / jQuery的答案?

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

    这样的事可能吗?

    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/

  • 2468

    我目前无法使这些工作正常工作,因为对我而言,(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>
    
  • 14

    您可以在不使用仅使用HTML的Javascript的情况下执行此操作您需要设置默认选择选项disabled =“”和selected =“”并选择tag 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>
    

相关问题