web-dev-qa-db-fra.com

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

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

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

Cela fonctionne (place le smiley après "buu!" Et avant "encore")

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

Cela ne fonctionne pas - il colore certaines valeurs en rouge, mais il n’ya pas de smiley.

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

Qu'est-ce que je fais mal? dois-je utiliser un autre pseudo-sélecteur?

Remarque: Je ne peux pas ajouter une span autour de ma input car elle est générée par un contrôle tiers.

585
matra

:after et :before ne sont pas pris en charge dans Internet Explorer 7 et inférieur, sur aucun élément.

Il n'est également pas conçu pour être utilisé sur des éléments remplacés tels que éléments de formulaire (entrées) et éléments d'image.

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

Documents API sur .after

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

230
Alex

:before et :after rendent à l'intérieur d'un conteneur

et <input> ne peuvent pas contenir d'autres éléments.


Les pseudo-éléments ne peuvent être définis (ou mieux, ne sont pris en charge que) sur les éléments de conteneur. Parce que la manière 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, ils ne sont donc pas pris en charge. button d'autre part, c'est aussi un élément de formulaire qui les prend en charge, car c'est un conteneur d'autres sous-éléments.

Si vous me demandez si un navigateur ne affiche ces deux pseudo-éléments sur des éléments non conteneur, il s'agit d'un bogue et d'une conformité non standard. La spécification parle directement du contenu de l'élément ...

Spécification W3C

Si nous lisons attentivement la spécification elle indique en fait qu'ils sont insérés à l'intérieur d'un élément contenant:

Les auteurs spécifient le style et l'emplacement du contenu généré avec les pseudo-éléments: before et: after. 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', associée à ces pseudo-éléments, spécifie ce qui est inséré.

Voir? l'arborescence de documents d'un élément contenu. Si je comprends bien, cela signifie dans un conteneur.

1175
Robert Koritnik

Bizarrement, cela fonctionne avec certains types d’entrées. Au moins dans Chrome, 

<input type="checkbox" />

fonctionne bien, même chose que

<input type="radio" />

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

58
vals

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

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

Côté note, 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

35
CatalinBerta

Voici une autre approche (en supposant que vous maîtrisiez le HTML): ajoutez un <span></span> vide juste après l'entrée et ciblez-le dans CSS à l'aide de 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 ajoute automatiquement les classes .ng-invalid aux éléments de formulaire <input> et au formulaire, mais pas au <label>.

35
Blazemonger

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

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

28
Veiko Jääger

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

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

Pour que cela fonctionne dans d'autres navigateurs, utilisez :-moz-placeholder, ::-moz-placeholder et :-ms-input-placeholder dans différents sélecteurs . Impossible de regrouper les sélecteurs, car si un navigateur ne reconnaît pas le sélecteur, l'instruction entière est invalidée.

UPDATE: Le code ci-dessus ne fonctionne qu'avec les pré-processeurs CSS (SASS, LESS ...), sans pré-processeurs, utilisez:

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

J'ai trouvé ce poste car j'avais le même problème, c'était la solution qui fonctionnait pour moi. Plutôt que de remplacer la valeur de l'entrée, supprimez-la et placez absolument derrière elle une étendue de même taille, une pseudo-classe :before peut lui être appliquée avec la police 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
Morgan Feeney

Les pseudo-éléments tels que :after, :before ne concernent que les éléments de conteneur. Les éléments commençant et fermant à un seul endroit, comme <input/>, <img>, etc., ne sont pas des éléments de conteneur. Les pseudo-éléments ne sont donc pas pris en charge. Une fois que vous appliquez un pseudo-élément à un élément conteneur tel que <div>, vous pouvez comprendre ce que je veux dire si vous inspectez le code (voir l’image). En réalité, 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>

 enter image description here

11
Pons Purushothaman

Une solution de travail en CSS pur:

L'astuce consiste à 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: 

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

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

11
user3114072

Selon un 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). Ceci sera défini plus en détail dans une spécification future. ”Bien que input ne soit plus un élément remplacé, la situation de base n'a pas changé: l'effet de :before et :after sur cet élément n'est pas spécifié et n'a généralement aucun effet.

La solution consiste à trouver une approche différente du problème que vous essayez de traiter 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 qu'il fait partie de la valeur initiale du contrôle, mais il ne peut pas être modifié - il semblerait donc que ce soit forcé au début de la commande. contrôle, mais il ne serait pas encore soumis avec les données du formulaire.

4
Jukka K. Korpela

Comme d'autres l'ont expliqué, les inputs sont des éléments void un peu remplacés, aussi la plupart des navigateurs ne vous permettent-ils pas de générer des pseudo-éléments ::before et ::after.

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

De https://lists.w3.org/Archives/Public/www-style/2016mar/0190.html ,

Safari et Chrome autorisent tous les deux des pseudo-éléments sur leurs entrées de formulaire . Les autres navigateurs n'en ont pas. Nous avons cherché à supprimer cela, mais le use-counter enregistre ~ .07% des pages qui l'utilisent, soit 20x notre max seuil d'élimination.

Spécifier réellement des pseudo-éléments sur des 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 à faire encore (et je ne suis pas sûr que nous * pouvons * faire). Mais Boris suggéré, dans l’un des bugthreads, le permettant sur l’apparence: aucun entrées - en les transformant simplement en <div> s, plutôt que éléments "un peu remplacés".

4
Oriol

essayez ensuite:

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

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 avant sur le div de l'emballage d'une entrée et le place ensuite dans l'entrée - ou du moins, il lui ressemble. Évidemment, c’est un moyen de contourner le problème, mais efficace à la rigueur et qui se prête à la réactivité. Vous pouvez facilement en faire un après si vous avez besoin de mettre un autre contenu.

Travailler Fiddle

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

Le 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
Kapunahele Wong

Si vous essayez de styler un élément d’entrée avec: before et: after, vous tentez probablement de imiter les effets d’autres span, div ou même d’un élément de votre pile CSS.

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

CEPENDANT, HTML 5 a introduit l’élément button qui est un conteneur et se comporte comme un élément input [type = "submit | reset"].

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

:before et :after ne fonctionnent que pour les nœuds pouvant avoir des nœuds enfants car ils insèrent un nouveau nœud en tant que premier ou dernier nœud.

1
Juan Mendes

Résumé

Cela ne fonctionne pas avec <input type="button">, mais cela fonctionne bien avec <input type="checkbox">.

Fiddle: 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
K48

J'ai trouvé que tu peux le faire comme ça:

.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 padding et le: after . Le premier parent doit être relatif et le second div doit être absolu pour que vous puissiez définir la position de after.

0
Patrick

Le plus grand malentendu ici est la signification des mots before et after. Ils ne pas font référence à l'élément lui-même, mais au contenu de l'élément. Donc, element:before est avant le contenu, et element:after est après le contenu, mais les deux sont toujours à l'intérieur de l'élément d'origine.

L'élément input n'a pas de contenu dans la vue CSS et n'a donc pas de pseudo contenu :before ou :after. Cela est vrai de nombreux autres éléments vides ou remplacés.

Il n'y a pas de pseudo élément faisant référence à outside l'élément.

Dans un autre univers, ces pseudo-éléments auraient peut-être été appelés autre chose pour clarifier cette distinction. Et quelqu'un aurait même pu proposer un pseudo élément qui est réellement en dehors de l'élément. Jusqu'à présent, ce n'est pas le cas dans cet univers.

0
Manngo

Vous pouvez utiliser les éléments after ou before de votre bloc parent avec jQuery .

$(yourInput).parent().addClass("error-form-field");
0
Dima Dulin