Puis-je utiliser un pseudo-élément: before ou: after sur un champ de saisie?

J'essaie d'utiliser le pseudo-élément :after css sur un champ input, mais cela ne fonctionne pas. Si je l'utilise avec un span, cela fonctionne bien.

<style type="text/css">
.mystyle:after {content:url(smiley.gif);}
.mystyle {color:red;}
</style>

Cela fonctionne (met le smiley après "buu!"et avant "un peu plus")

<span class="mystyle">buuu!</span>a some more

Cela ne fonctionne pas - il ne colore que someValue en rouge, mais il n'y a pas de smiley.

<input class="mystyle" type="text" value="someValue">

Ce que je fais mal? dois-je utiliser un autre pseudo-sélecteur?

Note: Je ne peux pas ajouter un span autour de mon input, car il est généré par un tiers contrôle.

558
demandé sur BoltClock 2010-04-06 23:28:08

19 réponses

:after et :before ne sont pas pris en charge dans Internet Explorer 7 et Sous, sur tous les éléments.

Il n'est pas non plus destiné à être utilisé sur des éléments remplacés tels que form elements (inputs) et image elements.

En d'autres termes, c'est impossible avec du CSS pur.

Cependant, si vous utilisez jquery Vous pouvez utiliser

$(".mystyle").after("add your smiley here");

API docs sur .après

Pour ajouter votre contenu avec javascript. Cela fonctionne sur tous les navigateurs.

227
répondu Alex 2015-09-28 00:14:36

:before et :after rendent dans un conteneur

Et ne peut pas contenir d'autres éléments.


Les Pseudo-éléments ne peuvent être définis (ou mieux, ne sont pris en charge) que sur des éléments de conteneur. Parce que la façon dont ils sont rendus est dans le conteneur lui-même en tant qu'élément enfant. input ne peut pas contenir d'autres éléments, donc ils ne sont pas pris en charge. Un button d'autre part c'est aussi un élément de formulaire soutient, car c'est un contenant d'autres sous-éléments.

Si vous me demandez, si un navigateur affiche ces deux pseudo-éléments sur des éléments non-conteneurs, c'est un bug et une conformité non standard. La spécification parle directement du contenu de l'élément...

Spécifications W3C

Si nous lisez attentivement la spécification, il dit qu'ils sont insérés dans un élément contenant:

Les auteurs spécifient le style et l'emplacement du contenu généré avec :before et :après les pseudo-éléments. Comme leurs noms l'indiquent, les pseudo-éléments :before Et: after spécifient l'emplacement du contenu avant et après le contenu de l'arborescence de documents d'un élément. La propriété' content', en conjonction avec ces pseudo-éléments, spécifie ce qui est inséré.

Tu vois? arbre de document d'un élément contenu. Si je comprends bien, cela signifie dans un conteneur.

1129
répondu Robert Koritnik 2016-11-07 22:54:09

Curieusement, cela fonctionne avec certains types d'entrée. Au moins en Chrome,

<input type="checkbox" />

Fonctionne bien, comme

<input type="radio" />

C'est juste type=text et d'autres qui ne fonctionnent pas.

55
répondu vals 2014-07-15 18:15:21

Voici une autre approche (en supposant que vous avez le contrôle du code HTML): ajoutez un <span></span> vide juste après l'entrée, et ciblez-le en CSS en utilisant input.mystyle + span:after

.field_with_errors {
  display: inline;
  color: red;
}
.field_with_errors input+span:after {
  content: "*"
}
<div class="field_with_errors">Label:</div>
<div class="field_with_errors">
  <input type="text" /><span></span> 
</div>

J'utilise cette approche dans AngularJS car elle ajoutera automatiquement des classes .ng-invalid aux éléments de formulaire <input>, et au formulaire, mais pas au <label>.

34
répondu Blazemonger 2016-03-07 15:07:45

:before et :after sont appliqués à l'intérieur d'un conteneur, ce qui signifie que vous pouvez l'utiliser pour les éléments avec une balise de fin.

Il ne s'applique pas aux éléments à fermeture automatique.

Sur une note de côté, les éléments à fermeture automatique (tels que img/hr/input) sont également appelés "éléments remplacés", car ils sont remplacés par leur contenu respectif. "Objets externes" pour l'absence d'un meilleur terme. Une meilleure lecture ici

30
répondu CatalinBerta 2017-05-24 07:18:55

J'ai utilisé le background-image pour créer le point rouge pour les champs requis.

input[type="text"][required] {
  background-image: radial-gradient(red 15%, transparent 16%);
  background-size: 1em 1em;
  background-position: top right;
  background-repeat: no-repeat
}

Vue sur Codepen

23
répondu Veiko Jääger 2017-01-25 13:24:19

Vous ne pouvez pas mettre un pseudo-élément dans un élément d'entrée, mais vous pouvez mettre un élément d'ombre, comme un espace réservé!

input[type="text"] {   
  &::-webkit-input-placeholder {
    &:before {
      // your code
    }
  }
}

Pour le faire fonctionner dans d'autres navigateurs, l'utilisation :-moz-placeholder, ::-moz-placeholder et :-ms-input-placeholder dans les différents sélecteurs. Impossible de regrouper les sélecteurs, car si un navigateur ne reconnaît pas le sélecteur invalide l'instruction entière.

UPDATE : le code ci-dessus ne fonctionne qu'avec le pré-processeur CSS (SASS, LESS...), sans pré-processeurs utiliser:

input[type="text"]::-webkit-input-placeholder:before { // your code }
22
répondu Shankar Cabus 2015-09-01 20:23:57

J'ai trouvé ce post car j'avais le même problème, c'était la solution qui a fonctionné pour moi. Au lieu de remplacer la valeur de l'entrée, supprimez-la et positionnez absolument une span derrière elle de la même taille, la span peut avoir une pseudo-classe :before appliquée avec la police d'icône de votre choix.

<style type="text/css">

form {position: relative; }
.mystyle:before {content:url(smiley.gif); width: 30px; height: 30px; position: absolute; }
.mystyle {color:red; width: 30px; height: 30px; z-index: 1; position: absolute; }
</style>

<form>
<input class="mystyle" type="text" value=""><span class="mystyle"></span>
</form>
13
répondu Morgan Feeney 2012-11-02 10:58:25

Une solution de travail en CSS pur:

L'astuce est de supposer qu'il y a un élément dom après le champ de texte.

/*
 * The trick is here:
 * this selector says "take the first dom element after
 * the input text (+) and set its before content to the
 * value (:before).
 */
input#myTextField + *:before {
  content: "";
} 
<input id="myTextField" class="mystyle" type="text" value="someValue" />
<!--
  There's maybe something after a input-text
  Does'nt matter what it is (*), I use it.
  -->
<span></span>

( * ) solution limitée, cependant:

  • Vous devez espérer qu'il y a un élément dom suivant,
  • Vous devez espérer qu'aucun autre champ de saisie ne suit votre champ de saisie.

Mais dans la plupart des cas, nous connaissons notre code donc cette solution semble efficace et 100% CSS et 0% jQuery.

6
répondu 2017-10-29 08:52:29

Pseudo éléments comme :after, :before sont uniquement pour les éléments de conteneur. Éléments commençant et se fermant dans un seul endroit comme <input/>, <img> etc ne sont pas des éléments de conteneur et donc les pseudo-éléments ne sont pas pris en charge. Une fois que vous appliquez un pseudo-élément à l'élément conteneur comme <div> et si vous inspectez le code (voir l'image), vous pouvez comprendre ce que je veux dire. En fait le pseudo-élément est créé à l'intérieur de l'élément conteneur. Ceci n'est pas possible dans le cas de <input> ou <img>

entrez la description de l'image ici

6
répondu Pons Purushothaman 2017-12-04 11:20:32

Selon une note dans la spécification CSS 2.1, la spécification " ne définit pas complètement l'interaction de: before et: after avec des éléments remplacés (tels que IMG en HTML). Cela sera défini plus en détail dans une spécification future."Bien que input ne soit plus vraiment un élément remplacé, la situation de base n'a pas changé: l'effet de :before et :after sur lui dans unspecified et n'a généralement aucun effet.

, La solution est de trouver une approche différente du problème que vous essayons d'aborder de cette façon. Mettre le contenu généré dans un contrôle de saisie de texte serait très trompeur: pour l'utilisateur, il semblerait faire partie de la valeur initiale du contrôle, mais il ne peut pas être modifié – il semblerait donc être quelque chose de forcé au début du contrôle, mais il ne serait pas soumis dans le cadre des données de formulaire.

4
répondu Jukka K. Korpela 2013-10-14 11:00:57

Comme d'autres l'ont expliqué, input s sont des éléments vides un peu remplacés, donc la plupart des navigateurs ne vous permettront pas de générer ::before Ni ::after pseudo-éléments en eux.

Cependant, le groupe de travail CSS envisage d'autoriser explicitement ::before et ::after dans le cas où le input a appearance: none.

À Partir de https://lists.w3.org/Archives/Public/www-style/2016Mar/0190.html,

Safari et Chrome autorisent tous deux des pseudo-éléments sur leurs entrées de formulaire. Les autres navigateurs ne le font pas. Nous nous sommes penchés sur la suppression de ce, mais les utilisation-compteur d'enregistrement ~.07% des pages qui l'utilisent, ce qui est 20x notre max seuil de suppression.

Spécifier réellement des pseudo-éléments sur les entrées nécessiterait de spécifier la structure interne des entrées au moins un peu, ce que nous n'avons pas réussi à le faire encore (et je ne suis pas confiant que nous * pouvons * faire). Mais Boris suggéré, dans l'un des bugthreads, permettant à l'apparence:aucun entrées-fondamentalement juste les transformer en S, plutôt que "kinda-remplacé" élément.

4
répondu Oriol 2016-03-17 22:47:49

Vous devez avoir une sorte de wrapper autour de l'entrée pour utiliser un pseudo-élément avant ou après. Voici un violon qui a un before sur le wrapper div d'une entrée, puis place le before à l'intérieur de l'entrée - ou du moins il ressemble à cela. Évidemment, c'est un travail autour mais efficace dans un pincement et se prête à être réactif. Vous pouvez facilement en faire un après si vous avez besoin de mettre un autre contenu.

Violon De Travail

Signe Dollar dans une entrée en tant que le pseudo-élément: http://jsfiddle.net/kapunahele/ose4r8uj/1/

Le code HTML:

<div class="test">
    <input type="text"></input>
</div>

Le CSS:

input {
    margin: 3em;
    padding-left: 2em;
    padding-top: 1em;
    padding-bottom: 1em;
    width:20%; 
}


.test {
    position: relative;
    background-color: #dedede;
    display: inline;
}

.test:before {
    content: '$';
    position: absolute;
    top: 0;
    left: 40px;
    z-index: 1;
}
3
répondu Kapunahele Wong 2014-12-19 15:25:23

Essayez suivant:

label[for="userName"] {
  position: relative;
}

label[for="userName"]::after {
  content: '[after]';
  width: 22px;
  height: 22px;
  display: inline-block;
  position: absolute;
  right: -30px;
}
<label for="userName">
	Name: 
	<input type="text" name="userName" id="userName">
	</label>
3
répondu Alex Ovchinkin 2016-11-06 10:04:20

Si vous essayez de styliser un élément d'entrée avec :before Et: after, il est probable que vous essayez de imiter les effets d'autres éléments span, div ou même a dans votre pile CSS.

Comme le souligne la réponse de Robert Koritnik,: before Et: after ne peuvent être appliqués qu'aux éléments de conteneur et les éléments d'entrée ne sont pas des conteneurs.

Cependant, HTML 5 a introduit l'élémentbutton qui est un conteneur et se comporte comme une entrée [type= " submit / reset"] élément.

    <style>
    .happy:after { content:url(smiley.gif); }
    </style>

    <form>
    <!-- won't work -->
    <input class="happy" type="submit" value="Submit" />

    <!-- works -->
    <button class="happy">Submit</button>
    </form>
1
répondu Kevin Conroy 2015-12-31 01:46:06

Résumé

, Il ne fonctionne pas avec <input type="button">, mais il fonctionne très bien avec <input type="checkbox">.

Violon: http://jsfiddle.net/gb2wY/50/

HTML:

<p class="submit">
    <input id="submit-button" type="submit" value="Post">
    <br><br>
    <input id="submit-cb" type="checkbox" checked>
</p>

CSS:

#submit-button::before,
#submit-cb::before {
    content: ' ';
    background: transparent;
    border: 3px solid crimson;
    display: inline-block;
    width: 100%;
    height: 100%;
    padding: 0;
    margin: -3px -3px;
}
1
répondu K48 2016-11-10 08:56:33

:before et :after ne fonctionne que pour les nœuds qui peuvent avoir des nœuds enfants puisqu'ils insèrent un nouveau nœud en tant que Premier ou dernier nœud.

1
répondu Juan Mendes 2017-02-10 13:42:05

J'ai trouvé que vous pouvez le faire comme ceci:

.submit .btn input
{
   padding:11px 28px 12px 14px;
   background:#004990;
   border:none;
    color:#fff;
}

 .submit .btn
 {
     border:none;
     color:#fff;
     font-family: 'Open Sans', sans-serif;
     font-size:1em;
     min-width:96px;
     display:inline-block;
     position:relative;
 }

.submit .btn:after
{
    content:">";
    width:6px;
    height:17px;
    position:absolute;
    right:36px;
    color:#fff;
    top:7px;
}
<div class="submit">
  <div class="btn">
     <input value="Send" type="submit" />
  </div>
</div>

Vous devez avoir un parent div qui prend le remplissage et le: after. Le premier parent doit être relatif et le second div doit être absolu afin que vous puissiez définir la position de l'après.

0
répondu Patrick 2015-07-12 13:07:44

Vous pouvez utiliser l'élément after ou before dans votre bloc parent avec jQuery. comme ceci:

$(yourInput).parent().addClass("error-form-field");
0
répondu Dima Dulin 2015-10-28 21:04:58