Posso usare uno pseudo-elemento: before o: after su un campo di input?


687

Sto cercando di utilizzare lo :afterpseudo-elemento CSS su un inputcampo, ma non funziona. Se lo uso con un span, funziona bene.

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

Funziona (mette la faccina dopo "buu!" E prima di "ancora un po '")

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

Questo non funziona - colora solo alcuniValore in rosso, ma non c'è smiley.

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

Che cosa sto facendo di sbagliato? dovrei usare un altro pseudo-selettore?

Nota: non riesco ad aggiungere un in spangiro my input, perché viene generato da un controllo di terze parti.


Se avete assolutamente alcun controllo sul codice HTML, provare a cambiare la border-colordel inputposto. Trovo che attiri più attenzione.
Blazemonger,

Risposte:


256

:aftere :beforenon sono supportati in Internet Explorer 7 e versioni precedenti, su alcun elemento.

Inoltre, non è pensato per essere utilizzato su elementi sostituiti come elementi del modulo (input) ed elementi dell'immagine .

In altre parole, è impossibile con CSS puro.

Tuttavia, se si utilizza jquery è possibile utilizzare

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

Documenti API su .after

Per aggiungere i tuoi contenuti con JavaScript. Funzionerà su tutti i browser.


Alex, sto usando IE8 e l'ultimo FF, quindi IE7 non è un problema. Cercavo qualsiasi documentazione sulla limitazione di: after, ma non riuscivo a trovarla. w3.org/TR/CSS2/generate.html afferma che è inserito dopo il nodo corrente nella struttura del documento, quindi dovrebbe funzionare in entrambi i casi.
matra,

3
A meno che tu non stia costruendo la pagina solo per tuo uso, una grande percentuale di Internet usa ancora quei browser. Le specifiche del w3c dicono questo sì; ma come ben sai i browser implementano la propria interpretazione delle specifiche. Usando: after on un input funzionerà solo in Opera 9+, ma non è implementato in IE, FF, safari o chrome a causa del modo in cui costruiscono internamente il DOM - di nuovo non può essere fatto con CSS puro.
Alex

3
Non sono sicuro se questo era il caso nel mese di aprile, ma Webkit fa supporto :afterin generale, anche se non supporta sia :beforeo :aftersugli ingressi.
coreyward

258
Per quanto ho capito W3C :aftere :beforepseudo elementi, possono essere messi solo su elementi contenitore. Perché? Perché sono aggiunti all'interno di quel particolare elemento. inputnon è un contenitore. buttonper esempio è quindi puoi indossarli. Funziona come previsto. La specifica in realtà dice: prima e dopo il contenuto della struttura di documenti di un elemento Dice esplicitamente CONTENUTO . Quindi un elemento deve essere un contenitore.
Robert Koritnik,

29
La risposta successiva è decisamente migliore. Fornisce una vera ragione piuttosto che parlare di IE 7 (che se ne frega) e di jQuery (cattiva idea)
Rowan,

1305

:beforee :afterrendering all'interno di un contenitore

e <input> non può contenere altri elementi.


Gli pseudo-elementi possono essere definiti (o meglio detti solo supportati) sugli elementi contenitore. Perché il modo in cui sono resi è all'interno del contenitore stesso come elemento figlio. inputnon può contenere altri elementi quindi non sono supportati. A buttond'altra parte, anche questo è un elemento di modulo che li supporta, perché è un contenitore di altri sotto-elementi.

Se mi chiedete, se qualche navigatore fa visualizzare questi due pseudo-elementi su elementi non del contenitore, è un bug e una conformità non standard. Le specifiche parlano direttamente del contenuto degli elementi ...

Specifiche del W3C

Se leggiamo attentamente la specifica , in realtà dice che sono inseriti all'interno di un elemento contenente:

Gli autori specificano lo stile e la posizione del contenuto generato con gli pseudo-elementi: before e: after. Come indicano i loro nomi, gli pseudo-elementi: before e: after specificano la posizione del contenuto prima e dopo il contenuto dell'albero del documento di un elemento. La proprietà 'content', insieme a questi pseudo-elementi, specifica cosa viene inserito.

Vedere? contenuto dell'albero dei documenti di un elemento . A quanto ho capito, questo significa all'interno di un contenitore.


119
+1 Molto meglio della risposta accettata. Grazie per la chiara spiegazione dello standard stesso. Questo per quanto riguarda [required]::before { content "*"; color: red; }: P
Kevin Peno,

93
Suggerimento: se stai riscontrando il problema con un solo input di invio <input type="submit" value="Send"/>, usa <button type="submit">Send</button>invece. La presentazione è identica ma <button>è un contenitore e quindi supporta :beforee :after.
influenza

15
Che dire <hr />? Pensavo che non fosse un elemento contenitore, ma potrebbe renderlo :aftere :before jsfiddle.net/Uf88j/1
Deathlock

7
@deathlock: è davvero interessante. Direi che deve essere una specie di anomalia e non mi affiderei al fatto che funzioni tra browser o versioni incrociate ... HR non è un elemento contenitore quindi non dovrebbe consentire pseudo elementi. Anche lo standard W3C afferma che non consente alcun contenuto. E se si controlla per elemento vuoto si può vedere che questi elementi non dovrebbero avere alcun contenuto in qualsiasi circostanza. Gli pseudo elementi sono contenuti, quindi aspettati che la versione futura del browser non riesca a visualizzarli.
Robert Koritnik,

5
" : prima e: dopo il rendering all'interno di un contenitore " Gli pseudo elementi: prima e: dopo vengono " prima e dopo il contenuto ". Non "all'inizio o alla fine del" contenitore. La specifica non menziona un contenitore . Con tag come pe h1, il contenuto è all'interno del tag, quindi anche prima / dopo appaiono all'interno. Con elementi come inpute hr,: before e: after apparirebbe ancora prima o dopo il contenuto, ma non è coinvolto alcun contenitore (specialmente per input). input: controllato: prima è ampiamente usato per indicare le caselle di controllo che vengono controllate tramite CSS.
Radley Sustaire,

60

Stranamente, funziona con alcuni tipi di input. Almeno in Chrome,

<input type="checkbox" />

funziona bene, lo stesso di

<input type="radio" />

È solo type=texte alcuni altri che non funzionano.


1
@ANeves, ha funzionato in Chromium per me, ma non in Firefox.
kcpr

45

Ecco un altro approccio (supponendo che tu abbia il controllo dell'HTML): aggiungi un vuoto <span></span>subito dopo l'input e scegli come target quello nel CSSinput.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>

Sto usando questo approccio in AngularJS perché aggiungerà .ng-invalidautomaticamente le classi agli <input>elementi del modulo e al modulo, ma non al <label>.


1
Permette di aggiungere azioni hover, come: input:hover+span:after{color: blue}. Upvote.
Krassowski,

2
Perché questa risposta ha così pochi voti? Penso che la conoscenza teorica sia importante, ma questo risolve il problema.
jorgefpastor,

Bella opzione da seguire per risolvere il problema.
Jester,

40

:beforee :aftervengono applicati all'interno di un contenitore, il che significa che è possibile utilizzarlo per gli elementi con un tag di fine.

Non si applica agli elementi a chiusura automatica.

In una nota a margine, gli elementi che si chiudono automaticamente (come img / hr / input) sono anche noti come "elementi sostituiti", in quanto vengono sostituiti con i rispettivi contenuti. "Oggetti esterni" per la mancanza di un termine migliore. Una lettura migliore qui


Questa risposta è corretta, concisa e fornisce un contesto importante. Dovrebbe essere in cima, imo.
Paolo,

32

Ho usato il background-imageper creare il punto rosso per i campi obbligatori.

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

Visualizza su Codepen


21

Non puoi inserire uno pseudo elemento in un elemento di input, ma puoi inserire un elemento shadow, come un segnaposto!

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

Per farlo funzionare in altri browser, l'uso :-moz-placeholder, ::-moz-placeholdere :-ms-input-placeholder in diversi selettori . Non è possibile raggruppare i selettori, perché se un browser non riconosce il selettore invalida l'intera istruzione.

AGGIORNAMENTO : Il codice sopra riportato funziona solo con il pre-processore CSS (SASS, LESS ...), senza pre-processori usare:

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

3
Bello! Si noti che lo pseudo elemento segnaposto ha un supporto proprietà limitato: colore, sfondo, spaziatura parole, spaziatura lettere, decorazione testo, allineamento verticale, trasformazione testo, altezza linea, rientro testo, opacità. Vedi css-tricks.com/almanac/selectors/p/placeholder
henry

Grazie per il suggerimento. Basta ricordare che tutto all'interno dello pseudo-elemento scompare quando la casella di input viene compilata dall'utente. Questo è un problema UX se tutto ciò che volevi, come me, era mostrare un glyphicon-searchmarkup senza toccare.
Davi Lima,

2
Qualche contesto sul perché questo non funziona più: bugs.chromium.org/p/chromium/issues/detail?id=582301
Oliver Joseph Ash,

18

Pseudo elementi come :after, :beforesono solo per elementi contenitore. Gli elementi che iniziano e si chiudono in un unico posto come <input/>, <img>ecc. , Non sono elementi contenitore e quindi gli pseudo elementi non sono supportati. Una volta applicato uno pseudo elemento a un elemento contenitore simile <div>e se si controlla il codice (vedere l'immagine), è possibile capire cosa intendo. In realtà lo pseudo elemento viene creato all'interno dell'elemento contenitore. Questo non è possibile in caso di <input>o<img>

inserisci qui la descrizione dell'immagine


15

Una soluzione funzionante in puro CSS:

Il trucco è supporre che ci sia un elemento dom dopo il campo di testo.

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

(*) Soluzione limitata, tuttavia:

  • devi sperare che ci sia un seguente elemento dom,
  • devi sperare che nessun altro campo di input segua il tuo campo di input.

Ma nella maggior parte dei casi, conosciamo il nostro codice, quindi questa soluzione sembra efficiente e 100% CSS e 0% jQuery.


2
input#myTextField ~ span:before {molto meglio, ma span dovrebbe avere una classe davvero più esplicita come .ticko.icon
Val

13

Ho trovato questo post mentre stavo avendo lo stesso problema, questa era la soluzione che ha funzionato per me. A differenza della sostituzione del valore dell'input, basta rimuoverlo e posizionare assolutamente uno span dietro la stessa dimensione, lo span può avere una :beforepseudo classe applicata ad esso con il carattere icona di tua scelta.

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

1
+1: questa soluzione funziona bene se si utilizza un plug-in o un framework che aggiunge automaticamente classi di validazione all'elemento stesso, ma non all'etichetta principale.
Blazemonger,

9

Il più grande fraintendimento qui è il significato delle parole beforee after. Non si riferiscono all'elemento stesso, ma al contenuto nell'elemento. Lo stesso element:beforevale prima del contenuto e element:afterdopo il contenuto, ma entrambi sono ancora all'interno dell'elemento originale.

L' inputelemento non ha contenuto nella vista CSS e quindi non ha contenuto :beforeo :afterpseudo. Questo vale per molti altri elementi nulli o sostituiti.

Non esiste alcun pseudo elemento che si riferisce all'esterno dell'elemento.

In un universo diverso, questi pseudo elementi avrebbero potuto essere chiamati qualcos'altro per rendere più chiara questa distinzione. E qualcuno potrebbe anche aver proposto uno pseudo elemento che è veramente al di fuori dell'elemento. Finora, questo non è il caso in questo universo.


Potrei non capire cosa intendi, ma se lo faccio, gli pseudo elementi funzionano su h? jsfiddle.net/demetriad/o49yn5hq
Chris l'

1
@ Chris Questa è una sorpresa per me e per la ricerca, per alcuni altri. Penso che sia una stranezza. hrè sempre stato ambiguo dal punto di vista CSS, anche se lo vedi di più nella discussione del colore.
Manngo,

5

Secondo una nota nella specifica CSS 2.1, la specifica “non definisce completamente l'interazione di: before e: after con elementi sostituiti (come IMG in HTML). Questo sarà definito in modo più dettagliato in una specifica futura. " Sebbene inputnon sia più un elemento sostituito, la situazione di base non è cambiata: l'effetto di :beforee :aftersu di esso non è specificato e generalmente non ha alcun effetto.

La soluzione è trovare un approccio diverso al problema che stai cercando di affrontare in questo modo. Mettere il contenuto generato in un controllo di input di testo sarebbe molto fuorviante: per l'utente sembrerebbe essere parte del valore iniziale nel controllo, ma non può essere modificato, quindi sembrerebbe essere qualcosa di forzato all'inizio del controllo, ma non verrebbe inviato come parte dei dati del modulo.


3
Questo è un commento, non una risposta - un commento piuttosto lungo, ma comunque un commento.
Blazemonger,

@Blazemonger, non è del tutto chiaro quale fosse la domanda, ma in ogni caso, questa risposta risolve lo stesso problema della risposta accettata, ma in un modo più corretto. Non è impossibile utilizzare il contenuto generato per gli inputelementi, solo non specificato e dipendente dal browser.
Jukka K. Korpela,

5

Come altri hanno spiegato, inputs sono elementi vuoti in qualche modo sostituiti, quindi la maggior parte dei browser non ti consente di generare ::before::afterpseudo-elementi in essi.

Tuttavia, il gruppo di lavoro CSS sta prendendo in considerazione esplicitamente il permesso ::beforee, ::afternel caso, lo inputha fatto appearance: none.

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

Safari e Chrome consentono entrambi pseudo-elementi nei loro input di modulo. Gli altri browser no. Abbiamo cercato di rimuoverlo, ma il contatore degli usi sta registrando ~ .07% delle pagine che lo utilizzano, che è 20 volte la nostra soglia di rimozione massima.

La specifica effettiva degli pseudo-elementi sugli input richiederebbe di specificare almeno un po 'la struttura interna degli input, cosa che non siamo ancora riusciti a fare (e non sono sicuro di poter * fare *). Ma Boris ha suggerito, in uno dei bugthreads, di permetterlo in apparenza: nessuno input - fondamentalmente semplicemente trasformandoli in <div> s, piuttosto che elementi "sostituiti in qualche modo".


4

prova dopo:

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

Devi avere una sorta di wrapper attorno all'input per usare uno pseudo-elemento prima o dopo. Ecco un violino che ha un precedente sul div wrapper di un input e quindi posiziona il prima all'interno dell'input - o almeno sembra simile. Ovviamente, questo è un modo per aggirare ma efficace in un pizzico e si presta ad essere reattivo. Puoi farlo facilmente dopo aver bisogno di aggiungere altri contenuti.

Fiddle di lavoro

Simbolo del dollaro all'interno di un input come pseudo-elemento: http://jsfiddle.net/kapunahele/ose4r8uj/1/

HTML:

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

Il 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;
}

Bel trucco, ma potresti fare un div stilizzato per "continuare" l'input. Guarda questo violino jsfiddle.net/ose4r8uj/31 Ma potresti anche farlo più facilmente usando bootstrap: getbootstrap.com/css/#forms-control-validation cerca la parte "Con icone opzionali". Anche se, questo non ha nulla a che fare con la domanda originale.
Victor Ivens,

1
FYI non va bene per: focus
,:

2

Se stai cercando di modellare un elemento di input con: before e: after, le probabilità sono che stai cercando di imitare gli effetti di altri span, div o persino elementi nel tuo stack CSS.

Come sottolinea la risposta di Robert Koritnik,: prima e dopo possono essere applicati solo agli elementi contenitore e gli elementi di input non sono contenitori.

TUTTAVIA, HTML 5 ha introdotto l' elemento button che è un contenitore e si comporta come un 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>

HTML 4 ha effettivamente introdotto l'elemento <button>.
Mr Lister,

1

Sommario

Non funziona con <input type="button">, ma funziona bene con <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

:beforee :afterfunziona solo per i nodi che possono avere nodi figlio poiché inseriscono un nuovo nodo come primo o ultimo nodo.


0

Ho scoperto che puoi farlo in questo modo:

Devi avere un genitore div che prende il padding e il: after. Il primo genitore deve essere relativo e il secondo div deve essere assoluto in modo da poter impostare la posizione del dopo.


-1

Ho un'altra idea usare questo invece:

<div>
<input type="text"></input>text can be entered here</div>

L'autore della domanda ha dichiarato esplicitamente di non essere in grado di modificare il markup HTML. Questa risposta non ha senso. Probabilmente avrebbe dovuto essere ridimensionato anziché modificato, @Morpheus.
Palec,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.