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.


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


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


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


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


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


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 }

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


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.


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>

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.


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.


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.


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>


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

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>

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

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


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.


-1

Mam inny pomysł, użyj tego zamiast:

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

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.