28

I have an image that kind of slides up from the menu when you hover it. Because it's hidden under the menu i want to give the bottom of the image a little bit of deph by adding a dark fade to the bottom. I figured the best way to achieve this is to use pseudo elements. I don't really care much about IE support as it's such a small detail.

So, here's what i've got:

.header-section .trygg-ehandel-icon {
    position: absolute;
    top: 45px;
    right: 280px;
    z-index: 0;
    display: block;
    // Stripped out some transition style here
  }

  // Here's where the cool stuff begins!
  .header-section .trygg-ehandel-icon::after {
    position: absolute;
    top: 0px; left: 0px;
    height: 20px; width: 20px;
    display: block;
    content: '.';
    z-index: -999999px;
    background: red;
  } 

First off, i'm unsure whether to use double or single colons before "after". I've always used one but recently i noticed people using two, so what's the way to go? Either seems to work!

You can see it in action here: http://goo.gl/RupQa

It's the yellow logo popping up above the header menu. Why am i not seeing a 20x20 red box above the image? The parent (.trygg-ehandel-icon) is absolute positioned, so the pseudo element should show up relative to it, right?

I've been trying to fix this for over an hour now, any suggestions?

qwerty
  • 5,166
  • 17
  • 56
  • 77
  • 2
    +1 for nice looking website design. – crush Jan 29 '13 at 14:23
  • "First off, i'm unsure whether to use double or single colons" If you don't care about IE8, which you state, then use double colons so you know you're working with a pseudo-element (that's what double colons were intended for). The single colon should only be used with IE8 because it doesn't understand double colons for pseudo-elements. – BoltClock Jan 29 '13 at 14:29
  • @BoltClock So you're saying that the correct way to do it is with double colons, but IE did it wrong? I know IE generally fails at things but come on, it's like they purposely ignored the spec and said "screw it, i'm gonna ignore double colons". – qwerty Jan 29 '13 at 14:31
  • 1
    @BoltClock You are right and wrong: http://www.w3.org/wiki/CSS/Selectors#Pseudo-classes. Double colon is used only for `first-line`, `first-letter`, `before`, and `after`. – crush Jan 29 '13 at 14:34
  • 1
    @qwerty: Pretty much, although single colons were the only option before; double colons were only introduced in CSS3 to distinguish pseudo-elements from pseudo-classes. You're kind of right - IE8 was (very!) focused on CSS2.1, with only bits of CSS3 here and there, so one *could* say it deliberately ignored the spec, although oddly enough `~` and advanced attribute selectors make an appearance. – BoltClock Jan 29 '13 at 14:36
  • Double colons are used for pseudo-elements while single colons are used for pseudo-classes. – crush Jan 29 '13 at 14:37
  • @crush: I didn't say single colons cannot be used for previously-introduced pseudo-elements... in fact that was the *only* possible way to specify them. I'm saying double colons should be used going forward, as any new ones won't be able to use single colons anyway (those are reserved for legacy support). – BoltClock Jan 29 '13 at 14:39
  • 2
    http://stackoverflow.com/questions/5843035/does-before-not-work-on-img-tags Apparently, using `::before` and `::after` pseudo-elements with `img` tags does not work in most browsers. I have been completely unable to get it to work in my tests, even with the simplest example. Notice, there are some hacked work-arounds in that link, as well as a technical explanation about why it doesn't work out-of-the-box. – crush Jan 29 '13 at 14:45
  • @crush Well that explains it! I'll just replace it with a div and have the image as a background, that should work. Thanks! – qwerty Jan 29 '13 at 14:51
  • @crush: That's the answer - go ahead and post it as one. `::before`/`::after` is not defined for `img` elements and the like (so-called replaced elements), due to stuff such as what coreyward explains in that question. – BoltClock Jan 29 '13 at 14:56

1 Answers1

56

As answered in this question.

Using before and after psuedo-elements with the img tag does not work in most browsers, by design.

Image tags are self-closing (<tag />) tags because they contain no content. Since they do not contain any content, no generated content can be appended (::after) or prepended (::before) to the existing content.

The article linked above lists two work-around solutions. The CSS work-around is very hackish in nature, while the jQuery solution is much more elegant, but depends on both Javascript being enabled and the jQuery library being included.

Community
  • 1
  • 1
crush
  • 16,713
  • 9
  • 59
  • 100
  • 11
    A note for future readers. This appears to be true for inputs as well (at least as far as my tests go). Makes sense as they are also self closing. – Erik Honn Jun 19 '13 at 07:37
  • 2
    @ErikHonn as well as for any other void element, which are: ``, ``, `
    `, ``, ``, ``, `
    `, ``, ``, ``, ``, ``, `` and ``.
    – Pavlo Dec 27 '13 at 22:26
  • 1
    "Since they do not contain any content, no content can be appended" - that's a very awkward explanation. Are you really trying to tell me that this image I'm looking has **no content**? Of course it has content! This is a technical issue and a shortcoming of the spec. Software should be designed to be intuitive. If I think I should be able to add a pseudo-element after an img, then I should be able to do that. This limitation is unnecessary. – hawk Jun 21 '14 at 04:02
  • 3
    @hawk, technically the `` element has no content. It marks a point in the document tree where external content (the image referenced with `src` attribute) should be inserted, but it's just a point, even `alt` attribute is not the content of the element. Probably it would be better to design it as `alternative content` instead (like for `` or ` – Ilya Streltsyn Dec 11 '14 at 08:18
  • @Pavlo, it's interesting that almost all browsers actually allow adding `::before` and `::after` to `hr` element: http://css-tricks.com/simple-styles-for-horizontal-rules/ :) – Ilya Streltsyn Dec 11 '14 at 08:21
  • @IlyaStreltsyn Browsers do a lot of things to enable developers to continue writing bad code. I'd rather browsers were extremely strict to the specification instead of lenient towards poor coding. But, that would put a LOT of people out of work, and leave consumers of browsers scratching their head about why sites aren't working. "It's not the browsers fault!" is not something most consumers want to hear or understand. Thus, we are stuck with browsers enabling poor coders. In your link, the author uses pseudo-elements with pseudo-class syntax. The browser corrects this mistake for him. – crush Jul 01 '15 at 12:52
  • Let me reiterate. The [specification](http://www.w3.org/TR/css3-selectors/#pseudo-elements) currently allows for `:after, :before, :first-line, and :first-letter` exclusively. This is because these were introduced before CSS3. CSS3 introduced the `::` to delineate pseudo-elements, but also makes note that user-agents should support the old, now deprecated syntax for only the above mentioned pseudo-elements for reasons of backwards compatibility. It's not encouraged to be used in new documents which means it will likely be officially deprecated in a future revision. – crush Jul 01 '15 at 13:17
  • Judging by the specification, I can see no valid reason why a browser should honor the `::before` and `::after` pseudo-elements on an `HR` element. The specification states that `HR` has no content, and that pseudo-elements are to be appended before or after the content in the document tree. Since there is no content, it shouldn't be able to append generated content either. If `HR` is crucial to the flow of your site's presentation, I wouldn't count on `HR` supporting these pseudo-elements in all user agents. This is one of those times that just because it "works" doesn't mean you should do it – crush Jul 01 '15 at 13:20
  • @crush, I completely agree that the old single-colon syntax for CSS1 pseudo-elements is not encouraged for using in new documents, but it's the only way to get them working in IE8 (and below, for `first-letter`/`first-line`), so usage of this syntax still may be not the coder's "mistake", but the result of the practical need. When IE8- die out completely and CSS Selectors 4 reaches Candidate Recommendation, we would be able to say that this old syntax is kind of "deprecated" (as it says that coders _must_ use `::`), but CSS Selectors 3 doesn't require this. – Ilya Streltsyn Jul 02 '15 at 08:30
  • @crush, again, I agree that strictly by the spec, `::before` and `::after` shouldn't work for `hr`. The only possible justification for this behavior I see is the old draft of CSS3 Content module that [allowed](http://www.w3.org/TR/css3-content/#inserting3) `content` property for _all elements_ (and if an element may have content, even generated, it may have something before/after it as well). So of course styling `hr` with pseudo-elements shouldn't be anything more than sort of progressive enhancement. – Ilya Streltsyn Jul 02 '15 at 08:38
  • is this still true? – nanquim Feb 27 '22 at 20:04