Comment styler pour chaque navigateur

Pour l'instant, seuls Firefox et Webkit (Safari/Chrome) permettent de styler le placeholder. Évidemment, chacun le fait différemment. Et aucun des deux n'est pérenne, puisqu'ils en parlent sur www-style.

Voyons tout de même comment ça fonctionne.

Dans Firefox (à partir de la version 4)

Firefox propose une pseudo-classe qui s'appelle -moz-placeholder. On peut lire sa documentation sur le Mozilla Developer Network. On l'utilise simplement de la manière suivante :

input:-moz-placeholder, textarea:-moz-placeholder {
    color: red;
}

Par défaut, Firefox utilise la valeur graytext qui correspond à #B1A594[1].

Dans Webkit

Avec Webkit, on nous propose cette fois un pseudo-élément -webkit-input-placeholder. On l'utilise de la manière suivante :

input::-webkit-input-placeholder, textarea::-webkit-input-placeholder {
    color: red;
}

La valeur par défaut est darkGray qui correspond à #A9A9A9[2].

Premier problème : écrasement des styles navigateurs avec Firefox

Ça a été ma première surprise, et cela arrive uniquement dans Firefox. Si on spécifie un style pour les balises input, il écrase dans Firefox le style spécifique du placeholder !

Ainsi, lorsqu'on utilise le simple code suivant, les placeholders ne sont plus différemment stylés !

input {
  color: blue;
}

L'explication de ce comportement n'est pas si simple, puisqu'il faut tenir compte de plusieurs paramètres :

  • Tout d'abord, puisqu'on utilise une pseudo-classe, le style du placeholder par défaut s'applique à l'élément input lui-même.
  • Ensuite, comme décrit dans la spécification CSS2, les règles définies dans la page par l'auteur sont plus prioritaires que les règles par défaut du navigateur.
  • Ainsi, c'est bien la règle de l'auteur qui est utilisée, quand bien même sa spécificité est plus faible !

Je n'ai pas trouvé d'autre solution que de redéfinir un style pour le placeholder...

Second problème : on ne peut pas mixer les sélecteurs pour Firefox et les sélecteurs pour Webkit

Bêtement, je me suis dit qu'on pourrait cumuler les 2 sélecteurs dans la même règle, ainsi :

input:-moz-placeholder, textarea:-moz-placeholder,
input::-webkit-input-placeholder, textarea::-webkit-input-placeholder {
    color: red;
}

Mais en fait, ça ne fonctionne pas ! La règle est ignorée par les deux navigateurs ! L'explication la plus plausible, c'est que lorsqu'un navigateur rencontre une pseudo-classe ou un pseudo-élément qu'il ne comprend pas, il ignore l'ensemble du sélecteur.

Il faut donc répéter la règle, comme ceci :

input:-moz-placeholder, textarea:-moz-placeholder {
    color: #555;
}
 
input::-webkit-input-placeholder, textarea::-webkit-input-placeholder {
    color: #555;
}

Heureusement, les styles pour les placeholders seront généralement bien courts.

Une implémentation pour les navigateurs plus anciens ?

Une recherche rapide m'a amené sur le plugin jQuery Enable Placeholder qui remplit bien sa fonction. Il permet aussi de styler le texte du placeholder en utilisant une classe, qui est la classe placeholder par défaut.

On met tout bout à bout

Voici donc le CSS final utilisé dans mon projet :

input, textarea {
    color: #333;
}
 
input:-moz-placeholder, textarea:-moz-placeholder {
    color: #555;
}
 
input::-webkit-input-placeholder, textarea::-webkit-input-placeholder {
    color: #555;
}
 
input.placeholder, textarea.placeholder {
    color: #555;
}

Surtout, si vous avez des commentaires sur ce que je raconte là, n'hésitez pas !

Notes

[1] en tout cas sur mon Linux; est-ce différent ailleurs ?

[2] encore une fois, testé chez moi sur Chromium.