Как сделать заполнитель для поля "выбрать"?


Я использую заполнители для ввода текста, который работает просто отлично. Но я также хотел бы использовать заполнитель для моих селекторов. Конечно, я могу просто использовать этот код:

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

но "Выберите свой вариант" находится в черном, а не светло-серый. Поэтому мое решение может быть основано на CSS. jQuery тоже в порядке.

Это только делает опцию серой в выпадающем списке (так что после нажатия на стрелку):

option:first {
    color: #999;
}

Edit: вопрос в том, как люди создать заполнители в окна? Но на него уже ответили, ура.

и использование этого приводит к тому, что выбранное значение всегда будет серым (даже после выбора реальной опции):

select {
    color:#999;
}
23 1172

23 ответа:

Как насчет ответа без CSS - no javascript/jQuery?

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

просто наткнулся на этот вопрос, вот что работает в 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' стиль просто делает список выглядеть "хорошо".

Примечание: с помощью пустой value атрибут на опции "заполнитель" позволяет проверку (требуется атрибут), чтобы обойти наличие "заполнителя", поэтому, если опция не изменена, но требуется; браузер должен предложить пользователю выбрать опцию из списка.

Обновление (Июль 2015):

этот метод подтверждается работой в следующих браузерах:

  • Гугл Хром - В. 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):

удалены style="display: none" в пользу атрибута HTML5 hidden, который имеет широкую поддержку. Элемент hidden элемент имеет аналогичные черты, как display: none в Safari, т. е. (проект Spartan нуждается проверка) где то option отображается в выпадающем списке, но не выбирается.

Обновление (Январь 2016):

когда select элемент required это позволяет использовать :invalid псевдо-класс CSS, который позволяет вам стилизовать select элемент, когда он находится в состоянии "заполнитель". :invalid работает здесь из-за пустого значения в местозаполнитель option.

после того, как значение было установлено на :invalid псевдо-класс будет удален. Вы можете по желанию также используйте :valid если вы так хотите.

большинство браузеров поддерживают этот псевдо-класс. IE10+. Это лучше всего работает с пользовательским стилем select элементы; в некоторых случаях т. е. (Mac в Chrome / Safari) вам нужно будет изменить внешний вид по умолчанию

для необходимого поля в современных браузерах есть решение pure-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>

что-то вроде этого возможно?

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/

Я просто добавил скрытый атрибут в опции, как показано ниже, он отлично работает для меня.

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

это решение работает и в 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>

у меня была такая же проблема и во время поисков наткнулся на этот вопрос, и после того, как я нашел хорошее решение для меня, я хотел бы поделиться им с вами в случае, если кто-то может извлечь из этого пользу. вот оно: 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. Надеюсь, это кому-то поможет :)

обновление: спасибо @user1096901, как a работа вокруг для браузера IE, вы можете добавить place_holder класс снова в случае, если первый вариант выбран снова :)

вот мой

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>

нет необходимости в каких-либо 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>

Он вообще не показывает опцию, просто устанавливает значение опции по умолчанию.

однако, если вы просто Не нравится заполнитель, который имеет тот же цвет, что и остальные, вы можете исправить это встроенное следующим образом:

<!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 select на отдельные файлы.

Примечание: функция onload исправляет ошибку обновления.

Я вижу признаки правильных ответов, но чтобы собрать все это вместе, это было бы моим решением.

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>

здесь я изменил ответ Дэвида (принятый ответ). На его ответ он поставил отключенный и выбранный атрибут на теге опции, но когда мы также поместим скрытый тег, он будет выглядеть намного лучше. Добавляя дополнительный скрытый атрибут на теге option, предотвратит повторный выбор опции " выберите свой вариант "после выбора опции" Durr".

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

еще одна возможность в 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

здесь CSS решение, которое прекрасно работает. Содержимое добавляется (и абсолютно позиционируется относительно контейнера) после содержащего элемента (через :после псевдо-класс). Он получает свой текст из атрибута-заполнителя, который я определил, где я использовал директиву ( attr (заполнитель)). Еще одним ключевым фактором является указатель-события: отсутствует - это позволяет нажимать на текст заполнителя, чтобы перейти к выбору. В противном случае это не будет выпадать, если пользователь нажимает на текст.

добавить .пусто класс сам в моей директиве select, но обычно я нахожу, что angular добавляет / удаляет. ng-пустой для меня (я предполагаю, что это b / c я впрыскиваю версию 1.2 Angular в моем примере кода)

(в Примере также показано, как обернуть HTML-элементы в angularJS для создания собственных пользовательских входов)

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>

вы можете сделать это без использования 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>

Я хотел, чтобы выбор был серым, пока не выбран так для этого фрагмента 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, возможно, и в других браузерах, но я не проверял.

Я не мог заставить ни один из них работать в настоящее время, потому что для меня это (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>

попробуйте это для разнообразия

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

вход [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>

Я не довольствуюсь только решениями HTML / CSS, поэтому я решил создать пользовательский select С помощью JS.

это то, что я написал в последние 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>

обновление: я улучшил этот (выбор с помощью клавиш up/down/enter). Немного прибрался на выходе и превратил это в объект. Текущий объем производства:

<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 (переименован).


обновление: снова переписан. Вместо того, чтобы использовать список, мы можем просто использовать Select. Таким образом, он будет работать даже без JS (в случае, если это нетрудоспособный.)

вход:

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

Если вы используете угловой идти так

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

пользователь не должен видеть заполнитель в select options. Я предлагаю использовать 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>

вот мой вклад. 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) чтобы сохранить заполнитель серым, когда он открывается, но мне было все равно что.

в отношении всех решений выше, но этот, кажется, наиболее действителен из-за спецификаций HTML:

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

обновление: Простите меня за этот неправильный ответ, это определенно не заполнитель решение для select элемент, но заголовок для сгруппированных параметров под открытым select список элемент.