Forum Moderators: not2easy

Message Too Old, No Replies

Pseudo Element Stacking Context in IE9

:before/:after, z-Index, position and display

         

SuzyUK

12:08 am on Dec 5, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



was having a play today with something that should work, but doesn't in IE8 - ackk I thougt thought it would (no big deal just a playing thingie..!), not sure if this a problem/feature of other browsers too (works in FF, Opera10, Chrome) - so if anyone fancies a quick copy/paste and feedback it would be appreciated, all explained in the code

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Pseudo Element Stacking</title>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<style type="text/css" media="screen">
/* image being used: http://www.google.co.uk/images/logos/ps_logo2.png - 364px x 126px */
#logo {
position: relative;
z-index: 1;
border: 1px solid #00f;
height: 126px;
width: 364px;
text-align: center;
font: 40px/106px Georgia, "trebuchet ms", sans-serif;
padding: 10px;
color: #00f;
background: #ccc; /* to show background of background :o! */
}

#logo:after {
content: "";
background: transparent url(http://www.google.co.uk/images/logos/ps_logo2.png) no-repeat 0 0;
width: 364px;
height: 126px;
position: absolute;
z-index: 1000;
top: 10px;
left: 10px;
}

img {float: left; margin: 20px 20px 0 0;}
#info {overflow: hidden;}
</style>
</head>
<body>
<h1 id="logo">Google</h1>
<h2>IE8 Stacking Context?</h2>
<img src="http://www.google.co.uk/images/logos/ps_logo2.png" alt="">
<div id="info">
<p>The bordered "google" header above contains the image also shown on the left of this paragraph</p>
<p>The header above should show no "plain text" on top of it - but should show plain text if images are off, and also still show text if CSS is off </p>
<p>it does not work in IE7 or below without a script, I'm thinking it should work in IE8, but it doesn't! Any insight gratefully received..
<p>also looking for the feedback on how it works in IE9, Safari, Opera versions etc.</p>
<p>Tested working in FF, Chrome, Opera 10</p>
</div>
</body>
</html>


tia,
Suzy {x}

milosevic

10:27 am on Dec 6, 2010 (gmt 0)

10+ Year Member



Hi Suzy, it does seem surprising that it doesn't work - I've tried a few ideas tweaking the code but nothing seems to work for me either.

I had experienced issues with before and after that have made me give up on using them due to display issues. Had problems with Firefox pre-3.5 and earlier with before and after displaying strangely or not interpreting some declarations.

Be interested to know if you can find a solution to this!

alt131

12:51 pm on Dec 6, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



What fun ;) Here's a sampling (mostly predictable):

Opera: 7.23, 9.61, 10.53 = as designed
Firefox: 2.0, 3.0 = No image showing
Firefox: 3.5, 3.6 = as designed
winSafari: 3.1, 5 = as designed
Netscape: 8.1 = no image showing

Suzy, have you had time to progress further - I've limited time right now, but I assume you trialled the following and know it works:
<h1 id="logo"><span>Google</span></h1>
with
span {
position:absolute;
top:-10px; /* top and left set to track location */
left:-10px;
z-index:-1; /* note the negative, also note that to make it easy I set #logo = z-index:1 #logo:after = z-index:2 */
background-color:aqua;
}

Note I had to take the span back to z-index:-1 before it would stack under #logo:after. (Also tested using a div and p to eliminate any inline/block differences. )

The rest of this assumes the above code modification, but maybe my rambling reasoning will prompt something.
I suspected the pseudo element, so played with z-index:
Removing z-index from span, then span and #logo:after, then all three elements produced the predictable result of displaying as designed in ff and winsafari, but stacking the span on top of the image in ie.
That is, with the span z-index:auto, or all elements have z:index:auto, ff and winsafari stack the contents lower than the pseudo element :after, while ie stacks the contents higher than the pseudo element :after.

Interesting in reverse:
Removing z-index from #logo (with the existing z-index still applied to span and :after), stacked span behind #logo in all three browsers, as did removing the z-index from #logo AND #logo:after.
That is, when the parent element has a z-index of auto, all browsers obeyed the negative z-index of the span and placed it behind the parent.
Also, when the parent element and the pseudo element have a z-index of auto, all browsers obey a z-index:2 on the content and stack it on top.
Setting span to z-index:0-1 produced different results:
At z-index:0 ff and winSafari stack the span above the parent, but below the :after. That seems predictable. ie (also predictably) stacks the content above the pseudo element. At z-index:1 the content is drawn above the pseudo element in all three.

Firebug does not give a computed style for :after, and winSafari Developer does not report a z-index for :after unless explicitly set. However, it all suggests that :after is treated as last written. (A couple quick tests with :before suggests this holds true in relation to stacking.)


So, the whole point of these ramblings are that in this case I think the issue if treatment of pseudo elements. That led me to this older article dev.moonhenge.net/css21/spec/z-index/ (credibility unknown, but made sense), and to Appendix E of the Recommendations.

I'm sure the answer is in Annex E, and maybe someone else already has it, but I think the issue with the original code is that there is no explicit statement on how to handle stacking for the combination of an anonymous line box AND a replaced element on a pseudo element. There is logic in the ff and winsafari approach in that the last element in the code should be at the front. However, I am also compelled by the ie result, which is consistent with displaying (not hiding*) content. (Haven't looked to see if this has been modded in ie9.)

*hiding seems to be coming up a lot at the moment ;)

alt131

1:00 pm on Dec 6, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hey milosovic, I missed your post
I've tried a few ideas tweaking the code but nothing seems to work for me either.
Sounds helpful - I'd like to explore this further, but as stated, have limited time - would you mind very much sharing what you tried but didn't work: It will save trying the same things, and as discussions in other threads show, will definitely prompt deeper thought and discussion ;)

SuzyUK

4:55 pm on Dec 6, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



@Milosevic will keep trying but I'm not hopeful without scripting in an extra element, which of course would need to be done for IE7 anyway so it's no bother to include IE8 in the conditional, will post that code solution later.. the exercise was just disappointing as I tend to only like to relegate IE7 and below to conditional CSS if I have to and would like to find out if IE8 can be worked around in another way :o

Thanks K, I've not had much more time either, it was just a playtime excercise but one which I'd love to explore, so am coming back to read both your findings in more detail when time permits! - Annexe E was something I'd hoped to avoid ;) and yes this stemmed from the "hidden" discussion" but I think the technique would have much more uses.. multiple/multiple backgrounds etc. for progressive enhancement type features

ignoring the :before/:after (and earlier FF) support for the minute, I *think* but am not sure that IE8 is wrong with it's stacking context hence I wanted to see if it works as described in IE9 yet.

To my mind it should, as you rightly say, treat the :after pseudo element as an element immediately following the content and should stack it accordingly, if fact my test & script fix is to add an empty span after the text in #logo.. i.e.
<h1 id="logo">Google<span></span></h1>
and then applying the exact same CSS to
#logo span {}
as to
#logo :after {}
which works as expected in IE7 as well as 8, so it seems that IE8 is not quite getting the pseudo element right, in truth this would hardly be noticeable if using the technique for multiple backgrounds as there wouldn't be text there anyway, but still ;)

thanks again both of you, looking forward to seeing if there's any more than can be done

ta, Suzy

[edited by: alt131 at 10:59 pm (utc) on Dec 24, 2011]

Fotiman

5:24 pm on Dec 6, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I tried it in IE9 and it looks the same for me as it does in Chrome.

alt131

2:02 am on Dec 7, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



So ie9 "comes into line". Very useful thanks fontiman.
Apologies for the anecdotal nature of the test results - I started an hour after bed-time and by end time my brain was too mushy to translate the observed results into a conclusion. The older version tests aren't that helpful, beyond the pleasant surprise that (yet again) Opera was well ahead of the bunch. Not a browser I favour, but all credit to the developers.

Suzy, I figured you'd already tested the use of an empty span. Absolutely no need to record my opinion of all those "solutions" based on scripting an empty element to achieve a presentational effect ;). darn the real world.

I only brought myself to hand-coding the extra span so i could manipulate the content for testing. The results of not setting a z-index on parent elements provoked lots of thought about the consequences of over-engineering given I too have carefully protected myself from contact with the detail of Appendix E ;).

Great exerccise though, and even if ie9 is running with the herd, too good an opportunity to permit ie to teach me more about coding, so I'll keep exploring too

SuzyUK

11:43 am on Dec 7, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Good to hear on the IE9 front Foti.. thanks..

I can't quite believe I didn't try this especially when I even mentioned about the use of this for multiple backgrounds - the way to use this for multiple backgrounds would be to have one image as the content and another for the background - using both the
:before
and
:after
pseudo elements could give a lot of scope for getting multiple images in there - think those designs that always wanted an image fixed to the bottom right corner or fancy borders around headings..

So I think we may have a winner.. once we can relegate FF2/3 to the "couldn't care less" pile that is ;)

Solution: put the main image in the content property - another image or a blank repeating gif or plain color could then be used as a background, which would be useful if the content image was a transparent png perhaps?

sometimes things can fly right past, I can't believe I didn't try that before!

what do you think now?

CSS only, HTML unchanged..
#logo {
position: relative;
z-index: 1;
border: 1px solid #00f;
height: 126px;
width: 364px;
text-align: center;
font: 40px/106px Georgia, "trebuchet ms", sans-serif;
padding: 10px;
color: #00f;
}

#logo:after {
content: url(http://www.google.co.uk/images/logos/ps_logo2.png);
background: #008 url(http://example.com/anotherimage.jpg) no-repeat top right;
position: absolute;
z-index: 1000;
top: 0px;
left: 0px;
width: 364px;
height: 126px;
padding: 10px;
}


/* general */
img {float: left; margin: 20px 20px 0 0;}
#info {overflow: hidden;}

alt131

11:43 am on Dec 8, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



what do you think now?
It works as per the versions tested above - yay ;) And I agree, lots of opportunity to get creative. Oh what fun!

But am now wondering what the question was. There's a difference between "why doesn't this work" , and "how can [this] be achieved" - although avoiding Appendix E earns extra points ;)

<Begin seasonal grinch>
Any technique that applies across a wider range of browsers is good - especially when the alternative is scripting in extra elements for presentation only. But I'm mindful of css3 multiple backgrounds, although this technique provides more opportunity for control. I'm also wary because if combined with :before, this creates the opportunity for at least 5 non-content critical images to be sucked down the pipes. Nationally we're still trying to achieve 100% cell phone coverage - forget high speed access - and that's before some design genius layers multiple elements to use as multiple hooks for even more non-content-critical image effects. I know that for some "first world country without high speed" is an oxymoron, but for others it's reality.

Unless on a controlled intranet, I'm also 50% thinking that solutions that apply to the widest range of versions are good given css3 is not yet standard, and many users will get stuck at ie8 because ie9 won't deploy on windows xp. The other 50% is thinking that as non-ie users tend to upgrade relatively rapidly, so targeting a limited set of partially understanding browsers risks coding for three groups of versions (non-understanding, partially understanding and understanding*). Legacy and non-legacy is bad enough ;)
* Where
non-understanding = doesn't recognise selected parts of css2.1 and css3 - like pseudo elements and css3 multiple backgrounds
partially understanding = recognises css2.1 but not css3
understanding = recognises both

</End seasonal grinch>

ignoring the :before/:after (and earlier FF) support for the minute, I *think* but am not sure that IE8 is wrong with it's stacking context hence I wanted to see if it works as described in IE9 yet.
I'm with those who believe ie is wrong, although haven't fully explored ie8. I said it much better in this thread - Legacy IE and z-index:-1 vs z-index:0 [webmasterworld.com]

I was sleep-befuddled when looking at this code, so could be missing something obvious, but the behaviour was inconsistent with the (incorrect) stacking I expected. That might be adjustments to ie8, but my hunch is that the (incorrect) local stack was further affected by the combination of anonymous box plus pseudo element.

So I think this code snippet is a great opportunity to consider the issue in detail, and worthwhile preparation for a future that has cleared ie6&7, but remains glued to ie8. Positioning questions at WebmasterWorld seem to go in cycles, but I still feel a really good article would be a valuable contribution to the forum library.

alt131

2:21 am on Dec 10, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hi suzy, In pursuing the "why" I found another approach.

Just note bug report #67 at James Hopkins [jhop.me] which identifies the issue is a bug. Follow the links to the person who reported it, and they have settled on the same technique (setting the image as content) for image replacement as you, but they are doing some intersting things with float, and backgrounds that are worth a look.

The confusing aspect of "why" is the difficulty figuring where anonymous content of the associated element should stack. I also found references to ff 3 and below being incorrect - which affects expectations, and that ie internet explorer may have switched from ie7's z-index:auto incorrectly establishing a new stacking context, to ie8 doing it for z-index:0 instead. (Coffee isn't hallucinogenic after all. ;). )

Recalling I was trying to trace stack levels and stack context creation, then manipulate both to slide the pseudo element up and down the z-axis. That is fraught with partial/buggy/wrong implementations of positioning, and gets really crazy.

Then I realised this is a display issue. The default is inline, but there are buggy inheritance issues from unexpected ancestors. Either way inline and block elements did not work, so I dusted off trusty old display:inline-block.

That should have limited negatives because at this level of manipulation coders will probably want to control the size and shape of the pseudo-element, it means avoiding stack issues if there are multiple ancestors and siblings, the pseudo element can be positioned using margins, and the content remains open for another image, text, or just empty.


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>My Title</title>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<style type="text/css">
/*Note that it is only necessary to declare z-index and positioning on the "pseudo-"ancestor. Also works for relative positioned ancestors (some solutions didn't), and you can use an image for content as well */
h1 {
position:absolute;
z-index:1;
width: 364px;
height: 126px;
border:1px solid red;
}

h1:after {
display:inline-block;
background: blue url(http://www.google.co.uk/images/logos/ps_logo2.png);
border:1px solid red;
content: " ";
margin-top:-20px;
width: 364px;
height: 126px;
}

</style>
<h1>My text</h1>
</body>
</html>

This dsiplays as designed in ie8, winsafari, and FF. Foti - would you mind testing in ie9?

milosevic

9:45 am on Dec 10, 2010 (gmt 0)

10+ Year Member



Heavyweight stuff!

Nice research and I think this technique is something I will definitely start using. Reading these posts is hurting my head at this time in the morning!

SuzyUK

12:27 am on Dec 11, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



But am now wondering what the question was. There's a difference between "why doesn't this work" , and "how can [this] be achieved" - although avoiding Appendix E earns extra points wink


thanks for the extra points hehe.. there really was no question, it was atypical of me stumbling from ahah moments but this time sharing as I went AND asking for a bit of help regards testing, without actually presenting a technique to test.. I do that now and again :)

thanks so much for your in depth looks, you have been busy! I recalled that IE had an issue with (explicit) auto setting a new context so I tried with/without it and various negatives..

but woah! you just hit the nail, I think.. haven't checked bug reports or latest status since IE9 is in works I presume it to be a done deal for 8, and I gave up! what we have now is what we have, I think 8 was the first/last shot at getting the real things in, but as no-one was using the pseudos it's missed the bar.. LOL

although hasLayout was "reportedly" removed in IE8, there was some weird display errors that lingered, not surprising really as you can't just take out a chunk and expect everything to run smoothly but everything most visual, or the IE8 'bugs', was "fixed" - much like IE7 itself on an 'as seen' basis thanks to them releasing it in beta to test

in this case your solution is as good as any other, by changing the element display to inline-block you have removed the need to position it, therefore avoiding the "flaky" stacking context - instead you/we have to use a bit of maths for the margins instead of the positioning co-ordinates.. good job!

I like it primarily because I love inline-block.. ;) but more because it avoids the need for the inline-block workaround seeing as how the pseudo is inline by default, however I dislike it because to "position" the background (content or background) takes another step..e.g. in my case I had to realise that the "child" pseudo then referenced its parent's line-height for its position.

in your example the image didn't line up and removing the top margin you can see that the child nestles right under the text, in mine because I'd stated the line height - so the plain text would center vertical - I just made my top margin equal that line-height

also in your case I would use relative: positioning for the ancestor so the text after flows without re-margining, if you use AP you will have to margin any following text too.

this is great thinking, I wasn't really looking for a solution as I never really asked "how can [this] be achieved" was just going with the flow of the discussion, it wasn't a test honestly - tough I think you get merit awards too ;)

let's face it we've successfully avoided "E"! .. I think this should work "fine in nine" because it doesn't involve the stacking context.. with the disclaimers that line-height needs to be explicitly declared to match the top margin of the pseudo

alt131

3:01 am on Dec 12, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



No troubles with "ahah moments' - prompts discussion, provokes thought, just useful to identify the different possible "questions".

All valid comments regards my code sample ... although is a work-around for inline-block still required?. I agree relative positioning has more real-world application than absolute, but at this stage of my testing seems more fragile (odd). Also, my example code was a proof of concept, so I deliberately margined the :after so it showed a little of the h1 text as proof the content was not showing through. Good spotting on the relationship to line-height! Note the posted code also unintentionally "proves" </head> and <body> are optional so much for complaining about browsers ... ;)

At this stage the example is not world-ready - this has some provisos - like yours, and I've broken it myself. But I've also broken winsafari several times so that might only prove I can break things ;)

Given the purpose of pseudo elements, I can't immediately think of a best practise application using a background-image but no content an :after. As placing the image in the content resolves the issue in your approach, another solution should not be required. Explicitly declaring a positon then using top/left is more intuitively logical, and as they ahve to be declared, reduces the opportunity for issues created by over-engineering as well

However the theory has me hooked, so I've spent today tidying up the suite I used to test z-index, position and display combinations across ff3.5, ie8 and winsafari4 to make it easier to extract conclusions. But I also want to track inheritance as that is already producing some (unhelpfully) interesting issues. All should also be tested against block/inline elements and replaced and non-replaced content, but I'm not sure I'll have time to get to that right now.

Avoiding "E" is getting more difficult. Brace yourself for some interpretation questions ...

although hasLayout was "reportedly" removed in IE8 ...
Humph. I believe I successfully triggered it several times before remembering it doesn't exist :) (In fairness there are so many variables it could be something else.)

IE had an issue with (explicit) auto setting a new context so I tried with/without it and various negatives
As above, apparently fixed in ie8, but now applied to z-index:0. At this stage of my testing I've put it in the same category as the (supposedly) fixed haslayout. As we know, negatives didn't resolve the issue of the associated elements content showing through. There are several possible reasons/"culprits", and in pursuing that I have a test that causes winSafari and ff to slide the :after below 4 parents to draw it just above the root. (Ie just slides it below 3.) Fun

Fotiman

6:23 pm on Dec 13, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month




This dsiplays as designed in ie8, winsafari, and FF. Foti - would you mind testing in ie9?

Not sure what the expected display is (only have access to IE9 and Chrome on my test system), but it looks the same to me in IE9 as it does in Chrome. :)

SuzyUK

9:59 am on Dec 14, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



although is a work-around for inline-block still required?


no, well spotted! i-b workaround only required for IE7 and below - was working on something at same time so it's just my bad mentioning it in here.. I was trying to visualise how it might work with JS inserted elements but wouldn't need it if I used spans anyway :o

Q: What were you trying that broke it, were you trying the floats and stuff?

I tinkered with your code a little and didn't actually manage to break it, though I made some changes and interestingly I discovered that it would only work with
inline-block
.. and not "block" or "floats which become blocks" - follows is the reason I think it's so - that is IE's natural workaround

from: Layered Presentation [w3.org]- Very close but didn't quite have to go to the dreaded "E" :)

Within each stacking context, the following layers are painted in back-to-front order.

1. the background and borders of the element forming the stacking context.
2. the child stacking contexts with negative stack levels (most negative first).
3. the in-flow, non-inline-level, non-positioned descendants.
4. the floating descendants.
5. the in-flow, inline-level, non-positioned descendants, including inline tables and inline blocks.
6. the child stacking contexts with stack level 0, and the positioned descendants with 'z-index: auto'.
7. the child stacking contexts with positive stack levels (least positive first).


if as we believe IE has a bug treating the positioning of pseudos properly i.e. it has a dodgy time with stacking contexts, that rules out 6 & 7 - the next thing nearest the user is 5, and my bold, it has been clearly spelled out to browsers what to do with inline-blocks (yes IE works with inline-table too, though that doesn't have support in FF!) and IE's support of them has always been longer/better than other browsers, so in this case I believe it simply always had that built in LOL.. so well done you for finding that..

here is some retweaked code with I think the minimal CSS:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>My Title</title>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<style type="text/css">
h1 {
width: 364px;
height: 126px;
padding: 10px;
background: #fee;
font: 40px/126px sans-serif;
border:1px solid red;
margin: 0;
}


h1:after {
display: inline-block; /* doesn't work if this is block, floated (block by default) or positioned! */
width: 364px;
height: 126px;
border:1px solid blue;

content:"";
background: blue url(http://www.google.co.uk/images/logos/ps_logo2.png) no-repeat 0 0;

position: relative;
left: 0;
top: -126px; /* need an line-height the equivalent to the box height to calculate */
}

p {margin: 10px 0; background: #dad;}
</style>
</head>
<body>
<h1>My text</h1>
<p>but where does the paragraph after go?</p>
</body>
</html>


Good Job! so this means we could be using this for simple image replacement today, feeding JS <spans> to IE7 and below for progressive enhancement, except I'm not sure that folks are willing to put FF3 in the "relegated to plain text" category yet either - but could we use jquery to target only FF2/3 via PE spans too?

------------------------------------------------

Given the purpose of pseudo elements, I can't immediately think of a best practise application using a background-image but no content an :after


Ah well you see I was actually thinking we could use this technique for multiple backgrounds as progressive enhancement until the CSS3 multiple backgrounds are more widely available, cut down on the divitis.. see I told you this wasn't just about "hiding " LOL - to be honest the text-replacement and the subsequent stacking issue is a side issue which tripped me up in the process.. so only the image replacement usage would need the "inline-block" workaround. In theory this should be quite well supported already barring FF2/3 and <=IE7

I'm not feeling terribly creative and I also wanted to be able to refer to an example of how this could be done.. so using this page: CSS3.info example [css3.info] and the images and HTML code from it.. (note it's still probably not the best example yet either because I can't actually see the need for the header to be generated content, but it's the most visual example I can find for now that should remain stable for reference, I think probably you could take the two techniques & "hide" the site title under the logo if you really wanted to, though I would suggest adding an element for the Site Title ;)

applying the CSS below that page can be achieved in a few more browsers than the multiple backgrounds supporting ones already - and though I see IE9 supports mb's I can't seeing us being free of 7/8 for a while yet..

body {padding: 10px 20px;}
p {margin: 1em 0;}

.example {
width: 720px;
padding: 170px 20px 11px 20px;
background: #fcf url(body-middle.gif) repeat-y 0 0;
position: relative;
}

.example:before {
background: url(body-top.gif) no-repeat 0 0;
content: url(banner_fresco.jpg);
text-align: center;

padding-top: 11px;
height: 151px;
width: 760px;

position: absolute;
top: 0;
left: 0;
}

.example:after {
background: url(body-bottom.gif) repeat-y 100% 0;
content: "";

padding: 0;
height: 12px;
width: 760px;

position: absolute;
bottom: 0;
left: 0;
}


now take that theory to some of the more creative rounded corner, irregular shaped, or popout (where a background image hangs over the edge of a box type thing) and I think I can see a use for it as it avoids the need for extra elements.. designs can be enhanced using the existing simple HTML code

anyway if I find a nicer example I might post that but referring to "trendy" designs is always dodgy as they can change and it's hard to imagine a picture without it and again TBH it's likely only of use for FF3.5 & IE8 without the use of script as the multiple background support seems to very good in more modern browsers (& ones users are likely to keep up to date that is) leaving FF3 & <=IE7 needing scripted solutions anyway - though does multiple backgrounds allow you to "overhang" the box edge?

anyway thanks again for the great chat & ideas..

SuzyUK

10:03 am on Dec 14, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Not sure what the expected display is (only have access to IE9 and Chrome on my test system), but it looks the same to me in IE9 as it does in Chrome.


Thanks too Foti, that would be fine then ;) I didn't think IE9 would have trouble with this method but good to have it cofirmed

btw.. expected display is to see the background image and NO plain text - IE8 was, in the OP, keeping the actual text on top of the image which is what we've be playing with, trying to get it gone.. but as K says probably not much real world use, as multi-backgrounds support is catching up (well except for IE7/8!)

oh and sssshh, don't tell her - but it could be an accessible hiding method ;)

[edited by: alt131 at 11:06 pm (utc) on Dec 24, 2011]

Fotiman

3:08 pm on Dec 14, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



What I was seeing was a Google image with red border on top of another box with border that looks like it has the text "My text" (though the bottom half of the text is covered by the image). So maybe that's not the expected behavior?

alt131

4:04 pm on Dec 14, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



That's the exact behaviour Foti, and thanks very much for checking.

Given the concerns over the lack of pixel-perfect positioning, I am wondering if a "proof of concept" is only used where I am. They are simple examples intended to demonstrate the effect of a specific theory/concept.

For that reason the :after (with the background-image) was deliberately placed so some of the text could still be seen. This "proves" the :after is being painted above the content of the associated element, and therefore "proves" that inline-block helped resolve that issue.

alt131

8:25 am on Dec 28, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Suzy, different paths - my test suite applies different values for display, positioning z-index, replaced and non-replaced etc to inline and then block associated elements, then tests in ie, op , ff and winsafari to track what is happening as there doesn't seem much hard research. I have hundreds of iterations, and even asked over in javascript (thanks fotiman) to try to achieve some of this programmatically as the suite is hard to manage manually.

Conversely, all I'm doing (as strategic Human Resource Managers would say), is "making tacit knowledge explicit" - I got inline-block without this, so wonder at the overall benefit. However, given we are both working through this, I thought it worthwhile to start recording what we know to save covering the same ground, plus might trigger other ideas. I'll start the list in a later post.

Q: What were you trying that broke it, were you trying the floats and stuff?
..... errrr... invalid code will do it ;)
Per above, nothing fun, but winsafari has produced oddities, and with the right combination of z-index, positioning, etc, it breaks. The precise iterations occurred around 2:30am one morning and that's no help - so put this on hold until I've fully eradicated coder error.

A note on float - I haven't fully investigated the technique but suspect the linked technqiues rely on css2, not css2.1 float behaviour. After a quick look:
  1. Positive: The pseudo's -
    • can be dimensioned without setting display (or position:absolute). (As you refer, they take block)
    • can be drawn outside the associated elements "containing box" using margins. (A fantastic way to avoid positioning issues.)

  2. Negatives: The pseudo's -
    • are restricted to floating in relation to each other and the content of the associated element - not other elements on the page
    • cannot be stacked on top of each other, or the content of the associated element (without a position and z-index) - and therefore do not resolve the issue that started this
    • rely on default z-index, and will be drawn on top of other non-positioned elements, but below positioned elements - which will cause layout issues in a complex page.
    • are subject to the same clipping issues as other options in more complex situations (such as transforms) - more later

Wow this is triggering all my pet irritations!
<irritation>Although float saves a few key-strokes over typing display, it does not resolve any other issue without adding additional code. I think the float examples are interesting because they raise doubts about the eradication of haslayout, but they look suspiciously like examples of floats being used to produce block behaviour. I think better to tell browsers exactly what is wanted: display:inline-block/block works, works across more scenarios ... and doesn't rely on an out-dated definition of something completely different I wanted css_3_ for Christmas - not css_2_, thank you ;) </end irritation>

I discovered that it would only work with inline-block
..... I should have said that out loud. Sorr-eeee!

Layered presentation - that explains a simple example, but wouldn't a positioned element in a nest with all positive z-index's be painted per 8 - regardless of display? ... I'm sure something else is going on.

Some thoughts on "E" Conversely, although ie has the overall concept of locstacking context's wrong, it may be "more correct" in details - such as painting. After brief forays into "E" I think it is unwise to assume stack order and painting order are the same. "E" is vague on anonymous boxes, confusing as to replaced elements, and nothing on generated content. When you consider we are have also decided to position inline elements that do not appear in the document tree, I don't think it wise to assume where anonymous content might be painted.

Tweaked code. I'm just loathe to put a position on the pseudo but no position on the associated element as a standard technique. I am sure it has broken - but let me keep checking for code error.

I recognise it limits the negatives of positioning, but scenarios with more complicated ancestor/descendant relationships create different local stacks if left to auto, and position on the associated element guarantees the pseudo's local stack. I can hear you gasping at me suggesting over-engineering, but this isn't just about painting the content: In some browsers negative z-index's will render the entire pseudo below everything except the root - or not - depending on the local stack. That may have implications for layering pseudo's to fully exploit multiple background effects. So (having spent 12 minutes searching for one tucked under everything but the root), I'm inclined to think a couple lines to explicitly position and z-index the associated element may outweigh the time spent locating where a pseudo has been painted.

...feeding JS <spans> ... could we use jquery to target ... was actually thinking we could use this technique for multiple backgrounds
I'm pretending this does not open the door to a gazillion server hits to download js to force recognition of pseudo's that downloads gigs of background-images to make things nice for visual users.
Who, as eye-tracking heat maps show, don't look ;}
But seriously, yes, yes and yes. just the bogey of code management. In a carefully managed system with rigorous progressive enhancement processes, all good. My only qualification is reliably accessing the pseudo given it doesn't appear in the document tree. (But I'm sure fotiman will have some suggestions if he is still watching.)

That said, time for fun -

alt131

3:50 pm on Dec 28, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Fun stuff - fancy borders, border slants, but not pointed stars

Birdbrains fancy borders
Birdbrain produced an amazing solution that must be seen to be appreciated at [webmasterworld.com...] This version requires only two elements:
/* birdbrains fancy border - css could be further simplified as all pseudo's are absolute and have same dimensions */

div.birdbrain {
/* position relative to control the pseudo's */
/* it is possible to leave position off the div, and instead set position, display and z-index on the pseudo, but that requires more code.*/
position:relative;
border:4px solid #ddd;
padding:20px;
width:240px;
height:300px;
}

div.birdbrain:before, div.birdbrain:after {
/*no display required because absolute pseudo takes dimensions */
position:absolute;
/*it is necessary to position the pseudo because it respects padding on the associated element*/
top:0;
width:20px;
height:20px;
content:"";
border-top:4px solid #000;
}

div.birdbrain:before {
left:0;
border-left:4px solid #000;
}

div.birdbrain:after {
right:0;
border-right:4px solid #000;
}

.birdbrain p {
position:relative;
padding:20px;
margin:10px;
background-color:#eee;
top:-10px;
left:-10px;
width:200px;
height:260px;
}

.birdbrain p:before, .birdbrain p:after {
position:absolute;
content:"";
width:20px;
height:20px;
bottom:-20px;
border-bottom:4px solid black;
}

.birdbrain p:before {
border-left:4px solid black;
left:-20px;
}

<div class="birdbrain"><p>Birdbrains amazing fancy borders!</p></div>


css3.info multiple backgrounds
so using this page: CSS3.info example [css3.info] and the images and HTML code from it..
All respect to the css3.info team, but this seems a good example of the worst to come. It really requires a single header image, and I'd like a real (styled) uri that was clickable - it's wasted seo and I tried to click before realising it wasn't a link. (This also put me in mind of the "popular" opaque strips, but I haven't tested opacity yet). This took a couple of minutes - it isn't pixel-perfect, needs refining, but reduces your code even more.
Note the use of the pseudo background-colour because the div content is painted higher in the stack - the advantage of using the header for real content, not a carrier for images.
div#css3_info {
width:720px;
height:200px;
border:3px double #C6C6C4;
padding:6px;
}

div#css3_info:before {
width:720px;
height:200px;
/* url modd'ed to save css3 hits */
background: #F1EFED url(break image link- [css3.info...] -9px 0 no-repeat;
content:" ";
position:absolute;
}

div#css3_info ul {
display:block;
position:relative;
top:125px;
padding:0;
}

div#css3_info ul li, div#css3_info ul li a {
display:inline-block;
padding: 0 1px;
}

div#css3_info h1 {
position:relative;
top:105px;
}

<div id="css3_info">
<ul>
<li><a href="#">My breadcrumbs</a> \</li>
<li><a href="#">My breadcrumbs</a> \</li>
</ul>
<h1>My Heading</h1>
<div>



Can position:fixed be used to create a "scrolling" logo effect - think max design?
Apparently not in ie8:
  • pseudo's without position will inherit position:fixed from the associated element, and the pseudo's will "scroll" with the associated element.
  • op, ff and winsafari recognise position:fixed on the pseudo, and the pseudo can be "fixed" independent of the associated element. It will then scroll while the associated element remains static.
  • however ie does not recognise position:fixed on the pseudo, so it cannot be "fixed" independent of the associated element.

Do pseudo's accept transforms/filters - think "web2" stars/badges?
The results are similar to position:
  1. In all browsers a transform such as rotation applied to the associated element will be inherited by the pseudo
    • In op, ff and winsafari a transform can be set on just the pseudo, or an inherited pseudo changed
    • In ie a transform cannot be set on just the pseudo, and a transform on the associated element cannot be "undone".
    • In ie, applying a transform prevents the pseudo's being positioned outside the associated element. Depending on context, it may be possible to set padding or a border to create a larger containing block. a negative clip can be applied to pseudo's independent of the associated element to create a larger containing block, but ie does not recognise clip on a pseudo once a transform has been applied.
    • In ie transforms are applied to the borders, and anonymous boxes (such as text), but are not automatically applied to replaced content that has a z-index (see this in action in the polaroid example below)

  2. Transforms such as gradient effects are not inherited
    • As for other transforms, they cannot be applied to pseudo's independently in ie.
    • ie accepts only one transform per item, so it is not possible to rotate the associated element then apply a gradient effect.

  3. In ie, only the last transform in the code will be applied
Most results are predictable based on expected inheritance (Property Index [w3.org]), but browser variations make it worth testing.
I also trialled using open- and close-quote to see if that might work magic, but it was not much advantage especially as not recognised by winsafari.

Making shapes - cross browser border-slants
ie does not accept a transform on the pseudo, and filters are complicated to use, or too simplified (for example, rotate does not include a 45deg turn), plus I've found transforms noticeably slow. There are js libraries /behaviours to force understanding in ie, but the old stand-bys still work.
h1#cross-browser_border_slants {
position:relative;
/* for control give an explicit line-height or height - hat-tip to suzy*/
line-height:40px;
/* Create a space for the pseudo */
/* Padding applies to pseudo's so position the text away from the pseudo's by giving the pseudo's a negative margin or left the same length as the padding. It is also possible to set a border on the associated element, then negatively position the pseudo on top of the border */
padding-left:50px;
}

h1#cross-browser_border_slants:before {
position:absolute;
content:"";
/* Remove the effect of padding on the pseudo */
left:0;
border-width: 0 20px 20px;
border-style:solid;
border-color:transparent;
border-bottom-color:navy;
}

h1#cross-browser_border_slants:after {
position:absolute;
/* Remove the effect of padding on the pseudo, then push it down below the :before = the pseudo border-width */
left:0;
top:20px;
content:"";
border-width: 20px 20px 0 20px;
border-style:solid;
border-color:transparent;
border-top-color:red;
}

<h1 id="cross-browser_border_slants">Cross browser border slants</h1>


A quick Polaroid photo album
Colours etc need considerable refinement before this is realistic, but is quick to code, and demonstrates how many visual effects can be achieved without using js or adding html elements. The lower "photo corners" could be created by hanging the pseudo's off the caption if it was <p> - similar to the birdbrain eg. It also works (without the pseudo photo corners) in ie7.
div#polaroid {
position:relative;
left:100px;
width:150px;
height:200px;
/* Outline is tempting, but it has too many varying issues */
border:1px solid #aaa;
padding:10px;
text-align:center;
/* ie is too troublesome for a transform, but gets a zoom on hover */
-webkit-transform: rotate(-5deg);
-moz-transform: rotate(-5deg);
-o-transform:rotate(-5deg);
}

div#polaroid:hover {
zoom:1.1;
-webkit-transform: rotate(0deg) scale(1.25);
-moz-transform: rotate(0deg) scale(1.25);
-o-transform:rotate(0deg) scale(1.25);
/* un-comment the filter in to see the effect of a transform when a replaced element has a z-index */
/*-ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.7071067811865476, M12=-0.7071067811865475, M21=0.7071067811865475, M22=0.7071067811865476,sizingMethod='auto expand')";*/
}

div#polaroid img {
/* replaced content creates special issues, position and z-index so it displays below the pseudo (display:inline-block does not work in this case). This could be resolved by setting the image as a background-image, but it is actual content that really belongs in the html */
position:relative;
z-index:-1;
display:block;
margin-bottom:0.6em;
/* padding and background for visual effect because the image has a white background */
background-color: #eee;
padding:1px;
}

div#polaroid:before {
position:absolute;
left:-4px;
top:-4px;
content:"";
border-width: 20px 10px 10px 20px;
border-style:solid;
border-color:#eee transparent transparent #eee;
}

div#polaroid:after {
position:absolute;
right:-4px;
top:-4px;
content:"";
border-width: 20px 20px 10px 10px;
border-style:solid;
border-color:#eee #eee transparent transparent;
}
<div id="polaroid">
<img src="http://www.google.co.uk/images/logos/ps_logo2.png" width="150" height="150" alt="My image" >
My caption
</div>

tanfa re-visited
... because I couldn't find a "kilroy-was-here" style pic to drape over the top of an element, this neatly takes advantage of the difference beteen relative and absolute positioning - and the pics are lovely:

h1#tanfa {
font-family:"times new roamn", serif;
color:#AA0000;
width:200px;
margin:0 auto;
position:relative;
}

h1#tanfa:before {
/* relative makes the default position relative to the header text -also why this is the before rather than the canopy, which is visually firt */
position:relative;
display:inline-block; /* takes dimensions without disturbing default location */
padding-right:10px;
height:16px;
width:13px;
content: "";
background: url(h2bgr.gif) no-repeat;
}

h1#tanfa:after {
/* absolute makes it easy to dimension this larger than associated element and then position outside the heading*/
position:absolute;
left:-200px;
top:-80px;
content: "";
width:396px;
height:126px;
background-image: url(css-canopy1.gif);
}
<h1 id="tanfa">CSS - index</h1>

[edited by: tedster at 2:30 pm (utc) on Dec 29, 2010]
[edit reason] fixed the link [/edit]

SuzyUK

10:32 am on Dec 29, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hope you had a good Holiday.. got an unexpected afternoon off work yesterday, so came to have another look at this and you're back too, with some interesting thoughts :) - and those examples added later.. oh what fun.. great post.. and you took me back a bit lol.. hadn't even looked at that tanfa code since archiving it a few years ago, extra div heaven when it was written.. and if I remember I would've liked a more overhanging type look to it, but it's oh so old it's almost embarassing ;) - like Birdbrain's borders too, though I might be tempted to do them with one image only revealing the part of the corner required.. all nice examples!

----
anyway this reply was typed in reply before reading your second post and is the result of determining the difference between stacking contexts or stacking levels/painting order.. the terminology doesn't help!


Layered presentation - that explains a simple example, but wouldn't a positioned element in a nest with all positive z-index's be painted per 8 - regardless of display? ... I'm sure something else is going on.


"per 8" is that 8 from appendix "E" you're referring too?, not sure of your question here because the example which originally started this thread is a simple example, it doesn't actually need to have stacking contexts involved to show it - The MDC explains a complex scenario [developer.mozilla.org] quite well. (down at the bit about 'version numbers')

-----
This case is actually a simple one, it can be demonstrating without using z-index or creating stacking contexts at all.. that way relying on the "7 step" painting order (or stacking levels :o) The :before and :after elements are within the same stacking context as the H1 "anonymous" text line box, as far as I can tell you cannot lift them out of it and shouldn't need to, all that the z-index values would be doing for them is affecting their layer order of each other. and as this is not needed the sample can be run without them relying on the default, the result is the same.. nae working!


in the simplified sample below we see the IE8 problem quite clearly:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Pseudo Element Stacking</title>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<style type="text/css" media="screen">
#logo, #logo2 {
position: relative; /* to make containing block */
top: 0;
left: 0;
border: 1px solid #00f;
height: 180px;
width: 500px;
text-align: center;
font: 40px/2 Georgia, "trebuchet ms", sans-serif;
padding: 10px;
color: #00f;
background: #ccc; /* to show background of background :o! */
}

#logo:before, #logo:after,
.b, .a {
font: 20px/1.5 verdana;
width: 280px;
height: 100px;
position: absolute;
border-width: 3px;
border-style: solid;
text-align: center;
color: #fff;
}

#logo:before, .b {
content: "before text";
background: #f00;
border-color: #0f0;

top: 30px;
left: -10px;
}

#logo:after, .a {
content: "after text";
background: #080;
border-color: #0c0;

top: 50px;
right: -10px;
}

/*
#logo:after {
position: relative;
display: inline-block;
top: -120px;
right: -125px;
}
*/
</style>
</head>
<body>
<h1 id="logo">Anonymous text Anonymous Text</h1>
<p>Some following text</p>
<hr>
<h1 id="logo2"><span class="b">before text</span> Anonymous text Anonymous Text <span class="a">after text</span></h1>
<p>Some following text</p>
</body>
</html>


this is rendering (well #logo part anyway)

1. #logo = background
2. #logo:before = background
3. #logo:after = background
4. #logo = content
5. #logo:before = content
6. #logo:after = content

by no stretch of reading the above simple "7 Step" Painting order OR Appendix E [w3.org] can I reconcile that rendering..

the nearest I can figure is that it should be purely section 7:

Otherwise: first for the element, then for all its in-flow, non-positioned, block-level descendants in tree order:


where h1#logo is the element and "anonymous text" is the in-flow descendant, an anonymous inline box - though overall 7 is not right as I'm positioning the :before and :after descendants

or it should be 7.2 for the original "anonymous text" line box i.e. "Otherwise, for each line box of that element:"

then 8 for the two positioned descendants:
8. All positioned descendants with 'z-index: auto' or 'z-index: 0', in tree order.


I liken this to how part 2 of my code is laid out giving a very definite, explicit tree order to the code makes it works as you would think, no change to the CSS, stacking context or anything else..

either way I can't see how they can split up the painting descendant elements positioned or otherwise, and even if they did why isn't the
:before
text under the 'anonymous' text? That would at least show some sign that there was an attempt at a tree order and perhaps something else going on? then we could say it's painting all the backgrounds then all the text in the right order (even though that would still not seem right) .. it's quite clear, to me anyway at the top of that "E" page that the descriptions refer to this:

Element
In this description, "element" refers to actual elements, pseudo-elements, and anonymous boxes. Pseudo-elements and anonymous boxes are treated as descendants in the appropriate places. For example, an outside list marker comes before an adjoining ':before' box in the line box, which comes before the content of the box, and so forth.


I think it's just IE and that they've missed a basic bit out, like telling their browser that pseudo elements are a descendant of the element they're attached to, without being an inline-bock too ;)

alt131

11:08 am on Jan 2, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



If a picture paints a thousand words, this paints almost 3. Plus exceeds maximum post length. For anyone still awake a second instalment tries to connect this to the recs and what we have been seeing.

I think Tanfa underscores the time-less elegance of whitespace. I didn’t imagine it would/should cause embarrassment - but of course I apologise if it has –quite unintentional.

birdbrains solution is fascinating! Of course, "someone" suggests images - roll on background-clip ;) Noting the egs aren’t "showcases", just fun and demonstrating some general issues/opportunities and image-less creativity too.
"per 8" is that 8 from appendix "E" you're referring too?,
Too long after bed-time – should be "per 7" - a reference to your list from section 9.9. "8" from Appendix E isn't relevant - no wonder you were confused. But this highlights the ambiguity and incompleteness of the stacking model (whether the 7 point list from section 9.9, or the 10 points in "E"). I initially read it as a hierarchy, but later "points" don't always seem to "over-ride" the earlier ones. As you refer, one issue is the language (exacerbated by me using it past bed-time.) My comment that stack order and painting order may not be the same was a poorly put reference to a cluster of thoughts:

Where is the pseudo?
We know an elements components are painted/rendered (I no longer think these are inter-changeable) in a certain order. Years ago Jon Hicks produced a 3d box model [hicksdesign.co.uk]:
1. margin
2. background-color
3. background-image
4. padding and content
5. border.
There was a change in css 2.1 (see C.2.54), so I now think border is painted much earlier. But overall we assume the components will be painted in an order, and do not "split". That is, all of "Element A's" components would be drawn before starting to draw the components of "Element B". More relevant here, that one elements component's are not painted between the components of another element. My tests suggest this isn’t the case, hence I am now thinking in terms of the "stacking order” (of elements) and the "painting order” (of the components).

"E" deems pseudo’s a descendent, so that puts them in the "padding and content" layer. I don’t believe padding and content are “paired” as Hick’s diagram suggests - the w3 box model addresses them separately - the image at section 8 underscores that, as does the definition of "content edge" (As an aside, note the definition of rendered content (un)helpfully confirms it does not specify replaced elements.).

I don’t think "E" has little about content because the components are an unbreakable "group". If they were "E" would deal with the relationship between elements, not the components of elements. I keep coming back to section 9.9:
" A stacking context is atomic from the point of view of its parent stacking context; boxes in other stacking contexts may not come between any of its boxes."
It's intuitively correct, but I can put a pseudo between boxes in other stacking contexts, such as multiple elements with multiple absolutely positioned or fixed pseudo’s. They do not participate in the other element's stacking context, but they definitely move between boxes in those other stacking contexts. In my head this is consistent with ”Stacking contexts are not necessarily related to containing blocks.” (9.9.1). I don’t see this as lifting the boxes out of their stacking order (as you refer) . What I see is the recs failing to properly account for manipulating the x,y and z-axis at the same time. In my head it is resolved by accepting that “stacking order” (z-index) is not the same as “painting order” (an elements components).

What is "E"?
It claims to be a painting order of descendent elements, which suggests a hierarchy (the last on the list will be the closest to the viewer), but some elements aren't provided for, and the qualifications, incompleteness and language sometimes require a comparative approach inconsistent with a true hierarchy. Some parts clearly refer to an element that could only be the "parent" ... and at other times “element” could be parent, child or grandchild.

There must be at least four different painting/rendering “stacks”:
1. tree order (y-axis)
2. line boxes - (x-axis)
3. the box model – the vertical stacking of an individual elements individual components
4. stacking context/z-index (z-axis)
Horizontal is easy because line boxes are laid out one after the other. Vertical is messy because the recs allow expansion and collapsing. Overall I don’t believe "stacking" has been fully explicated, and “E” certainly doesn’t deal with the relationship between these stacks with any clarity or certainty at all. So maybe browser manufacturers were just as confused and took a "best guess" - or gave up and did their own thing: What we see may not be explained by the recs because it wasn’t designed according to the recs ;)

What is a pseudo?
This is critical and not completely clear. After my new tests I’m certain the behaviour in the egs can be traced to the default behaviour of vanilla elements. Lots of detail below, but when you add the complications of applying properties that change core attributes, I think the “what is” becomes critical in answering the “why”. In part because I still think this is a display issue, not a z-index issue. There must be “higher” consideration of these things - have you noticed that the Editors Draft of the "default" style sheet (Appendix D) removed the white-space:pre for pseudo's?
This case is actually a simple one, it can be demonstrating without using z-index or creating stacking contexts at all…
I take the opposite view –the recs make this complex by not dealing with all the issues, and the egs do create new stack contexts, plus use properties that trigger known issues. Or perhaps browsers are as confused as we, or just wrong, so the egs don’t work per the recs because they are just a “best guess” ;)

Lets find the pseudo
I tested vanilla elements, then applied background-color/image, border, paddings and margins to the element and pseudo's. Did that for pseudo's associated with block and inline elements, both :before/:after, and with background-color/image plus different content. I can post my code, but in terms of what is being displayed by browsers this is the “drawing/painting that I saw in ff3.5, Opera10.5, winsafari5, ie8. When reading this:
  • Results are the same for all browsers - even ie
  • I've recorded what I "see" from top/left to bottom/right.
  • For "content" read "anonymous content" (I've been specific when referring to non-anonymous descendents and pseudo's ).
  • When using outlining in FF webdeveloper only the content of the :before is outlined. The whole of an :after (borders/padding etc) is outlined. This difference informs something- I don’t know what
  • vast differences between vertical and horizontal laying out, and the behaviour of block/inline descendents – see notes below.
This is huge detail –the bits most relevant to the OP are the notes on laying out descendent elements in a block associated element, and using an image as content.
The painting sequence as I see it:
  1. Associated element margin. For inline: left/right only applied to the first line
  2. Associated element border
  3. Associated element background-color/image
  4. Associated element padding. For inline associated elements: left/right only applies to the first/last line of content.
  5. :before left/right margin (top/bottom not applied)
  6. :before border
  7. :before background-color/image
  8. :before padding
  9. :before content
  10. Associated element content (Note anonymous, inline and block descendants all behave the same, with the components of border, background-color/image and content painted in the above sequence, and therefore above the :before, or below the :after)
  11. :after left/right margin (top/bottom not applied)
  12. :after border
  13. :after background-color/image
  14. :after padding
  15. :after content
How they are laid out and interact is more interesting

Laying out
Laying out seems to be taken from the content edge (or padding edge if they are the same) for vertical measurement, border edge to border edge for horizontal
  1. General Layout
    • For :before's, the left border of the pseudo starts at the left content edge of the associated element. The :before content starts at the top content edge of the associated element, and the next content of the associated element starts at the right border edge of the :before. Top/bottom borders are not allocated space so the :before top border is drawn over the associated elements top border, and the :before bottom border is drawn under the next line of content . This applies whether the associated element is block or inline
    • :after applies the same "rules", so the left border of the :after commences at the right content edge of the associated elements previous descendent. The top border is painted over the previous lines of the associated elements content, and the bottom border is painted over the associated elements border. The right border of the associated element is painted after the right border of the :after. Because a block associated element will compute a width to contain the contents, there will be a visual “gap” between the pseudo and right border if the :after falls on a "short" line.
    • I could be wrong on measuring from content edge but doing so allowed me to predict the “position” of every pseudo, descendent and other content, plus their individual components. It became even more simple once I realised that first line content edges also cleared each other.
      My defaults applied no height or line-height, but a test to manipulate using line-height confirmed that laying out is taken from content edge.
    • Fascinating is that although top/bottom borders sort of “collapse” and are not allocated vertical space, they are given priority and painted uppermost (top/:before bottom /:after), plus outline is drawn around them.

  2. I imposed a width on the overall container to force the content of the associated element to wrap without setting an explicit width to complicate things.
  3. inline associated elements
    • The above painting sequence applies "line-by-line", so the border/background/content sequence starts again when content wraps to a new line. Because vertical laying out is from content edge, the borders/backgrounds/content of the “new line” are visually “on top” of the preceding line, including the border/backgrounds/content of any descendents. I call this a “pile” to avoid confusion with stack / layering / painting etc.
    • :before Borders/margins/padding are not included in content edge to content edge measuring, so later content of the associated element will be visually piled on top of the border/background of an earlier :before.
    • :after As expected in a top-bottom rendering sequence, :afters (border, background/content) are painted uppermost regardless.

  4. Block associated elements are different:
    • A block descendent clears the preceding line of content and top/bottom border of the block descendent do not “collapse” and are given space. If a block descendent follows another block descendent all top/bottom borders are drawn in and given space. Laying out seems border edge to border edge – not content edge
    • BUT inline descendents measure content edge to content edge. Top/bottom borders are allocated no space, and if borders/padding/margins size the element taller than line-height, borders/ background/ content overlap, with the border/background/content of the later descendent drawn on top of all the components of the earlier descendent.
    • … so block descendents are laid out from border edge, respect their dimensions (even implied) so do not overlap, inline elements are laid out from content edge to content edge, so will overlap, with the border/background/content drawn uppermost in descending tree order.
    • block/inline descendent combinations are more interesting:
    • If a block descendent follows or precedes an inline element or anonymous (inline) content, the measurement is from content edge of the inline descendent to border edge of the block descendent so that: If the “Element A” is inline (whether anonymous or explicit), and first in the code, and “Element B” is block, “Element B draws its top border and background at “Element A’s” bottom content edge. Element B’s border and background will be under “Element A’s” border/ background/ content. “Element B’s” first line of content is painted after “Element A’s” bottom border edge, and on top of Element A’s border and background.
    • If the inline descendent is after the block descendent, the top border of the inline descendent is drawn at the block element’s content edge, and the border/background/content of the inline descendent painted on top of the earlier block descendent.

  5. :pseudo’s on block associated elements act like inline descendents (which they are)
    • :before plays like an earlier inline descendent – so a later inline descendent is measured content edge to content edge, but the border/background/content of the later inline descendent will be drawn on top of the :before. This means a later inline element with large padding/borders will be painted completely on top of the :before – although the content will always be laid out content edge to content edge.
      A later block descendent starts its border edge at the :before’s content edge, with the border and background drawn below the border and background of the :before, and the content of the block descendent above.
    • This gives lots of room for visual effects as the background of a large :before will be painted alternatively on top of later block descendents, and behind later inline’s.
    • :afters, like inline descendents, are painted on top of everything that precedes them. Rather boring ;)


Rendering content
The type of content is also relevant:
  1. If content:"[white-space]"
    • firefox draws borders, collapses white-space and respects all padding and margins.
    • winsafari does not draw the pseudo < --- odd
    • Opera draws borders, collapses white-space except for :after on inline associated element, and after on a block associated element with a margin, respects margins and padding.
    • Ie draws borders, collapses white-space for :before (but not after), and respects padding and margins

  2. If content: “”; (no whitespace)
    • firefox as above
    • winsafari draws borders, and respects all margins and padding
    • Opera draws borders and respects all margins and padding.
    • Ie draws borders and respects padding and margins

  3. Content = "\A[whitespace]\A"
    • all as for whitespace
    • Interesting because white-space pre-line should break respect newlines, and with positioned pseudo’s it will.

  4. More interesting: Content = an image
    • All browsers paint and “pile” and lay out the pseudo as for any other content, but computing the pseudo dimensions is another thing:
    • If the image height is less than the default line-heightthe pseudo height is the default line-height. The image is positioned on the text baseline. The content edge is at the computed line-height, and borders/padding/margins behave as expected
    • BUT if the image height is greater than the default line-height:
    • For block/inline associated elements and :before/:after– The image is drawn the size of its dimensions, but the pseudo height appears to be the default computed line-height. The image remains on the text baseline and protrudes upwards and the pseudo borders are drawn around the computed line-height, not around the full height of the image. (Which indicates borders are painted behind content)
    • For :before on a block associated element the pseudo is laid out so the top of the image starts at the top border edge and the first line of content (including pseudo) is “pushed down” the remaining height of the image. This is contrary to usual layout which had the top border and padding expand upwards over the border of the associated element.
    • For :after on a block element the pseudo content edge bottom aligns with the last line of content, but the entire last line is pushed down the remaining height of the image.
    • Padding/margins and other descendents are laid out as expected, except vertical dimensions appear to be computed as if the line-height was the total height. For example, padding edge is line-height + padding height (not image height +padding height).
    • For :before, later inline elements will overlay the :before (including the image content if the following element is large, and block elements are drawn with the border and background under the :after, and content on top . The image remains on the text base-line of the first line, so there is never an overlap.
    • :after is similar except the top of the image starts at the bottom border edge for a block descendent, and the bottom content edge for an inline element. The last line is pushed downwards the remaining height of the image so there is no overlap with block descendents, and the image overlays the order/background and padding as you would expect for an inline.
    • For :befores on inline associated elements there is no downwards “push”: The bottom content edge of the pseudo is vertically aligned with the bottom content edge of the other first line of content and the image protrudes upwards over the associated element border. BUT the whole of the associated element is pushed downwards unless the associated element also has a margin or a padding. It is a proportional amount but I haven’t yet decided what it is proportional to.
      Otherwise :before’s behave as expected.
    • :afters on inline associated elements align themselves with the content bottom of the previous line and “push” the whole of the last line down in the same way as :afters on block elements. They are interact with padding/margins and inline descendents in the same way as ordinary :afters.

SuzyUK

2:05 pm on Jan 2, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Happy New Year!

OMG K it's going to take a lot of time to get through all that I appreciate the time you've put in, looking forward to part 2..

I think though just in case anyone is confused by all this (I am!) that in reference to my OP - we have established that there is something uniquely different (wrong?) about the IE8 rendering/display and that it seems it is not be the same in IE9, as in it seems to behanve like the rest of the main browsers.. is that right? sorry just clarifying before we step into the recs ;)

"per 8" is that 8 from appendix "E" you're referring too?,

Too long after bed-time – should be "per 7" - a reference to your list from section 9.9. "8" from Appendix E isn't relevant - no wonder you were confused. But this highlights the ambiguity and incompleteness of the stacking model (whether the 7 point list from section 9.9, or the 10 points in "E"). I initially read it as a hierarchy, but later "points" don't always seem to "over-ride" the earlier ones. As you refer, one issue is the language (exacerbated by me using it past bed-time.) My comment that stack order and painting order may not be the same was a poorly put reference to a cluster of thoughts:


No worries, I wasn't sure I was missing something.. why I asked in't first place hehe... and yes that's exactly what I was getting at too, the original example I would've indeed expected to paint/display/render as "per 7" - then when it wasn't, removing nos. 6 & 7 from the "equation" as they both involved "positioned" elements - to my thinking, and gut feeling about IE past problems this could mean they have the possibility of being involved in a "z-index/stacking issue" left #5 as the next nearest to the viewer .. in there we find the words "inline-block" therefore all ambiguity is removed for IE who indeed treat an inline-block as we would expect no matter if a pseudo or not.

Anyhow, carry on the good work - I'll need sometime to read and digest that post above!

thx
Suzy

[edited by: alt131 at 11:16 pm (utc) on Dec 24, 2011]

alt131

7:26 am on Jan 24, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Good idea to clarify what we are doing: I want to know why this is happening, so this has really moved to exploring broader issues associated with the pseudo elements because we know little about them.

… ie is different – but is it “wrong”?

After hours on this I still think it is more than stacking, and that display informs. I have some explanations, but more unanswered questions, and still think all of the following are relevant:
# where it exists in the tree (tree order)
# whether it participates in the flow
# whether it participates in the block or inline formatting context
# what stack context it participates in
# where it is painted in the stack levels of that stack context

This is a summary of the detail and tests, and to summarise the summary, this code sample relies on rendering for which:
  • The recs contain fundamental and fatal contradictions, plus lots of lesser, but informing ambiguities
  • Inline-block is the magic bullet because it explicitly directs the browsers to apply characteristics that avoid the contradictions and ambiguities
  • I am no longer certain ie’s absolute and z-indexing model can be viewed as completely wrong as traditionally thought
  • Inability to inspect the pseudo’s prevents me establishing exactly what is going on but my testing indicates the behaviour of non-ie browsers is not always conforming either.
  • ie’s behaviour can be explained by reference to the recs. Non-ie is more difficult

The 9.9.1/”E” Conflict
Per 9.9.1 positioned elements with z-index:auto do not create a new stack context for descendents BUT Per “E” positioned elements with z-index:auto do create a new stack context for their descendents.
That’s a direct contradiction. It isn’t an option to implement one or other then treat the issue as “case closed” because the creation of a stack context is relevant to other parts of the recs. Further, stack orders are not confined to containing blocks, and 9.9.1 applies “document-wide”, so a rigid application of 9.9.1 would produce very stupid stack orders - and my theoretical models indicate browsers have not gone that far.

Background/borders
In combination 14.2 and 8.5.3 provide that background/borders of elements that create a new stacking context are painted at the bottom of the elements stacking context.
Per “E”, that means #logo participates in the :root stack, while creating a new stack context for its descendents. Per “E” the pseudo’s will also create a new stack context for their anonymous text, while participating in #logo’s stack. Per 14.2/8.5.3 the pseudo’s background/border should be painted at the bottom of the pseudo’s stacking context – and that is the stacking context created by #logo.

My tests at the defaults plus variations of position:relative/absolute on the associated element and pseudo’s produced consistent stacks cross-browser EXCEPT when position is set to absolute:
# If there is no position set on the associated element (and therefore does not create a new stack context per “E”) ie will paint the pseudo background/border below the associated element. (It will actually bury the pseudo background/border below all non-positioned ancestors.)
# If the associated element has an explicitly set position (so that per “E” it creates a new stack context for its descendents), ie paints the pseudo background/border above the #logo background/border, but below the anonymous content.

Sound familiar? ;) Applying the 9.9.1 stack order to the simplified code sample:
  1. the background and borders of the element forming the stacking context.
    --- #logo’s background/borders because #logo is positioned with z:index auto, so per “E” creates a stack context
  2. not relevant the stacking contexts of descendents with negative stack levels
  3. not relevant a stacking level containing in-flow non-inline-level descendents.
  4. not relevant stacking level for floats and their contents.
  5. a stacking level for in-flow inline-level descendents
    --- #logo’s anonymous text
  6. a stacking level for positioned descendents with 'z-index: auto', and any descendant stacking contexts with 'z-index: 0'.
    --- The pseudo’s. The pseudo itself participates in #logo’s stack context, and per 14.2/8.5.3 the backgrounds/borders are sent to the bottom of that stack. That means just above #logo’s background/borders, which per this hierarchy, means below #logo’s anonymous content.
    Then the pseudo’s anonymous content – which starts in this layer, and therefore is in a layer higher than #logo’s anonymous content – so is painted higher.

  7. not relevant the stacking contexts of descendents with positive stack levels
This also explains why the desired design was achieved by using an image as content, and why setting a higher z-index on the pseudo cannot “lift” the background/border above the anonymous content.

But it doesn’t explain why non-ie are different, why ie only does this when position is absolute, or why the pseudo ignores z-index. That would traditionally be attributed to ie’s “wrong” absolute and z-indexing model, but after reading “E” myself, I’m no longer certain that is the complete answer. So what is it about absolute?

What is an absolutely positioned pseudo?
I don’t think we can be sure ;)

Per 9.3/9.6, absolutely positioned elements are removed from the flow, so have no impact on later siblings. They create a containing block, (but not stacking context) for contents, which do not flow around other boxes. BUT per 12.1 pseudo’s locate content before and after an element's document tree content AND interact with other boxes as if they were real elements. Another conflict - OR single-sentence explanation. Also note 12.1 references content – which is not the same as background/border. More license.

Interaction with other elements per 12.1 requires both a stacking context and a formatting context. Per 9.4.1 absolutely positioned elements (and inline blocks) establish new block formatting contexts. BUT creating a block formatting context is not the same as the element being block itself, AND 12.2 explicitly states display determines whether the pseudo content is placed in a block or inline box.

9.2.2.1 emphasises that a block box has a block box inside it, it is forced to contain only block boxes. BUT, the Editors draft amended 9.2.2.1 to specify that anonymous text contained in a block box must be treated as an inline element, and 16.6.1 says the same. So if absolute switches the pseudo’s to block, but #logo’s anonymous content is inline, #logo’s anonymous content would be painted higher than the pseudo.

Absolute definitely switches to some sort of block. But what type? css2 specified block, but change note C.2.53 modifies that to “not always block”. 9.2.4 states that the computed value of display is the same as the specified value – except for positioned elements, which change per 9.7.

Per 9.7 the value of inline, inline-block and run-in all compute to block, yet explicitly applying them changes the pseudo’s location, which indicates display is relevant – and is not being computed per 9.7. Maybe I’ve been looking too long, but an absolute pseudo acts like a sort of hybrid. Not forgetting 9.2.4 explicitly states a user agents style-sheet may override an initial value of display:inline – exactly what we have here.

I can’t find any settings in the browser style-sheets, but who knows what’s in the engine? Absolute seems to start with flow issues, navigates a range of ambiguities, and ends with browsers salting to personal preference ;)

Inline-block
The logical choice would be inline-block because the definition at 9.9.1 is very explicit – as you’ve identified - and neatly avoids the 9.9.1/”E” conflict, the “E”/(14.2/8.5.3) conflict as well as the uncertainty about the absolute formatting context and display. This is probably why it is the “magic bullet” for ie, but although winSafari and ie seem to get it right, Op and ff flows it per the block formatting model, not inline. So it appears that non-ie aren’t applying inline-block by default as means to avoid all the issues.

The unanswered questions
None of that explains why this only applies to absolute, and only ie.

Maybe non-ie browsers are applying 9.3/9.6, ignoring 14.2/8.5.3, and atomically painting absolutes in a layer consistent with 9.9.1 stack level [6], so well above everything else.

ie appears to be creating a layer that is connected to the document tree content, and applying 12.1 so that even an explicit z-index cannot separate the pseudo content from the document tree content. This is reinforced by a pseudo’s willingness to move along the z-axis if z-index is applied to the associated element rather than the pseudo. 14.2/8.5.3 apply because they affect the pseudo’s background/border, not the relationship between the pseudo content and the tree content - although I doubt that was planned ;)

Relative
Relative works because it avoids the ambiguities/conflicts over what layer it occupies as it has not been removed from the flow, whether is it auto-magically converted to some type of block that may or may not affect the interaction with other elements, at the same time as it maybe, or maybe not, creates a new stack context: Just draw it at level [6] of the 9.9.1 stacking levels and be done ;)


I’m sure I’m missing something – but I’m too close to the detail - maybe fresh eyes will see it more easily.

alt131

10:24 am on Jan 24, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



... to prevent anyone getting a word in ... ;)
Been watching the Editors draft these last weeks, and just before posting the above tome noticed much work on run-in – including adding in specific references to pseudo elements. I have not worked it all through yet, but it makes sense given run-in is an interesting display option, and browsers with the better history with inline-block (ie and winSafari), and display:run-in (OP, winSafari and ie) produced consistent results – leaving ff on a limb

Even more important, 9.9.1 has had considerable work:

The definition of auto now specifies the stack level as 0, and stacking levels have been modified:

Within each stacking context, the following layers are painted in back-to-front order.
1.the background and borders of the element forming the stacking context.
2.the child stacking contexts with negative stack levels (most negative first).
3.the in-flow, non-inline-level, non-positioned descendants.
4.the floating descendants.
5.the in-flow, inline-level, non-positioned descendants, including inline tables and inline blocks.
6.the child stacking contexts with stack level 0, and the positioned descendants with 'z-index: auto'.
7.the child stacking contexts with positive stack levels (least positive first).

Positioned elements with 'z-index: auto' (in layer 6), floats (layer 4), inline blocks (layer 5), and inline tables (layer 5), are painted as if those elements generated new stacking contexts, except that their positioned descendants and any child stacking contexts take part in the current stacking context.

This painting order is applied recursively to each stacking context. This description of stacking context painting order constitutes an overview of the detailed normative definition in Appendix E.


“E” has been modified to replace “stacking order” with painting order (Thank goodness)

So a lot of the underlying issues highlighted by the code sample are being directly addressed - and should be resolved for the future.

SuzyUK

11:26 am on Jan 24, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I think alt131, you've done a tremendous amount of testing and work here! I'm bookmarking for sure.

If the changes are going on it possibly highlights that what we saw (the conflicts) were just beginning to show themselves in the grander scale and it's being addressed. I like this way of working "the living spec" if you like, it tends to mean things evolve as per how most users expect it to.. with the odd hiccup, gone are the days of writing the theory and trying to guess every single use case.

like Float containment (the lack of) which in Float behaviour theory sounded good, but in the end it HAD TO evolve differently as it was being used differently.

your posts (test suite) will be a great reference for checking how it actually progresses

Thank You for taking the time to write them up! :)