Czy mogę użyć pseudoelementu: before lub: after w polu wejściowym?

685

Próbuję użyć :afterpseudoelementu CSS na inputpolu, ale to nie działa. Jeśli używam go z span, działa OK.

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

To działa (umieszcza buźkę po „buu!” I przed „trochę więcej”)

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

To nie działa - tylko koloruje niektóreValue na czerwono, ale nie ma buźki.

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

Co ja robię źle? powinienem użyć innego pseudo-selektora?

Uwaga: nie mogę dodać spanwokół siebie input, ponieważ jest on generowany przez kontrolę innej firmy.

matra
źródło
Jeśli masz absolutnie żadnej kontroli nad HTML, spróbuj zmienić border-colorz inputzamiast. Uważam, że to przyciąga więcej uwagi.
Blazemonger

Odpowiedzi:

254

:afteri :beforenie są obsługiwane w Internet Explorerze 7 i niższych, na żadnych elementach.

Nie jest również przeznaczony do stosowania na zastąpionych elementach, takich jak elementy formularza (dane wejściowe) i elementy obrazu .

Innymi słowy jest to niemożliwe z czystym CSS.

Jednak jeśli używasz jquery , możesz użyć

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

Dokumenty API w .after

Aby dołączyć treść za pomocą javascript. Działa to we wszystkich przeglądarkach.

Alex
źródło
Alex, używam IE8 i najnowszego FF, więc IE7 nie stanowi problemu. Szukałem jakiejkolwiek dokumentacji dotyczącej ograniczenia: po, ale nie byłem w stanie jej znaleźć. w3.org/TR/CSS2/generate.html stwierdza, że ​​jest wstawiany po bieżącym węźle w drzewie dokumentów, więc powinien działać w obu przypadkach.
matra,
3
O ile nie budujesz strony wyłącznie na własny użytek, duży procent Internetu nadal korzysta z tych przeglądarek. Specyfikacja w3c mówi to tak; ale jak dobrze wiesz, przeglądarki implementują własną interpretację specyfikacji. Użycie: after na wejściu będzie działać tylko w Operze 9+, ale nie jest zaimplementowane w IE, FF, safari lub chrome ze względu na sposób, w jaki wewnętrznie konstruują DOM - ponownie nie można tego zrobić przy użyciu czystego CSS.
Alex
3
Nie jestem pewien, czy to było w kwietniu, ale Webkit obsługuje :afterw ogóle, choć nie obsługuje albo :beforeczy :afterna wejściach.
coreyward
258
O ile rozumiem W3C :afteri :beforepseudoelementy, można je umieszczać tylko na elementach kontenerowych. Dlaczego? Ponieważ są dołączone do tego konkretnego elementu. inputnie jest pojemnikiem. buttonna przykład dlatego możesz je założyć. Działa zgodnie z oczekiwaniami. Specyfikacja faktycznie mówi: przed i po zawartości drzewa dokumentu elementu Wyraźnie mówi TREŚĆ . Zatem element musi być kontenerem.
Robert Koritnik
29
Kolejna odpowiedź jest lepsze .. Daje rzeczywisty powód, zamiast mówić o IE 7 (kogo to obchodzi) i jQuery (zły pomysł)
Rowana
1305

:beforei :afterrenderować w pojemniku

i <wejście> nie może zawierać innych elementów.


Pseudoelementy można zdefiniować (lub lepiej powiedzieć, że są obsługiwane tylko) na elementach kontenera. Ponieważ sposób ich renderowania znajduje się w samym kontenerze jako element potomny. inputnie mogą zawierać innych elementów, dlatego nie są obsługiwane. Z buttondrugiej strony, który jest również elementem formularza, obsługuje je, ponieważ jest to kontener innych podelementów.

Jeśli pytasz mnie, jeśli niektóre przeglądarka nie wyświetla tych dwóch pseudo-elementów na elementy non-kontenerowych, jest to błąd i niestandardowym zgodności. Specyfikacja bezpośrednio mówi o zawartości elementu ...

Specyfikacja W3C

Jeśli uważnie przeczytać specyfikację faktycznie mówi, że są one wstawiane wewnątrz elementu zawierającego:

Autorzy określają styl i lokalizację generowanej treści za pomocą pseudoelementów: before i: after. Jak wskazują ich nazwy, pseudoelementy: before i: after określają lokalizację zawartości przed i po zawartości drzewa dokumentu elementu. Właściwość „content” w połączeniu z tymi pseudoelementami określa, co zostanie wstawione.

Widzieć? zawartość drzewa dokumentu elementu . Jak rozumiem, oznacza to wewnątrz pojemnika.

Robert Koritnik
źródło
119
+1 Znacznie lepiej niż zaakceptowana odpowiedź. Dzięki za jasne wyjaśnienie samego standardu. Tyle o [required]::before { content "*"; color: red; }: P
Kevin Peno,
93
Wskazówka: jeśli masz problem tylko z przesłaniem danych, takich jak <input type="submit" value="Send"/>, użyj <button type="submit">Send</button>zamiast tego. Prezentacja jest identyczna, ale <button>jest pojemnikiem, a zatem obsługuje :beforei :after.
grypa
15
Co <hr />? Myślałem, że to nie jest element kontenera, ale może renderować :afteri :before jsfiddle.net/Uf88j/1
deathlock
7
@deathlock: to jest naprawdę interesujące. Powiedziałbym, że musi to być jakaś anomalia i nie polegałbym na tym, działając w różnych przeglądarkach lub w różnych wersjach ... HR nie jest elementem kontenerowym, dlatego nie powinien uwzględniać pseudoelementów. Nawet standard W3C mówi, że nie dopuszcza żadnych treści. A jeśli sprawdzisz element void , zobaczysz, że elementy te nie powinny w żadnym wypadku zawierać żadnej treści. Pseudoelementy są treścią, więc spodziewaj się, że w przyszłej wersji przeglądarki ich nie wyświetli.
Robert Koritnik
5
: przed i: po renderowaniu w kontenerze ” Pseudoelementy: przed i: po pojawiają się „ przed i po treści ”. Nie „na początku ani na końcu” pojemnika. Specyfikacja nie wspomina o kontenerze . W przypadku tagów takich jak pi h1treść znajduje się w tagu, więc przed / po pojawiają się również wewnątrz. Elementy takie jak inputi hr:: przed i: po nadal pojawiałyby się przed lub po treści, ale nie dotyczy to żadnego kontenera (szczególnie dla input). input: selected: before jest powszechnie używany do wskazania, że ​​pola wyboru są sprawdzane przez css.
Radley Sustaire
60

Dziwnie, działa z niektórymi rodzajami danych wejściowych. Przynajmniej w Chrome

<input type="checkbox" />

działa dobrze, tak samo jak

<input type="radio" />

To tylko type=textniektóre inne, które nie działają.

vals
źródło
1
@ANeves, dla mnie to działało w Chromium, ale nie w Firefoksie.
kcpr
45

Oto inne podejście (zakładając, że masz kontrolę nad HTML): dodaj puste miejsce <span></span>po danych wejściowych i celuj w CSS za pomocą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>

Używam tego podejścia w AngularJS, ponieważ automatycznie doda .ng-invalidklasy do <input>elementów formularza i do formularza, ale nie do <label>.

Blazemonger
źródło
1
Pozwala ona dodać działania wskaźnikiem, jak: input:hover+span:after{color: blue}. Głosuj.
krassowski
2
Dlaczego ta odpowiedź ma tak mało pozytywnych opinii? Myślę, że wiedza teoretyczna jest ważna, ale to rozwiązuje problem.
jorgefpastor
Fajna opcja, aby rozwiązać problem.
Jester
39

:beforei :aftersą stosowane w kontenerze, co oznacza, że ​​można go używać do elementów z tagiem końcowym.

Nie dotyczy elementów samozamykających.

Na marginesie, elementy, które samozamykają się (takie jak img / hr / input) są również znane jako „Elementy zamienione”, ponieważ są one zastępowane odpowiednią treścią. „Obiekty zewnętrzne” z powodu braku lepszego terminu. Lepiej przeczytaj tutaj

CatalinBerta
źródło
Ta odpowiedź jest poprawna, zwięzła i zapewnia ważny kontekst. Powinien być na górze, imo.
Paul
32

Użyłem background-imagedo stworzenia czerwonej kropki dla wymaganych pól.

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

Zobacz na Codepen

Veiko Jääger
źródło
20

Nie możesz umieścić pseudo elementu w elemencie wejściowym, ale możesz umieścić element cienia, jak symbol zastępczy!

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

Aby pracować w innych przeglądarkach, wykorzystania :-moz-placeholder, ::-moz-placeholdera :-ms-input-placeholder w różnych selektorów . Nie można pogrupować selektorów, ponieważ jeśli przeglądarka nie rozpozna selektora, unieważnia całą instrukcję.

AKTUALIZACJA : Powyższy kod działa tylko z preprocesorem CSS (SASS, LESS ...), bez użycia preprocesorów:

input[type="text"]::-webkit-input-placeholder:before { // your code }
Shankar Cabus
źródło
3
Miły! Zauważ, że pseudoelement zastępczy ma ograniczoną obsługę właściwości: kolor, tło, odstępy między słowami, odstępy między literami, dekoracja tekstu, wyrównanie w pionie, transformacja tekstu, wysokość linii, wcięcie tekstu, krycie. Zobacz css-tricks.com/almanac/selectors/p/placeholder
henry
Dzięki za podpowiedź. Pamiętaj tylko, że wszystko wewnątrz pseudoelementu zniknie, gdy użytkownik wypełni pole wprowadzania danych. To problem UX, jeśli wszystko, czego chciałeś, tak jak ja, wyświetlało znak glyphicon-searchbez dotykania znaczników.
Davi Lima
2
Pewien kontekst, dlaczego to już nie działa: bugs.chromium.org/p/chromium/issues/detail?id=582301
Oliver Joseph Ash,
17

Pseudoelementy, takie jak :after, :beforesą tylko dla elementów kontenera. Elementy otwarcia i zamknięcia w jednym miejscu, takim jak <input/>, <img>itp nie są elementami pojemnik, a zatem elementy pseudo nie są obsługiwane. Po zastosowaniu pseudoelementu do elementu kontenera, takiego jak <div>i po sprawdzeniu kodu (patrz obrazek) możesz zrozumieć, co mam na myśli. W rzeczywistości pseudoelement jest tworzony wewnątrz elementu kontenera. Nie jest to możliwe w przypadku <input>lub<img>

wprowadź opis zdjęcia tutaj

Pons Purushothaman
źródło
15

Działające rozwiązanie w czystym CSS:

Sztuką jest założenie, że za polem tekstowym jest element dom.

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

(*) Ograniczone rozwiązanie:

  • musisz mieć nadzieję, że istnieje następujący element dom,
  • musisz mieć nadzieję, że żadne inne pole wejściowe nie podąży za twoim polem wejściowym.

Ale w większości przypadków znamy nasz kod, więc to rozwiązanie wydaje się wydajne i 100% CSS i 0% jQuery.


źródło
2
input#myTextField ~ span:before {o wiele lepiej, ale rozpiętość powinna mieć klasę, która powinna być bardziej wyraźna, jak .ticklub.icon
Val
13

Znalazłem ten post, ponieważ miałem ten sam problem, było to rozwiązanie, które działało dla mnie. W przeciwieństwie do zastąpienia wartości wejściowej, po prostu usuń ją i absolutnie umieść za nią rozpiętość o takim samym rozmiarze, rozpiętość może mieć przypisaną :beforepseudo klasę z wybraną czcionką ikony.

<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>
Morgan Feeney
źródło
1
+1 - To rozwiązanie działa dobrze, jeśli używasz wtyczki lub frameworka, który automatycznie dodaje klasy sprawdzania poprawności do samego elementu, ale nie do etykiety nadrzędnej.
Blazemonger
9

Największym nieporozumieniem jest znaczenie słów beforei after. Oni nie odnoszą się do samego elementu, lecz do zawartości w elemencie. Tak element:beforejest przed treścią i element:afterpo treści, ale oba nadal znajdują się w oryginalnym elemencie.

inputElement ma żadnej zawartości w widoku CSS, a więc nie ma :beforelub :afterzawartość pseudo. Dotyczy to wielu innych pustych lub zastąpionych elementów.

Nie ma pseudoelementu odnoszącego się do elementu zewnętrznego .

W innym wszechświecie te pseudoelementy można by nazwać czymś innym, aby uczynić to rozróżnienie wyraźniejszym. I ktoś mógł nawet zaproponować pseudoelement, który naprawdę jest poza tym elementem. Jak dotąd nie ma to miejsca w tym wszechświecie.

Manngo
źródło
Może nie rozumiem, co masz na myśli, ale jeśli to zrobię, pseudoelementy działają na hr? jsfiddle.net/demetriad/o49yn5hq
Chris
1
@Chris To mnie zaskakuje, a podczas wyszukiwania - niektórym innym. Myślę, że to dziwactwo. hrzawsze był niejednoznaczny z punktu widzenia CSS, chociaż widać to bardziej w dyskusji o kolorze.
Manngo,
5

Zgodnie z uwagą zawartą w specyfikacji CSS 2.1, specyfikacja „nie definiuje w pełni interakcji: przed i po po zastąpieniu elementów (takich jak IMG w HTML). Zostanie to bardziej szczegółowo określone w przyszłej specyfikacji. ” Chociaż inputtak naprawdę nie jest już zamienionym elementem, podstawowa sytuacja się nie zmieniła: efekt :beforei :afterna nią w nieokreślony i ogólnie nie ma wpływu.

Rozwiązaniem jest znalezienie innego podejścia do problemu, który próbujesz rozwiązać w ten sposób. Umieszczenie wygenerowanej treści w kontrolce wprowadzania tekstu byłoby bardzo mylące: dla użytkownika wydaje się, że jest częścią wartości początkowej w kontrolce, ale nie można go modyfikować - więc wydaje się, że jest to coś wymuszonego na początku kontrola, ale nie zostanie ona przesłana jako część danych formularza.

Jukka K. Korpela
źródło
3
To jest komentarz, nie odpowiedź - raczej długi komentarz, ale mimo to komentarz.
Blazemonger
@Blazemonger, nie jest całkiem jasne, jakie było pytanie, ale w każdym razie ta odpowiedź rozwiązuje ten sam problem, co odpowiedź zaakceptowana, ale w bardziej poprawny sposób. Nie jest niemożliwe użycie wygenerowanej treści dla inputelementów, po prostu nieokreślonych i zależnych od przeglądarki.
Jukka K. Korpela
5

Jak wyjaśnili inni, inputs są jakby pustymi elementami, więc większość przeglądarek nie pozwala na ich generowanie ::beforeani ::afterpseudoelementy.

Grupa robocza CSS rozważa jednak wyraźne zezwolenie, ::beforea ::afterjeśli tak, to na inputpewno appearance: none.

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

Zarówno Safari, jak i Chrome zezwalają na pseudoelementy w swoich formularzach. Inne przeglądarki nie. Zastanawialiśmy się nad usunięciem tego, ale licznik użycia rejestruje około 0,07% stron, które go wykorzystują, co stanowi 20-krotność naszego maksymalnego progu usuwania.

Właściwe określenie pseudoelementów na wejściach wymagałoby przynajmniej wewnętrznej struktury danych wejściowych, czego jeszcze nie zdołaliśmy (i nie jestem pewien, czy * możemy * zrobić). Ale Boris zasugerował, w jednym z wątków, pozwalając na pojawienie się: brak danych wejściowych - po prostu zamieniając je w elementy <div>, zamiast elementów w pewnym sensie zastąpionych.

Oriol
źródło
4

spróbuj dalej:

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>

Alex Ovchinkin
źródło
3

Musisz mieć jakieś otoczenie wokół wejścia, aby użyć pseudoelementu przed lub po. Oto skrzypce, które ma przedtem na otoku otoki wejścia, a następnie umieszcza przedtem wewnątrz wejścia - a przynajmniej tak to wygląda. Oczywiście jest to obejście, ale skuteczne w uścisku i nadaje się do reagowania. Możesz łatwo zrobić to później, jeśli chcesz umieścić inną treść.

Working Fiddle

Znak dolara wewnątrz pseudoelementu: http://jsfiddle.net/kapunahele/ose4r8uj/1/

HTML:

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

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;
}
Kapunahele Wong
źródło
Fajna sztuczka, ale możesz zrobić div stylizowany na „kontynuowanie” wprowadzania. Zobacz tę skrzypkę jsfiddle.net/ose4r8uj/31 Ale możesz to również zrobić łatwiej, używając bootstrap: getbootstrap.com/css/#forms-control-validation poszukaj części „Z opcjonalnymi ikonami”. Mimo to nie ma to nic wspólnego z pierwotnym pytaniem.
Victor Ivens
1
FYI nie nadaje się do: focus
,:
2

Jeśli próbujesz stylizować element wejściowy za pomocą: przed i po, istnieje szansa, że ​​próbujesz naśladować efekty innych zakresów, div, a nawet elementów na stosie CSS.

Jak wskazuje odpowiedź Roberta Koritnika: przed i po można stosować tylko do elementów kontenera a elementy wejściowe nie są kontenerami.

JEDNAK, HTML 5 wprowadził element przycisku , który jest kontenerem i zachowuje się jak element wejściowy [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>
Kevin Conroy
źródło
HTML 4 faktycznie wprowadził element <button>.
Pan Lister
1

Podsumowanie

To nie działa z <input type="button"> , ale działa dobrze <input type="checkbox">.

Skrzypce : 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;
}

źródło
1

:beforei :afterdziała tylko w przypadku węzłów, które mogą mieć węzły potomne, ponieważ wstawiają nowy węzeł jako pierwszy lub ostatni węzeł.

Juan Mendes
źródło
0

Odkryłem, że możesz to zrobić w następujący sposób:

Musisz mieć rodzica div, który pobierze dopełnienie i: po. Pierwszy rodzic musi być względny, a drugi div powinien być absolutny, aby można było ustawić pozycję po.

Patrick
źródło
-1

Mam inny pomysł, użyj tego zamiast:

<div>
<input type="text"></input>text can be entered here</div>
Dima Dulin
źródło
Autor pytania wyraźnie stwierdził, że nie jest w stanie zmienić znaczników HTML. Ta odpowiedź nie ma sensu. Prawdopodobnie powinien był zostać odrzucony zamiast zredagowany @Morpheus.
Palec