Czy: zanim nie działa na elementach img?

262

Próbuję użyć :beforeselektora, aby umieścić obraz na innym obrazie, ale okazuje się, że po prostu nie działa umieszczenie obrazu przed imgelementem, a tylko innym elementem. W szczególności moje style to:

.container
{
   position: relative;
   display: block;
}

.overlay:before
{
    content: url(images/[someimage].png);
    position: absolute;
    left:-20px;
    top: -20px;
}

i uważam, że to działa dobrze:

<a href="[url]" class="container">
  <span class="overlay"/>
  <img width="200" src="[url]"/>
</a>

ale to nie:

<a href="[url]" class="container">
  <img width="200" src="[url]" class="overlay"/>
</a>

Mogę użyć elementu divlub pzamiast tego span, a przeglądarka poprawnie nakłada mój obraz na obraz w imgelemencie, ale jeśli zastosuję klasę nakładki do imgsiebie, to nie zadziała.

Chciałbym, aby to działało, ponieważ to spanmnie obraża, ale co ważniejsze, mam około 100 postów na blogu, które chciałbym zmodyfikować, i mogę to zrobić za jednym razem, jeśli tylko mogę zmodyfikować arkusz stylów, ale jeśli będę musiał wrócić i dodać dodatkowy spanelement między elementami ai img, będzie to o wiele więcej pracy.

Joshua Frank
źródło
5
Jest to dziwne, tym bardziej, że sam standard CSS podaje przykład użycia: przedtem z elementem IMG…
@chharvey: To pytanie zostało zadane po tym.
Joshua Frank

Odpowiedzi:

262

Niestety większość przeglądarek nie obsługuje używania tagów img :afterani ich używania :before.

http://lildude.co.uk/after-css-property-for-img-tag

Możliwe jest jednak osiągnięcie tego, czego potrzebujesz za pomocą JavaScript / jQuery. Sprawdź to skrzypce:

http://jsfiddle.net/xixonia/ahnGT/

$(function() {

    $('.target').after('<img src="..." />');

});

Edytuj :

Z tego powodu nie jest to obsługiwane, sprawdź odpowiedź Coreyward .

cwharris
źródło
3
twoje skrzypce brakuje. To jest piękno linków jsFiddle.
Roko C. Buljan
Naprawione. Przepraszam za to.
cwharris 16.04.13
1
Ta odpowiedź nie wyjaśnia, dlaczego img nie może mieć przed czy po. Ponadto proponowane rozwiązanie javascript nie jest właściwym zamiennikiem.
Jasper Kennis
3
Proponowane rozwiązanie nie powinno działać w każdym scenariuszu. To po prostu przykład obejścia problemu. Jeśli chcesz zaproponować bardziej ogólne rozwiązanie, opublikuj odpowiedź.
cwharris
141

Pseudo-selektory przed i po nie wstawiają elementów HTML - wstawiają tekst przed lub po istniejącej zawartości elementu docelowego. Ponieważ elementy obrazu nie zawierają tekstu lub mieć potomków, ani img:beforeczy img:afterbędzie Pan jakieś dobre. Dotyczy to również elementów takich jak <br>iz <hr>tego samego powodu.

coreyward
źródło
Tagi img są elementami same w sobie, a jednak możemy wstawiać je przed lub po innych elementach za pomocą: przed i po selektorów psuedo. Czy nie ma tego w specyfikacji css?
cwharris
13
To trochę inaczej. Możesz wstawić obraz, ale nie używając tagu obrazu - musisz użyć content: url(/img/foo.jpg);składni. Szczegółowe informacje można znaleźć na w3.org/TR/CSS21/generate.html .
coreyward 30.04.11
4
Mała korekta: wstawiają elementy psuedo, które są bardziej podobne do elementów niż do węzłów tekstowych.
Chris Calo,
Wygenerowana treść staje się częścią Shadow DOM. Te nowe elementy, atrybuty i węzły tekstowe są bardzo realne. Możesz je zobaczyć np. W Inspektorze Chrome.
Marc Diethelm,
@coreyward Może zaufasz MDN (Replaced Element)
Marc Diethelm
41

Znalazłem sposób, aby to działało w czystym css:

Jestem po prostu fałszywe treści -method

czysta metoda CSS, która umożliwia img: after.

Możesz sprawdzić CodePen: Jestem tylko fałszywą treścią lub zobaczę źródło .

Źródło i fragment

img {
    /* hide the default image */
    height:0;
    width:0;

    /* hide fake content */
    font-size:0;
    color:transparent;

    /* enable absolute position for pseudo elements */
    position:relative;

    /* and this is just fake content */
    content:"I'm just fake content";
}

/* initial absolute position */
img:before,
img:after {
    position:absolute;
    top:0;
    left:0;    
}

/* img:before - chrome & others */
img:before {
    content:url(http://placekitten.com/g/250/250);
}

/* img:before - firefox */
body:not(:-moz-handler-blocked) img:before {
    padding:125px;
    background:url(http://placekitten.com/g/250/250) no-repeat;
}

/* img:after */
img:after {
    /* width of img:before */
    left:250px;

    content:url(http://lorempixel.com/350/200/city/1);
}
<img
    alt="You are watching the ~ I'm just fake content ~ method"  
/>

Obsługa przeglądarki

✓ Chrome 10+

✓ Firefox 11+

✓ Opera 9.8+

✓ Safari

Bez wsparcia

⊗ Internet Explorer 8/9

Testuj w innych przeglądarkach

TimPietrusky
źródło
1
Zasadniczo po prostu dodajesz treść: „” do stylu znacznika img i: przed i po rozpoczęciu pracy. Niezłe znalezisko, zastanawiam się, jak to jest w różnych przeglądarkach.
w00t
2
Skonfigurowałem test ikony jsbin.com/esewow/edit#html,live i mogę potwierdzić, że nie działa na IE8, ale na Chrome i Safari działa dobrze.
w00t
14
Przykład CodePen działa w przeglądarce Firefox tylko wtedy, gdy src znacznika img jest nieprawidłowy - powoduje to, że atrybut alt jest renderowany jako element, który faktycznie umożliwia: przed i po. Jeśli img src istnieje, przestaje działać: codepen.io/anon/pen/EjtDu
thenickdude
2
Zatrzymaj mnie, jeśli się mylę, ale wygląda na to, że nie działa już z Chrome 46
Gyum Fox,
5
img: before i img: after w ogóle nie działają w Safari . Nawet tego, co początkowo mnie ekscytowało. Dobra próba.
Wray Bowling
9

Ze względu na charakter <img>bycia zastąpiony elementem , stylizacja dokument nie dotyczy go.

W każdym razie, aby się do niego odwołać, <picture>zapewnia idealne, natywne opakowanie, do którego mogą być dołączone pseudoelementy:

img:after, picture:after{
    content:"\1F63B";
    font-size:larger;
    margin:-1em;
}
<img src="//placekitten.com/110/80">

<picture>
    <img src="//placekitten.com/110/80">
</picture>

dakab
źródło
3

Oto inne rozwiązanie wykorzystujące pojemnik div dla img podczas używania :hover::afterdo osiągnięcia efektu.

HTML w następujący sposób:

<div id=img_container><img src='' style='height:300px; width:300px;'></img></div>

CSS w następujący sposób:

#img_container { 
    margin:0; 
    position:relative; 
} 

#img_container:hover::after { 
    content:''; 
    display:block; 
    position:absolute; 
    width:300px; 
    height:300px; 
    background:url(''); 
    z-index:1; 
    top:0;
} 

Aby zobaczyć to w akcji, sprawdź skrzypce , które utworzyłem. Tylko dlatego, że wiesz, że jest przyjazny dla różnych przeglądarek i nie ma potrzeby oszukiwania kodu za pomocą „fałszywych treści”.

truleighsyd
źródło
Jest to przydatne do zastosowania display: inline-blockdo #img_container. Dzięki temu szerokość pojemnika będzie równa obrazowi przy wszystkich rozmiarach ekranu. Tak więc nie kończy się to, że :aftertreść unosi się poza obrazem.
Anonimowy
1

Myślę, że najlepszym sposobem na sprawdzenie, dlaczego to nie działa, jest: przed i po wstawieniu ich zawartości przed lub po treści w tagu, do którego je zastosujesz. Działa więc z divami lub rozpiętościami (lub większością innych tagów), ponieważ możesz umieszczać w nich zawartość.

<div>
:before
Content
:after
</div>

Img jest jednak samodzielnym, samozamykającym się znacznikiem, a ponieważ nie ma oddzielnego znacznika zamykającego, nie można w nim niczego umieścić. (To musiałoby wyglądać <img>Content</img>, ale oczywiście to nie działa.)

Wiem, że to stary temat, ale najpierw pojawia się w Google, więc mam nadzieję, że pomoże to innym się uczyć.

BevansDesign
źródło
1

Ten działa dla mnie:

HTML

<ul>
    <li> name here </li>
</ul>

CSS

ul li::before {
    content: url(../images/check.png);
}
Miecz I
źródło
1

::after może być użyty do wyświetlenia zastępczego obrazu


Zobacz poniższy przykład, pierwsze 2 imgtagi wskazują uszkodzone adresy URL. Ale drugi wyświetla obraz zastępczy zamiast domyślnego zepsutego logo z przeglądarki. Jednak nie jestem pewien, czy to jest praktyczne, uważam, że jest to dość trudne, aby dobrze działało.

img {
  position: relative;
  display: inline-block;
  width: 300px;
  height: 200px;
  vertical-align: top;
}
img:not(:first-child)::after {
  position: absolute;
  left: 0; top: 0; right: 0; bottom: 0;
  content: "<" attr(alt) "> NOT FOUND";
  border: 1px dashed #999;
  background: url(https://cdn.dribbble.com/users/1012566/screenshots/4187820/topic-2.jpg) center/100%;
}
<img src="https://source.unsplash.com/random/100/75" alt="logo">
<img src="https://source.unsplash.com/random/100/75" alt="logo">
<img src="https://source.unsplash.com/random/100x75" alt="logo">

Loi Nguyen Huynh
źródło
0

Wypróbuj ten kod

.button:after {
    content: ""
    position: absolute
    width: 70px
    background-image: url('../../images/frontapp/mid-icon.svg')
    display: inline-block
    background-size: contain
    background-repeat: no-repeat
    right: 0
    bottom: 0
}
subindas pm
źródło
-1

Próbowałem i znalazłem prostszą metodę, aby to zrobić. Oto HTML:

    <img id="message_icon" src="messages2.png">
    <p id="empty_para"></p>

To, co zrobiłem, to umieszczenie pustego <p>tagu za tagiem graficznym. Teraz użyję p :: before, aby wyświetlić obraz i ustawić go zgodnie z moimi potrzebami. Oto CSS:

#empty_para
{
    display:inline;
    font-size:40;
    background:orange;
    border:2px solid red;
    position:relative;
    top:-400px;
    left:100px;
}
#empty_para::before
{
    content: url('messages.png');
}

Spróbuj.

Tajveer Singh Nijjar
źródło
-1

Spróbuj :: po na poprzednim elemencie.

Dmytro Jurczenko
źródło
Czy opracowałbyś swój post?
zmag