Comment créer un espace réservé pour une boîte de sélection?

1543

J'utilise des espaces réservés pour les entrées de texte, ce qui fonctionne très bien. Mais j'aimerais également utiliser un espace réservé pour mes boîtes de sélection. Bien sûr, je peux simplement utiliser ce code:

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

Mais le "Sélectionnez votre option" est en noir au lieu de gris clair. Donc, ma solution pourrait éventuellement être basée sur CSS. jQuery est très bien aussi.

Cela ne fait que griser l'option dans la liste déroulante (donc après avoir cliqué sur la flèche):

option:first {
    color: #999;
}

La question est: comment les gens créent-ils des espaces réservés dans des boîtes de sélection? Mais il a déjà été répondu, applaudissements.

Et en utilisant cela, la valeur sélectionnée est toujours grise (même après avoir sélectionné une option réelle):

select {
    color: #999;
}
Thomas
la source
1
Juste au cas où quelqu'un lirait ceci - j'ai publié une solution plus courante pour les navigateurs modernes avec une validation intégrée du navigateur. Bienvenue à l'année 2020;)
Jurik

Réponses:

2975

Une réponse non CSS - pas de JavaScript / jQuery:

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

David
la source
134
Firefox (10) n'affiche pas une option désactivée comme sélection par défaut (espace réservé). Il montre le suivant par défaut, dans ce cas "Durr".
jarnoan
53
J'ajoute généralement à la fois désactivé et sélectionné. Semble également fonctionner dans FF.
nilskp
11
<select> <option value="" disabled selected>Select your option</option> </select>
kolypto
183
La raison pour laquelle ce n'est pas la bonne réponse est parce que (je crois) le demandeur veut que la sélection soit grise jusqu'à ce qu'une autre valeur ait été sélectionnée. Cette réponse rend l'option grise dans la liste déroulante; mais pas l'élément select.
Bill
22
sélectionnez {option [désactivé] {affichage: aucun; }}
Dimael Vertigo
822

Je suis juste tombé sur cette question, et voici ce qui fonctionne dans Firefox et Chrome (au moins):

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

L' option Désactivé arrête d' <option>être sélectionnée à la fois avec la souris et le clavier, tandis que le simple fait d'utiliser 'display:none'permet à l'utilisateur de toujours sélectionner via les flèches du clavier. Le 'display:none'style rend simplement la zone de liste «belle».

Remarque: L'utilisation d'un valueattribut vide sur l'option "espace réservé" permet à la validation (attribut requis) de contourner le fait d'avoir "l'espace réservé", donc si l'option n'est pas modifiée, mais est requise, le navigateur doit inviter l'utilisateur à choisir une option de la liste.

Mise à jour (juillet 2015):

Il est confirmé que cette méthode fonctionne dans les navigateurs suivants:

  • Google Chrome - v.43.0.2357.132
  • Mozilla Firefox - v.39.0
  • Safari - v.8.0.7 (l'espace réservé est visible dans la liste déroulante, mais il n'est pas sélectionnable)
  • Microsoft Internet Explorer - v.11 (l'espace réservé est visible dans la liste déroulante mais n'est pas sélectionnable)
  • Project Spartan - v.15.10130 (l'espace réservé est visible dans la liste déroulante, mais il n'est pas sélectionnable)

Mise à jour (octobre 2015):

J'ai supprimé l' style="display: none"attribut en faveur de HTML5 hiddenqui a un large soutien. L' hiddenélément a des traits similaires à ceux display: nonede Safari, Internet Explorer, (Project Spartan doit être vérifié) où le optionest visible dans la liste déroulante, mais il n'est pas sélectionnable.

Mise à jour (janvier 2016):

Lorsque l' selectélément est, requiredil permet d'utiliser la :invalidpseudo-classe CSS qui vous permet de styliser l' selectélément lorsqu'il est dans son état "espace réservé". :invalidfonctionne ici en raison de la valeur vide dans l'espace réservé option.

Une fois qu'une valeur a été définie, la :invalidpseudo-classe sera supprimée. Vous pouvez également éventuellement utiliser :validsi vous le souhaitez.

La plupart des navigateurs prennent en charge cette pseudo-classe. Internet Explorer 10 et versions ultérieures. Cela fonctionne mieux avec des selectéléments de style personnalisé ; dans certains cas, c'est-à-dire (Mac dans Chrome / Safari), vous devrez modifier l'apparence par défaut de la selectboîte afin que certains styles s'affichent, c'est-à-dire background-coloret color. Vous pouvez trouver des exemples et plus sur la compatibilité sur developer.mozilla.org .

Apparence d'élément natif Mac dans Chrome:

Cochez la case Mac natif dans Chrome

Utilisation de l'élément de bordure modifié Mac dans Chrome:

Boîte de sélection modifiée Mac dans Chrome

William Isted
la source
5
@jaacob Dans les navigateurs que j'ai testés, le style 'display: none' cache le "Veuillez choisir" dans la liste, ce qui le rend plus joli.
William Isted
38
Il est important de noter qu'une option désactivée ne peut pas être re-sélectionnée: si la sélection est obligatoire, c'est ok - mais pas si la sélection est facultative.
Robert Mark Bram
2
Explorer11 ignore le display:nonestyle.
T30
1
Félicitations à @MattW pour avoir travaillé bien :invalidavant moi.
William Isted
3
Vous pouvez également ajouter une règle pour "réinitialiser" colorles options de prise en charge des navigateurs comme dans ce violon . Cela contribuerait à renforcer le fait que le disbled optionest un espace réservé. (Edit: Je vois que MattW a déjà couvert cela dans sa réponse)
Shaggy
251

Pour un champ obligatoire, il existe une solution purement CSS dans les navigateurs modernes:

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>

MattW
la source
7
Incroyable - c'était la réponse en bas (sans aucun vote positif) qui était la plus simple et fonctionnait parfaitement. Merci! Espérons que cette réponse atteindra le sommet.
Dan Nissenbaum
2
@DanNissenbaum J'étais très en retard dans le jeu, en plus il a besoin de ça requiredpour fonctionner donc c'est inutile si vous voulez que le champ soit optionnel.
MattW
1
En passant, le :requiredsélecteur n'est pas pris en charge dans IE8 et les versions antérieures. Le :invalidsélecteur n'est pas pris en charge dans IE9 et versions antérieures. quirksmode.org/css/selectors
Matt Wagner
4
Pas de solution pour une sélection non requise?
user3494047
1
@ user3494047 pas avec cette approche - la requiredcondition est ce qui amène le navigateur à appliquer la :invalidpseudo-classe lorsque l'espace réservé est sélectionné. [value=""]ne fonctionnera pas comme un remplacement car ce qui est mis à jour par l'interaction de l'utilisateur est la propriété value mais cette syntaxe CSS fait référence à un attribut (inexistant) .
MattW
105

Quelque chose comme ça:

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

Exemple de travail: http://jsfiddle.net/Zmf6t/

Albireo
la source
8
c'est exactement ce que j'ai fait récemment. mais j'ai ajouté un gestionnaire de touches afin que le changement se produise également lorsqu'une option est sélectionnée via le clavier (en utilisant les flèches ou les raccourcis des lettres) jsfiddle.net/Zmf6t/131
Radu
cela m'a mis sur la bonne voie ... mais j'ai fait la valeur = "" (rien entre les guillemets) de sorte que lorsque le bouton soumettre a été cliqué, il n'a toujours pas validé la première option et une fenêtre contextuelle du navigateur apparaît pour vous informer pour sélectionner une option ... merci @Albireo
Craig Wayne
Pourquoi avez-vous appelé explicitement la fonction de changement.
Forever
@Foreever parce que j'ai défini la classe CSS dans le gestionnaire d'événement change de la sélection, donc si vous ne déclenchez pas manuellement l'événement lorsque le contrôle est créé, le style n'est pas appliqué (il ne sera appliqué que lorsque l'utilisateur modifie manuellement la valeur).
Albireo
Cela ne fonctionne pas sur JQeury 3.4.1
geobudex
45

Je viens d'ajouter un attribut caché dans un optioncomme ci-dessous. Cela fonctionne bien pour moi.

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

Ajithkumar S
la source
2
Juste pour mémoire, cela ne fonctionne pas pour moi (Chrome sur Win10).
Chris Rae
Mais vous ne pouvez pas le supprimer. Vous finissez par en choisir un, mais vous ne pouvez pas réinitialiser si vous changez d'avis.
Thielicious
Ouais! Mais dans le formulaire, l'utilisateur doit de toute façon sélectionner l'une de ces options. Si ce n'est pas un champ obligatoire, supprimez l'attribut caché.
Ajithkumar S
35

La solution ci-dessous fonctionne également dans Firefox, sans 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>

Dani-Br
la source
26

J'ai eu le même problème et pendant la recherche, je suis tombé sur cette question, et après avoir trouvé une bonne solution pour moi, je voudrais la partager avec vous au cas où quelqu'un pourrait en bénéficier.

C'est ici:

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

Une fois que le client a fait la première sélection, il n'y a plus besoin de couleur grise, donc le code JavaScript supprime la classe place_holder.

Grâce à @ user1096901, comme solution de contournement pour le navigateur Internet Explorer, vous pouvez à nouveau ajouter la place_holderclasse au cas où la première option serait à nouveau sélectionnée :)

rramiii
la source
2
Dans certains navigateurs, il peut toujours sélectionner l'affichage: aucune option, car il n'est pas masqué.
Srneczek
La solution consiste à ajouter à nouveau la classe "place_holder" au cas où la première option est sélectionnée :)
rramiii
23

Il n'y a aucun besoin de JavaScript ou CSS, juste trois attributs:

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

Il ne montre pas du tout l'option; il définit simplement la valeur de l'option comme valeur par défaut.

Cependant, si vous n'aimez tout simplement pas un espace réservé de la même couleur que le reste , vous pouvez le corriger en ligne comme ceci:

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

De toute évidence, vous pouvez séparer les fonctions et au moins le CSS de la sélection dans des fichiers séparés.

Remarque: la fonction onload corrige un bogue de rafraîchissement.

Jacob Schneider
la source
Cela ne fonctionne pas si l'option cachée est la seule
Eridanis
mais pourquoi auriez-vous un menu déroulant avec une seule option?
Jacob Schneider
J'ai une fenêtre contextuelle à onglets et le menu déroulant de tab3 prend l'entrée de tab2, qu'il affiche. Votre réponse est bonne et c'est un cas d'angle, mais je m'attendais à ce que la valeur par défaut apparaisse comme première option, à la place, vous obtenez une liste déroulante vide. Voir ici: jsfiddle.net/n66L7sza
Eridanis
C'est un bon point, auquel cas vous pouvez scanner la longueur de la liste déroulante, si elle est nulle, puis supprimer l'attribut caché
Jacob Schneider
Cela ne semble pas fonctionner correctement sur Google Chrome 65.0.3325.181 sur MacOS, il n'affiche pas l'entrée cachée et choisit celle en dessous.
Jamie H
19

L'utilisateur ne doit pas voir l'espace réservé dans les options sélectionnées. Je suggère d'utiliser l' hiddenattribut pour l'option d'espace réservé, et vous n'avez pas besoin de l' selectedattribut pour cette option. Vous pouvez simplement le mettre en premier.

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>

Roman Yakoviv
la source
2
ou select:invalidest également valide.
elquimista
2
Je recommande celui-ci car il ne comporte pas le texte de l'espace réservé dans la liste, au moins dans Chrome.
JoeRaid
Notez que le style ne fonctionne pas sansrequired
akmalhakimi1991
18

Ici, j'ai modifié la réponse de David (réponse acceptée). Sur sa réponse, il a mis l'attribut désactivé et sélectionné sur la optionbalise, mais lorsque nous mettons également la balise cachée, cela sera beaucoup mieux.

En ajoutant un attribut caché supplémentaire sur la optionbalise, cela empêchera l'option "Sélectionnez votre option" d'être resélectionnée après que l'option "Durr" soit sélectionnée.

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

Nawaraj
la source
Merci pour la mise à jour, mais la réponse n'explique toujours pas pourquoi elle est différente. Par exemple, cette réponse empêche que l' option "Sélectionnez votre option" soit à nouveau sélectionnée après que l' option "Durr" est sélectionnée. Quel attribut provoque ce comportement?
bgran
16

Voici le mien:

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>

Will Wang
la source
Vous pouvez simplement ajouter <option value="" selected disabled>Please select</option>comme première option.
sstauross
Cela ne rend pas l'espace réservé gris clair.
Chloé
12

Je vois des signes de réponses correctes, mais pour tout rassembler, ce serait ma solution:

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>

user3520445
la source
8
Durrest en gris après l'avoir sélectionné. Cela force toujours la case de sélection fermée à être grise.
Chloé
9

Si vous utilisez Angular, procédez comme suit:

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

arun kumar
la source
Vous pouvez ajouter l' hiddenattribut afin que cette option ne s'affiche pas lors de l'ouverture de select. Mais merci pour cette réponse, ça a marché pour moi.
dcg
5

Cette HTML + CSSsolution a fonctionné pour moi:

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>

Bonne chance...

Akash
la source
Il ne semble pas fonctionner dans JQuery 3.4.1
geobudex
5

Une autre possibilité 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

Jean-philippe Emond
la source
4

J'adore la solution acceptée et elle fonctionne très bien sans JavaScript.

Je veux juste ajouter comment j'ai adopté cette réponse pour un composant React à sélection contrôlée , car il m'a fallu quelques essais pour le comprendre. Ce serait vraiment simple à intégrer react-selectet à en finir, mais à moins que vous n'ayez besoin des fonctionnalités incroyables de ce référentiel, ce que je n'ai pas pour le projet en question, il n'est pas nécessaire d'ajouter plus de kilo-octets à mon bundle. Note, react-selectpoignées dans des espaces réservés sélectionne grâce à un système complexe de divers inputset htmléléments.

Dans React, pour un composant contrôlé , vous ne pouvez pas ajouter l' selectedattribut à vos options. React gère l'état de la sélection via un valueattribut sur selectlui - même, avec un gestionnaire de changement, où la valeur doit correspondre à l'un des attributs de valeur dans les options elles-mêmes.

Tels que, par exemple

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

Puisqu'il serait inapproprié et en fait, une erreur serait ajoutée pour ajouter l' selectedattribut à l'une des options, que faire alors?

La réponse est simple une fois que vous y pensez. Puisque nous voulons que notre premier optionsoit selectedaussi bien que disabledet hidden, nous devons faire trois choses:

  1. Ajoutez l' attribut hiddenet disabledau premier défini option.
  2. Définissez la valeur du premier optioncomme une chaîne vide.
  3. Initialisez la valeur de selectpour être également une chaîne vide.
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>

Vous pouvez maintenant styliser la sélection comme indiqué ci-dessus (ou via un classNamesi vous préférez).

select:invalid { color: gray; }
wlh
la source
3

Espace [type="text"]réservé de style d' entrée pour les éléments sélectionnés

La solution suivante simule un espace réservé en ce qui concerne un input[type="text"]élément:

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

Grant Miller
la source
3

Je voulais que SELECT soit gris jusqu'à ce qu'il soit sélectionné, donc pour ce morceau de HTML:

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

J'ai ajouté ces définitions CSS:

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

Cela fonctionne comme prévu dans Chrome / Safari et peut-être aussi dans d'autres navigateurs, mais je n'ai pas vérifié.

fbparis
la source
3

Voici une solution CSS qui fonctionne à merveille. Le contenu est ajouté (et absolument positionné par rapport au conteneur) après l'élément conteneur ( via: après la pseudo-classe ).

Il tire son texte de l'attribut d'espace réservé que j'ai défini où j'ai utilisé la directive ( attr (espace réservé) ). Un autre facteur clé est les événements de pointeur: aucun - cela permet aux clics sur le texte de l'espace réservé de passer à la sélection. Sinon, il ne tombera pas si l'utilisateur clique sur le texte.

J'ajoute moi-même la classe .empty dans ma directive select, mais normalement je trouve que angular ajoute / supprime .ng-empty pour moi (je suppose que c'est parce que j'injecte la version 1.2 d'Angular dans mon exemple de code).

(L'exemple montre également comment encapsuler des éléments HTML dans AngularJS pour créer vos propres entrées personnalisées)

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>

prospectus
la source
3

Je n'ai pas pu faire fonctionner ces éléments pour le moment, car pour moi ce n'est (1) pas requis et (2) j'ai besoin de l'option pour revenir à la sélection par défaut. Voici donc une option lourde si vous utilisez 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>

Eric G
la source
Merci, c'était le meilleur pour moi, comme vous l'avez dit ... l'élément select est requis.
Mousa Alfhaily
3

Je ne me contente pas de solutions HTML / CSS uniquement, j'ai donc décidé de créer une personnalisation en selectutilisant JavaScript.

C'est quelque chose que j'ai écrit au cours des 30 dernières minutes, il peut donc être encore amélioré.

Tout ce que vous avez à faire est de créer une liste simple avec peu d'attributs de données. Le code transforme automatiquement la liste en une liste déroulante sélectionnable. Il ajoute également un caché inputpour contenir la valeur sélectionnée, de sorte qu'il peut être utilisé dans un formulaire.

Contribution:

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

Production:

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

Le texte de l'élément censé être un espace réservé est grisé. L'espace réservé est sélectionnable, au cas où l'utilisateur souhaite revenir sur son choix. En utilisant également CSS, tous les inconvénients de selectpeuvent être surmontés (par exemple, l'incapacité de styliser les options).


Mise à jour : j'ai amélioré cela (sélection en utilisant les touches haut / bas / entrée), j'ai rangé un peu la sortie et je l'ai transformée en objet. Sortie courant:

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

Initialisation:

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

Pour un examen plus approfondi: JSFiddle , GitHub (renommé).


Mise à jour: je l'ai réécrit. Au lieu d'utiliser une liste, nous pouvons simplement utiliser une sélection. De cette façon, cela fonctionnera même sans JavaScript (au cas où il serait désactivé).

Contribution:

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

Production:

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

akinuri
la source
2

Vous avez besoin d'une validation de formulaire et les navigateurs modernes le proposent à partir de zéro.

Il n'est donc pas nécessaire de veiller à ce que l'utilisateur ne puisse pas sélectionner le champ. Parce que quand il le fait, la validation du navigateur lui dira que c'est une mauvaise sélection.

Le navigateur intégré à la fonction de validation checkValidity () .

Bootstrap a également un bel exemple.

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
}
Jurik
la source
1

Vous pouvez le faire sans utiliser en Javascriptutilisant uniquement HTMLVous devez par défaut de jeu sélectionnez l' option disabled=""et selected=""puis sélectionnez balise required="".navigateur ne permet pas à l' utilisateur de soumettre le formulaire sans sélectionner une option.

<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>
Thusitha Wickramasinghe
la source
Cela provoque le grisé de l'ensemble de l'élément jusqu'à ce qu'une option soit choisie, provoquant ainsi un comportement potentiellement indésirable.
wickedchild
1

Dans Angular, nous pouvons ajouter une option comme espace réservé qui peut être masquée dans la liste déroulante des options. Nous pouvons même ajouter une icône de liste déroulante personnalisée en arrière-plan qui remplace l' icône de liste déroulante du navigateur .

L' astuce consiste à activer l'espace réservé css uniquement lorsque la valeur n'est pas sélectionnée

/ ** Mon modèle de composant * /

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

/ ** Mon composant.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;
    }
  }
}
Mukundhan
la source
1

Solution pour Angular 2

Créez une étiquette au-dessus de la sélection

<label class="hidden-label" for="IsActive"
    *ngIf="filterIsActive == undefined">Placeholder text</label>
<select class="form-control form-control-sm" type="text" name="filterIsActive"
    [(ngModel)]="filterIsActive" id="IsActive">
    <option value="true">true</option>
    <option value="false">false</option>
</select>

et appliquez CSS pour le placer sur le dessus

.hidden-label {
    position: absolute;
    margin-top: .34rem;
    margin-left: .56rem;
    font-style: italic;
    pointer-events: none;
}

pointer-events: none vous permet d'afficher la sélection lorsque vous cliquez sur l'étiquette, qui est masquée lorsque vous sélectionnez une option.

edu
la source
1

Voici ma contribution. 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;
}

Il est possible d'utiliser uniquement CSS en modifiant le code du serveur et en définissant uniquement les styles de classe en fonction de la valeur actuelle de la propriété, mais cette méthode semble plus simple et plus propre.

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

Vous pouvez ajouter plus de CSS ( select option:first-child) pour garder l'espace réservé gris lorsqu'il s'ouvre, mais je m'en fichais.

Chloe
la source
1

Essayez ceci pour un changement:

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

Voici un exemple pratique pour y parvenir avec du JavaScript pur qui gère la couleur des options après le premier clic:

<!DOCTYPE html>
<html>
  <head>
    <style>
      #myselect {
        color: gray;
      }
    </style>
  </head>

  <body>
    <select id="myselect">
      <option disabled selected>Choose Item
      </option>

      <option>Item 1
      </option>

      <option>Item 2
      </option>

      <option>Item 3
      </option>
    </select>

    <script>
      // Add event listener to change color in the first click
      document.getElementById("myselect").addEventListener("click", setColor)
      function setColor()
      {
        var combo = document.getElementById("myselect");
        combo.style.color = 'red';
        // Remove Event Listener after the color is changed at the first click
        combo.removeEventListener("click", setColor);
      }
    </script>
  </body>
</html>
jonathana
la source
1

En vous basant sur la réponse de MattW , vous pouvez rendre l'option de sélection d'espace réservé visible dans le menu déroulant après qu'une sélection valide a été effectuée, en la masquant conditionnellement uniquement pendant que l'espace réservé reste sélectionné (et la sélection est donc: non valide).

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>

Matthew Millar
la source
0

D'après la réponse d'Albireo , cette version n'utilise pas de jQuery et la spécificité CSS est meilleure.

const triggerEvent = (el, eventName) => {
  let event = document.createEvent('HTMLEvents')
  event.initEvent(eventName, true, false)
  el.dispatchEvent(event)
}

let select = document.querySelector('.placeholder-select')
select.addEventListener('change', (e) => {
  e.target.classList[e.target.value == 0 ? 'add' : 'remove']('empty')
})
triggerEvent(select, 'change')
.placeholder-select option {
  color: #000000;
}
.placeholder-select option:first-child {
  color: #444444;
  font-style: italic;
  font-weight: bold;
}
.placeholder-select.empty {
  color: #7F7F7F;
}
<select class="placeholder-select">
  <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>

M. Polywhirl
la source