meyerweb.com

Skip to: site navigation/presentation
Skip to: Thoughts From Eric

Archive: September 2011

CSS Modules Throughout History

For very little reason other than I was curious to see what resulted, I’ve compiled a list of various CSS modules’ version histories, and then used CSS to turn it into a set of timelines.  It’s kind of a low-cost way to visualize the life cycle of and energy going into various CSS modules.

I’ll warn you up front that as of this writing the user interaction is not ideal, and in some places the presentation suffers from too much content overlap.  This happens in timelines where lots of drafts were released in a short period of time.  (In one case, two related drafts were released on the same day!)  I intend to clean up the presentation, but for the moment I’m still fiddling with ideas.  The obvious one is to rotate every other spec name by -45 degrees, but that looked kind of awful.  I suspect I’ll end up doing some sort of timestamp comparison and if they’re too close together, toss on a class that invokes a -45deg rotation.  Or maybe I’ll get fancier!

The interaction is a little tougher to improve, given what’s being done here, but I have a few ideas for making things, if not perfect, at least less twitchy.

I should also note that not every module is listed as I write this:  I intentionally left off modules whose last update was 2006 or earlier.  I may add them at the end, or put them into a separate set of timelines.  The historian in me definitely wants to see them included, but the shadow of a UX person who dwells somewhere in the furthest corners of my head wanted to avoid as much clutter as possible.  We’ll see which one wins.

Anyway, somewhat like the browser release timeline, which is probably going to freeze in the face of the rapid-versioning schemes that are all the rage these days, I had fun combining my love of the web and my love of history.  I should do it more often, really.  The irony is that I don’t really have the time.

Un-fixing Fixed Elements with CSS Transforms

In the course of experimenting with some new artistic scripts to follow up “Spinning the Web“, I ran across an interesting interaction between positioning and transforms.

Put simply: as per the Introduction of the latest CSS 2D Transforms draft, a transformed element creates a containing block for all its positioned descendants.  This occurs in the absence of any explicit positioning of the transformed element.

Let’s walk through that.  Say you have a document whose body contains nothing except a position: static (normal-flow) div that contains some absolutely-positioned descendants.  The containing block for those positioned elements will be the root element.  Nothing unusual or unexpected there.

But then you decide to declare div {transform: rotate(10deg);}.  (Or even 0deg, which will have the same result.)  Now the div is the containing block for the absolutely-positioned elements that descend from it.  It’s as though transforming an element force-adds position: relative.  The positioned elements will rotate with their ancestor and be placed according to its containing block—not that of the root element.

Okay, so that’s a little unusual but perhaps not unexpected.  I could make arguments both ways, and some of the arguments could get pretty complex.  To pick one example, if the transformed element didn’t generate a containing block, how would translate transforms be handled?

Either way, here’s where things got really troublesome for me:  a transformed element creates a containing block even for descendants that have been set to position: fixed.  In other words, the containing block for a fixed-position descendant of a transformed element is the transformed element, not the viewport.  Furthermore, if the transformed element is in the normal flow, it will scroll with the document and the fixed-position descendants will scroll with it. You can see my test case, where the red and blue boxes would overlap each other and stay fixed in place, except the second green div has been rotated.

Obviously this makes the fixed-position elements something less than fixed-position.  In effect, not only does the transformed element act as if it’s been force-assigned position: relative, the fixed descendants behave as if they’ve been force-changed to position: absolute.

I find this not only unusual and unexpected, but also a wee bit unsettling.  Personally, I think it goes too far.  Fixed-position elements should be fixed to the viewport, regardless of the transformation of their ancestors.  Of course, if you agree with my thinking there, realize that opens a whole new debate about how, or even whether, transforms of ancestors should be carried to fixed-position descendants.

I have my own intuitions about that, but this is definitely territory where intuitions are to be treated with caution.  There are a lot of interacting behaviors no matter what you do, and no matter what you do someone’s going to find the results baffling in some way or other.

But since I do have intuitions, here’s what they are:  transformed elements in the normal flow or floated do not establish containing blocks for absolutely- and fixed-position descendants.  This means that any transforms you apply to the transformed element are not applied to the positioned descendants, because transforms don’t inherit.

What if you want a normal-flow transformed element to be a containing block?  Use position: relative, same as you would if there were no transform.  And if you want the transforms to be passed on to the descendants even though no containing block is established?  The inherit value would work in some cases, though not all.  That’s where my approach runs aground, and I’m not yet sure how to get it back to sea.

Okay, so that’s what I think.  What do you think?

September 2011
SMTWTFS
August October
 123
45678910
11121314151617
18192021222324
252627282930  

Archives

Feeds

Extras