PDA

View Full Version : How to calculate the pixel to em ratio


brothercake
08-06-2003, 12:19 AM
I was thinking, draw an invisible, absolutely positioned element that's 10em wide, and then read its offsetWidth to work out the ratio.

But is there a cleaner way - a purely mathematical way or a system property?

jkd
08-06-2003, 01:52 AM
Not really. em is a relative unit, so it's size actually depends on where the style is being applied (should be on what font is currently applied methinks).

You could do something like:

var widthProp = document.defaultView.getComputedStyle(document.body, '').getPropertyCSSValue("width");
var pxOverEm = widthProp.getFloatValue(CSSPrimitiveValue.CSS_PX) / widthProp.getFloatValue(CSSPrimitiveValue.CSS_EMS);

But the only browser remotely close to this capability is Mozilla, and Mozilla chooses to throw a DOMException instead of converting to other units. And this would be em relative to the body of the document.

brothercake
08-06-2003, 04:47 AM
Originally posted by jkd
Not really. em is a relative unit, so it's size actually depends on where the style is being applied (should be on what font is currently applied methinks).
Oh, I hadn't thought of that, but maybe it's okay ...

The bottom line of what I wanna do ... you'll laugh ... is make "max-width" work in IE :D Here's the plan:

Say max-width is defined as 8em, I let the element render at "width:auto" and then read its offsetWidth; assume for now I already have the em-px ratio, I just have to work out 8em in pixels, see if the offsetWidth is greater, and apply 8em width if it is.

But getting that ratio - if I create a hidden element inside the element which will eventually have max-width applied, then the em-px ratio will be correct in the context of that element, which is all I need to know.

Does that make sense? Or is there a flaw in my logic ...?

jkd
08-06-2003, 05:04 AM
Originally posted by brothercake
But getting that ratio - if I create a hidden element inside the element which will eventually have max-width applied, then the em-px ratio will be correct in the context of that element, which is all I need to know.

That works. You'll have momentary overflow though, which may or may not be an issue depending on how flawless a presentation you need.

brothercake
08-06-2003, 08:03 AM
Unless .. if the element is positioned, then the test element can be absolutely positioned inside it, so no displacement :)

jkd
08-06-2003, 06:17 PM
Originally posted by brothercake
Unless .. if the element is positioned, then the test element can be absolutely positioned inside it, so no displacement :)

Ohh, crafty. :D

brothercake
08-07-2003, 07:15 AM
Excellent .. here's the method; I'm just copying this out of a larger script, where "udm" is the main object, "udm.tree" is the <ul> element, and udm.navbarStyles[0] is the defined value for max-width; it happens as the nav is loading - it has to be displayed but it can be invisible - then iterate through the first-level links and pass them to the method; setting a class whose width is the same as max-width means I don't even have to work out the ratio - just measure the created object - so it works for % as well :)

//apply max width for IE
udmNavbar.prototype.applyMaxWidth = function(udmLink)
{
//if we don't yet know the max width in pixels
if(udm.maxWidth == 0)
{
//create an element inside the tree
udm.testEle = document.createElement('div');
udm.tree.appendChild(udm.testEle);

//and set it to a test class whose width is the value of max-width
udm.testEle.setAttribute('class','');
udm.testEle.className = 'udmUnitTest';

//now measure it in pixels
udm.maxWidth = udm.testEle.offsetWidth;

//now remove it
udm.tree.removeChild(udm.testEle);
}

//get the link element width in pixels
udm.linkWidth = udmLink.offsetWidth;

//if it's greater than the equivalent max-width
if(udm.linkWidth > udm.maxWidth)
{
//apply max-width
udmLink.style.width = udm.navbarStyles[0];
}
}

jkd
08-07-2003, 07:19 AM
All of that just for "max-width" bla"... makes you really wish IE wasn't dominate... but a nice little hack nonetheless. :)

brothercake
08-07-2003, 07:23 AM
Tell me about it ... it's sooo tedious ... but having this means I can make a list-based horizontal navbar which can be generated from a database :) Without it, either all the cells would have to be fixed width, or there's the possibility of overlong links making the navbar too wide for the page.