¿Cómo hago un marcador de posición para un cuadro de "selección"?

1756

Estoy usando marcadores de posición para entradas de texto que están funcionando bien. Pero también me gustaría usar un marcador de posición para mis cuadros de selección. Por supuesto que puedo usar este código:

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

Pero el 'Seleccione su opción' está en negro en lugar de gris claro. Entonces mi solución posiblemente podría estar basada en CSS. jQuery también está bien.

Esto solo hace que la opción sea gris en el menú desplegable (después de hacer clic en la flecha):

option:first {
    color: #999;
}

La pregunta es: ¿Cómo crean las personas marcadores de posición en las casillas de selección? Pero ya ha sido respondido, salud.

Y usar esto da como resultado que el valor seleccionado siempre sea gris (incluso después de seleccionar una opción real):

select {
    color: #999;
}
1
  • 5
    En caso de que alguien lea esto, publiqué una solución más común para los navegadores modernos con la validación incorporada del navegador. Bienvenidos al año 2020;)Jurik 22/01/20 a las 10:03
3325

Una respuesta sin CSS, sin JavaScript / jQuery:

<select>
    <option value="" disabled selected>Select your option</option>
    <option value="hurr">Durr</option>
</select>
2
  • 151
    Firefox (10) no muestra una opción deshabilitada como la selección predeterminada (marcador de posición). Muestra el siguiente por defecto, en este caso "Durr". jarnoan 27/02/12 a las 12:12
  • Una vez que el usuario ha seleccionado un valor, no puede deseleccionarlo nuevamente (incluso cuando el valor seleccionado es opcional). Poul Bak 30 de julio a las 1:16
929

Me encontré con esta pregunta, y esto es lo que funciona en Firefox y Chrome (al menos):

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

La opción Desactivado detiene la <option>selección tanto con el mouse como con el teclado, mientras que el simple hecho de usar 'display:none'permite al usuario seguir seleccionando a través de las flechas del teclado. El 'display:none'estilo simplemente hace que el cuadro de lista se vea "agradable".

Nota: El uso de un valueatributo vacío en la opción "marcador de posición" permite la validación (atributo obligatorio) para evitar tener el "marcador de posición", por lo que si la opción no se cambia, pero es obligatoria, el navegador debe pedirle al usuario que elija una opción. de la lista.

Actualización (julio de 2015):

Se confirma que este método funciona en los siguientes navegadores:

  • Google Chrome: v.43.0.2357.132
  • Mozilla Firefox - v.39.0
  • Safari - v.8.0.7 (el marcador de posición es visible en el menú desplegable, pero no se puede seleccionar)
  • Microsoft Internet Explorer - v.11 (el marcador de posición está visible en el menú desplegable pero no se puede seleccionar)
  • Project Spartan - v.15.10130 (el marcador de posición es visible en el menú desplegable, pero no se puede seleccionar)

Actualización (octubre de 2015):

Quité el style="display: none"favor de HTML5 atributo hiddenque tiene un amplio apoyo. El hiddenelemento tiene características similares display: nonea las de Safari, Internet Explorer, (Project Spartan necesita verificación) donde optionestá visible en el menú desplegable, pero no se puede seleccionar.

Actualización (enero de 2016):

Cuando el selectelemento es required, permite el uso de la :invalidpseudoclase CSS que le permite diseñar el selectelemento cuando está en su estado de "marcador de posición". :invalidfunciona aquí debido al valor vacío en el marcador de posición option.

Una vez que se ha establecido un valor, la :invalidpseudoclase se eliminará. Opcionalmente también puede utilizar :validsi así lo desea.

La mayoría de los navegadores admiten esta pseudoclase. Internet Explorer 10 y posterior. Esto funciona mejor con selectelementos de estilo personalizado ; en algunos casos, es decir, (Mac en Chrome / Safari), deberá cambiar la apariencia predeterminada del selectcuadro para que se muestren ciertos estilos, es decir, background-colory color. Puede encontrar algunos ejemplos y más sobre compatibilidad en developer.mozilla.org .

Apariencia del elemento nativo Mac en Chrome:

Seleccione el cuadro nativo de Mac en Chrome

Usando el elemento de borde alterado Mac en Chrome:

Cuadro de selección alterado Mac en Chrome

0
280

Para un campo obligatorio, existe una solución de CSS puro en los navegadores modernos:

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

Algo como esto:

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();

Ejemplo de trabajo: http://jsfiddle.net/Zmf6t/

1
  • Esto funciona bien, cuando el valor de selección es opcional, el usuario puede deseleccionar nuevamente. Poul Bak 30 de julio a las 1:19
53

Acabo de agregar un atributo oculto en un me optiongusta a continuación. Está funcionando bien para mí.

<select>
  <option hidden>Sex</option>
  <option>Male</option>
  <option>Female</option>
</select>
2
  • 2
    asombroso, el más simple! Foggy Minded Greenhorn 24 de junio a las 13:55
  • Una vez que el usuario ha seleccionado un valor, no puede deseleccionarlo nuevamente (incluso cuando el valor seleccionado es opcional). Poul Bak 30 de julio a las 1:21
41

La siguiente solución también funciona en Firefox, sin 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>
1
  • Una vez que el usuario ha seleccionado un valor, no puede deseleccionarlo nuevamente (incluso cuando el valor seleccionado es opcional). Poul Bak 30 de julio a las 1:21
26

Tuve el mismo problema y mientras buscaba me encontré con esta pregunta, y después de encontrar una buena solución para mí, me gustaría compartirla con ustedes en caso de que alguien pueda beneficiarse de ella.

Aquí está:

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");
});

Una vez que el cliente realiza la primera selección, no es necesario el color gris, por lo que el código JavaScript elimina la clase place_holder.

Gracias a @ user1096901, como solución alternativa para el navegador Internet Explorer, puede place_holdervolver a agregar la clase en caso de que se vuelva a seleccionar la primera opción :)

0
24

No hay necesidad de JavaScript o CSS, solo tres atributos:

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

No muestra la opción en absoluto; simplemente establece el valor de la opción como predeterminado.

Sin embargo, si simplemente no le gusta un marcador de posición que es del mismo color que el resto , puede arreglarlo en línea de esta manera:

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

Obviamente, puede separar las funciones y al menos el CSS de la selección en archivos separados.

Nota: la función de carga corrige un error de actualización.

0
22

El usuario no debería ver el marcador de posición en las opciones de selección. Sugiero usar el hiddenatributo para la opción de marcador de posición, y no necesita el selectedatributo para esta opción. Puedes ponerlo como el primero.

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>
1
  • Una vez que el usuario ha seleccionado un valor, no puede deseleccionarlo nuevamente (incluso cuando el valor seleccionado es opcional). Poul Bak 30 de julio a las 1:23
18

Aquí he modificado la respuesta de David (respuesta aceptada). En su respuesta, puso el atributo desactivado y seleccionado en la optionetiqueta, pero cuando también ponemos la etiqueta oculta, se verá mucho mejor.

Al agregar un atributo oculto adicional en la optionetiqueta, evitará que se vuelva a seleccionar la opción "Seleccione su opción" después de seleccionar la opción "Durr".

<select>
    <option value="" disabled selected hidden>Select your option</option>
    <option value="hurr">Durr</option>
</select>
0
dieciséis

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

Veo señales de respuestas correctas, pero para juntarlo todo, esta sería mi solución:

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

Si está utilizando Angular, haga lo siguiente:

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

Esta solución HTML + CSS funcionó para mí:

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

Esto funciona bien para mi:

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

Otra posibilidad en 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

5

Sobre la base de la respuesta de MattW , puede hacer que la opción de selección de marcador de posición sea visible en el menú desplegable después de que se haya realizado una selección válida, ocultándola condicionalmente solo mientras el marcador de posición permanece seleccionado (y, por lo tanto, la selección no es válida).

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

Puede establecer el color de la primera opción gray, establecer su visualización none, establecer el selectcolor de grayy agregarle un inputdetector de eventos que establezca su color 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>

Usando la customElementAPI:

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

    Array.from(this.children).forEach(function(el, i) {
      if (i !== 0) {
        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>
4

Me encanta la solución aceptada y funciona muy bien sin JavaScript.

Solo quiero agregar cómo adopté esta respuesta para un componente React de selección controlada , porque me tomó algunos intentos resolverlo. Sería realmente sencillo incorporarlo react-selecty terminar con él, pero a menos que necesite la increíble funcionalidad que proporciona este repositorio, que yo no tengo para el proyecto en cuestión, no hay necesidad de agregar más kilobytes a mi paquete. Tenga en cuenta que react-selectmaneja los marcadores de posición en selecciones a través de un complejo sistema de varios elementos inputsy html.

En React, para un componente controlado , no puede agregar el selectedatributo a sus opciones. React maneja el estado de la selección a través de un valueatributo sobre selectsí mismo, junto con un controlador de cambios, donde el valor debe coincidir con uno de los atributos de valor dentro de las propias opciones.

Como por ejemplo

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

Dado que sería incorrecto y de hecho arrojaría un error agregar el selectedatributo a una de las opciones, ¿entonces qué?

La respuesta es simple una vez que lo piensa. Como queremos que nuestro primero optionsea selectedtan bueno como disabledy hidden, tenemos que hacer tres cosas:

  1. Agregue el atributo hiddeny disabledal primero definido option.
  2. Establezca el valor del primero optionpara que sea una cadena vacía.
  3. Inicialice el valor de selectpara que también sea una cadena vacía.
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>

Ahora puede diseñar la selección como se indica arriba (o mediante a classNamesi lo prefiere).

select:invalid { color: gray; }
4

Necesita validación de formularios y los navegadores modernos ofrecen esto desde cero.

Por lo tanto, no es necesario que tenga cuidado de que el usuario no pueda seleccionar el campo. Porque cuando lo está haciendo, la validación del navegador le dirá que esta es una selección incorrecta.

El navegador incorpora la función de validación checkValidity () .

Bootstrap también tiene un buen ejemplo.

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

[type="text"]Marcador de posición de estilo de entrada para elementos seleccionados

La siguiente solución simula un marcador de posición en relación con un input[type="text"]elemento:

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

Quería que SELECT fuera gris hasta que se seleccionara para esta pieza de HTML:

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

Agregué estas definiciones de CSS:

select { color: grey; }
select:valid { color: black; }

Funciona como se esperaba en Chrome / Safari y tal vez también en otros navegadores, pero no lo he comprobado.

3

Aquí hay una solución CSS que funciona a la perfección. El contenido se agrega (y se posiciona absolutamente en relación con el contenedor) después del elemento contenedor (a través de: después de la pseudoclase ).

Obtiene su texto del atributo de marcador de posición que definí donde utilicé la directiva ( attr (marcador de posición) ). Otro factor clave son los eventos de puntero: ninguno : esto permite que los clics en el texto del marcador de posición pasen a la selección. De lo contrario, no se desplegará si el usuario hace clic en el texto.

Yo mismo agrego la clase .empty en mi directiva select, pero normalmente encuentro que angular agrega / elimina .ng-vacío para mí (supongo que es porque estoy inyectando la versión 1.2 de Angular en mi muestra de código).

(La muestra también demuestra cómo envolver elementos HTML en AngularJS para crear sus propias entradas personalizadas)

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

No pude hacer que ninguno de estos funcione actualmente, porque para mí (1) no es necesario y (2) necesito la opción para volver a la opción predeterminada seleccionable. Entonces, aquí hay una opción de mano dura si está usando 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>
0
3

No estoy satisfecho con las soluciones solo HTML / CSS, así que decidí crear una personalizada selectusando JavaScript.

Esto es algo que he escrito en los últimos 30 minutos, por lo que se puede mejorar aún más.

Todo lo que tiene que hacer es crear una lista simple con pocos atributos de datos. El código convierte automáticamente la lista en un menú desplegable seleccionable. También agrega un oculto inputpara contener el valor seleccionado, por lo que se puede usar en un formulario.

Aporte:

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

Producción:

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

El texto del elemento que se supone que es un marcador de posición está atenuado. El marcador de posición es seleccionable, en caso de que el usuario quiera revertir su elección. También utilizando CSS, selectse pueden superar todos los inconvenientes de (por ejemplo, la incapacidad del estilo de las opciones).

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

Actualización : he mejorado esto (selección usando las teclas arriba / abajo / enter), arreglé un poco la salida y lo convertí en un objeto. Salida de corriente:

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

Inicialización:

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

Para un examen más detallado: JSFiddle , GitHub (renombrado).


Actualización: he reescrito esto de nuevo. En lugar de usar una lista, podemos simplemente usar una selección. De esta manera, funcionará incluso sin JavaScript (en caso de que esté deshabilitado).

Aporte:

<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]);

Producción:

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

0
3

Vea esta respuesta:

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

Debido a la diversidad de estilos y funcionalidades entre las respuestas proporcionadas en este hilo, la siguiente tabla aclara el estilo y la lógica de formulario aplicable para cada una de las soluciones HTML, HTML + CSS y HTML + CSS + Javascript proporcionadas.

Tuve que usar formato de código porque las tablas no están permitidas en el marcado, por alguna razón.
Se proporcionará una tabla HTML utilizando el fragmento de código para evitar la restricción de la tabla.

He marcado esta publicación community wikipara que cualquiera pueda detallar las nuevas publicaciones, aunque agregue JQuery, React, Angular, CoffeeScript, etc., a una publicación alternativa para mantener esta tabla simple.

         | 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:invalid{Grey} |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
8442831  | Yes |   No   | Grey  |   Invalid   | Black |      Yes       | Invisible  |    N/A     |  N/A  |          No           | Black | select:invalid{Grey} |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
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:valid{visible} | Black |          No          |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
44406771 | Yes |   No   | Grey  |   Invalid   | Grey  |      No        |  Visible   |     No     | Grey  |          No           | Black | select:invalid{Grey} |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
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          |
3

Esto se puede hacer sin necesidad de utilizar JavaScript y utilizando sólo HTML que necesita para establecer la opción de selección por defecto disabled=""y selected=""y seleccione la etiqueta required="".navegadores no permiten al usuario enviar el formulario sin seleccionar una opción.

<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>
0
1
 <select>
    <option disabled selected hidden>Please Choose...</option>
    <option>One</option>
    <option>Two</option>
</select>
3
  • Debe proporcionar algo de contexto para explicar en qué se diferencia su respuesta de la aceptadaFederico 16 de agosto a las 9:19
  • está usando solo una etiqueta de selección sin JQuery ni CSS. usar atributo Deshabilitado, seleccionado y ocultoPriya Maheshwari 16 de agosto a las 10:20
  • El punto es ayudar a alguien que no conoce estos atributos. Por lo general, no se acepta bien en Stack Overflow una respuesta que simplemente descarga el código sin explicaciones. Federico 17 de agosto a las 8:02
0

En Angular podemos agregar una opción como marcador de posición que se puede ocultar en el menú desplegable de opciones. Incluso podemos agregar un ícono desplegable personalizado como fondo que reemplaza el ícono desplegable del navegador .

El truco consiste en habilitar css de marcador de posición solo cuando el valor no está seleccionado

/ ** Mi plantilla de componente * /

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

/ ** Mi Component.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;
    }
  }
}