3

This is the site:

http://m2c.dreamhosters.com/wordpress/

The clearfix:

.clearfix:after,
.sub-menu:after,
.sub-menu:after li {
    content: "";
    display: table;
    clear: both;
}

works totally OK in Chrome. But in Firefox it doesn't even show up in the element inspector (and makes the parents div shrink.

How can I fix the problem?

alexchenco
  • 53,565
  • 76
  • 241
  • 413
  • as a side note `.sub-menu:after li` can't be applied since pseudoelements can't contain children – Fabrizio Calderan Dec 16 '14 at 10:12
  • `.sub-menu:after li` will break your css rule in FF. – t.niese Dec 16 '14 at 10:13
  • @Fabrizio Calderan, t.niese: Well-spotted. That selector looks like a mistake. What's baffling is the fact that Chrome accepts it just fine... I think Chrome has some exceptions when it comes to parsing selectors with pseudo-elements though. – BoltClock Dec 16 '14 at 10:18
  • Didn't spend much time on firefox, but it looks like its inspector doesn't show pseudo classes, but developer edition of firefox does, so you can see what's up in more detail in there. All seems to be fine here though - I'm using Firefox 32.0.3 – robjez Dec 16 '14 at 10:19
  • @BoltClock might be general problem in the underlaying selector engine as `document.querySelector(".sub-menu:after li");` will also be accepted in Chrome while FireFox will throw an exception. Regardless of whether such a selector makes any sense with `document.querySelector` at all. – t.niese Dec 16 '14 at 10:30
  • In any case, it isn't really just a side note. It's the answer. I'll guess I'll do the honors... – BoltClock Dec 16 '14 at 10:54
  • FireFox displays this warning in console: _Expected end of selector or a user action pseudo-class after pseudo-element but found 'li'. Ruleset ignored due to bad selector. (styles.css, line 42)_ – Salman A Dec 16 '14 at 11:48

2 Answers2

3

As mentioned in the comments, Firefox is dropping the rule because the .sub-menu:after li in your selector is invalid. In CSS2.1 and Selectors 3, only one pseudo-element may appear at most per complex selector and it must be at the very end of the selector. When encountering an invalid selector in a ruleset a browser must drop the entire ruleset. This is why it's not showing up in the inspector.

To fix it, either remove the offending selector, as it appears to be a mistake:

.clearfix:after,
.sub-menu:after {
    content: "";
    display: table;
    clear: both;
}

Or if you meant to apply the :after pseudo-element to .sub-menu li, relocate the pseudo-element like so:

.clearfix:after,
.sub-menu:after,
.sub-menu li:after {
    content: "";
    display: table;
    clear: both;
}

So, instead of asking why this CSS doesn't work on Firefox, the real question is: why does Chrome accept it? That's most likely because WebKit (and by extension Blink) is known to be more lenient when it comes to parsing pseudo-elements, perhaps due to the fact that it employs certain non-standard features that require actively violating the spec. To quote this other answer of mine:

Perhaps the root of the problem lies in the very fact that you're trying to add generated content to other pseudo-elements, which again seems to work in WebKit browsers for whatever bizarre reason. Unlike the above issue with generated content within replaced elements, the current Selectors 3 spec and the upcoming Selectors 4 spec are both very clear on this: you are not supposed to have more than one pseudo-element per complex selector. Of course, WebKit has infamously flouted various rules when it comes to implementing pseudo-elements, so in hindsight it does not surprise me to see WebKit mess up doing so.

Either way, the real conclusion is that the implementation of CSS generated content is extremely poor beyond the scope of the current standard of CSS2.1 + Selectors, by which I mean generated content for replaced elements such as input and progress, and nesting of pseudo-elements in a single selector.

Community
  • 1
  • 1
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
0

Try this one:

.clearfix:before,
.clearfix:after {
    content: " ";
    display: table;
}

.clearfix:after {
    clear: both;
}

It is the one used in the HTML5Boilerplate. I can't really explain how it is different to yours, but this code has been reviewed by many people, and it is used mainstream. Unlikely that you will find it failing.

Enrique Moreno Tent
  • 24,127
  • 34
  • 104
  • 189