Clearing Absolutes Again

Update

A revised script that addresses the issues brought up in the comments of this post is available for discussion in Absolute Clearance.

Prompted by renewed conversation about clearing absolutely positioned elements by Eric Meyer and Mike Davidson, and a concern voiced by Simon Willison in the comments of my original post I’ve developed a revised approach to the issue.

Shortcomings of the Original Script

Previously the script I wrote required containing elements to have a specific class to indicate that they should “clear” the absolutely positioned elements inside them. On top of that, once the script ran, any resizing of text via browser controls caused the layout to either overlap in the case of enlarging the text, or spread apart when the text size was reduced. Neither limitations would be acceptable in a production environment, the first for semantic reasons and the second for accessibility/usability concerns.

Exploration

In developing this alternate approach I explored a number of options. To eliminate the inline classing of target elements I imagined setting a fictional CSS property, -si-flow: inline together with position: absolute to indicate a cleared absolute. Unfortunately Safari dashed that idea as it’s scripting engine remains blissfully ignorant of all but inline or scripted styles (I would love for someone to prove this statement wrong).

Look Ma, No Classes!

What developed instead was a logic that determines the positioning of child elements based on their parent element’s height. If all elements inside a parent element are absolutely positioned then the parent collapses resulting in an offsetHeight of 0. If one or more of the elements are absolutely positioned, then the parent element’s offsetHeight will be less than the sum of the offsetHeight of its children. Any element for which either case is true should be cleared by the script.

A Second Round of Exploration

Problem number one solved (for now). Solution number two proved a little more challenging to imagine but came together rather quickly after that. My first attempt assumed that there was no way to determine if the user had resized the text via a browser menu and instead focussed on capturing keypresses equating to the key commands that achieve the same effect. It was incomplete but a fair start I reasoned. That effort proved fruitless as the JavaScript engine in most browsers seemed to be ignorant of any keypresses that result in a predefined browser action.

The solution came to me while working on another problem and I stumble across the fact that the onresize even can be triggered on “windows and objects.” Excitedly I slapped the event on an image set it’s width and height in ems and resized the text in my browser. No luck. It turns out the event only fires on the window and document objects. So what to do?

Everybody Loves iFrames

The solution to the second problem is to dynamically create an invisible iframe, set its dimensions in ems and then load into it a small document (which is admittedly malformed to conserve bandwidth) that calls the SI_clearAbsolutes() function onresize. Now whenever the user resizes the text, the proportions of the hidden iframe change relative to the text size and an onresize event fires and redraws the page. Here are two examples of the revised script in action: a single instance and nested instances.

Problem Solved?

The only remaining concern is the dependence on scripting for layout. That is easily accommodated by setting a default height for elements that contain cleared absolutely positioned elements that is in excess of their potential offsetHeight. There may be extra scrolling for those without JavaScript or with it disabled but that is more desirable than the alternative overlapping of positioned content.

Previous
Home Schooled
Next
This Land
Author
Shaun Inman
Posted
July 20th, 2004 at 8:41 am
Categories
CSS
JavaScript
Comments
011 (Now closed)

011 Comments

001

You wiley bastard.

Author
Jason Santa Maria
Posted
Jul 20th, 2004 5:01 am
002

Yeah. What Jason said.

Author
Trevor Filter
Posted
Jul 20th, 2004 6:02 am
003

For some reason this approach disables the Back button. I’m using Firefox and it let’s me click the back button I just don’t go anywhere. By this I mean all means of Back. Alt-Left Arrow, right click, Go menu, etc…

I can however, pull down the Back menu and choose from there.

Baby got back?

Author
Michael Hupp
Posted
Jul 20th, 2004 7:37 am
004

Shaun,

You don’t need to use an IFRAME. I have been using a very similar concept with just an absolutely positioned DIV that has top set to a negative number.

Author
Dimitri Glazkov
Posted
Jul 20th, 2004 7:39 am
005

Hmm, good call Michael. I didn’t consider that. But it’s not actually breaking the back button. What’s happening is that the iframe document is taking a spot in the history. You can double click the back button to get back. That’s still not acceptable. Back to the drawing board, I guess.

Author
Shaun Inman
Posted
Jul 20th, 2004 7:44 am
006

Care to elaborate Dimitri? In my experimentation, no other element fires an onresize event consistently across browser.

Author
Shaun Inman
Posted
Jul 20th, 2004 7:47 am
007

You could play with the javascript history object and remove the last entry…

Author
Amit Snyderman
Posted
Jul 20th, 2004 8:59 am
008

Basically, I just set up an interval check for a width (or height) of a SPAN which contains single monospace character.

Take a look at this code: glazkov.com/Resources/Code/TestFontSize … ector.html

Author
Dimitri Glazkov
Posted
Jul 20th, 2004 12:43 pm
009

Now, a more interesting question would be how to fire an “onresize” event on an HTMLElement in Gecko? I can do it very easily with MSIE, but Mozilla gives me a lot of grief…

If we could somehow accomplish this, it would be very easy to decouple font size change detector into its own little script.

Author
Dimitri Glazkov
Posted
Jul 20th, 2004 12:51 pm
010

Ah, I see Dimitri. I’d rather not have a script running in the background the entire time someone is viewing a page. It’s not economical and could have a negative impact on other scripts that might run over the course of a page view. Especially for those with slower machines. I chose this approach so that SI_clearAbsolutes() only runs once when required.

Author
Shaun Inman
Posted
Jul 20th, 2004 8:49 pm
011

I guess both methods offer some advantages and disadvantages…

Author
Dimitri Glazkov
Posted
Jul 21st, 2004 4:35 am