D
David Mark
How to Measure Element Dimensions
Typically these functions fall into three categories: call them
getOuterDimensions, getInnerDimensions, and getCssDimensions. The
first two refer to the size outside and inside the border respectively
and the last the CSS dimensions (per the box model).
The first two have just one rendition each. With simplified feature
detection*:-
if (document.documentElement && typeof
document.documentElement.offsetWidth == 'number') {
var getOuterDimensions = function(el) {
return [el.offsetHeight, el.offsetWidth];
};
}
if (document.documentElement && typeof
document.documentElement.clientWidth == 'number') {
var getInnerDimensions = function(el) {
return [el.clientHeight, el.clientWidth];
};
}
Those never change. They work even in IE 4. Due to the host feature
detection and conditional creation of these functions, applications
that do proper API feature detection will degrade gracefully in IE 3.
Of course, if the application's script has a try-catch, the
degradation path for IE 4 and under is a parse error.
As for getCssDimensions, a GP solution may (and often does) use
getComputedStyle, but unfortunately that method has been notoriously
buggy over the years and the older versions of IE (under 9) don't
support it at all. You could try to string together a bunch of hacks
to emulate getComputedStyle with IE's various proprietary objects, but
it's a fool's errand.
Here is a relatively slow solution that works for all box models in
"all browsers":-
http://www.cinsoft.net/size.html
As with virtually everything in cross-browser scripting, defining a
specific context is the key to creating a reliable function.
What if the design decision was made to measure only elements with the
border-box box model? Then you could do this:-
var getCssDimensions = getOuterDimensions;
Unfortunately, that is an inappropriate solution for most contexts as
many browsers do not support that box model. For example, IE 5-8 will
do it only in quirks mode (which is always best avoided).
What if the design decision was made to measure only elements with the
content-box box model *and* without padding? Then you could do this:-
var getCssDimensions = getInnerDimensions;
This is an excellent (and relatively fast) solution as the default for
virtually every element in virtually every modern browser is content-
box. When designing an application's widgets, simply take care to only
measure elements without padding. It's not hard to do and the payoff
is a fast, concise and cross-browser solution. Just make sure to
document the context as the documentation is as much a part of the
rendition as the code.
How *Not* to Measure Element Dimensions
And what of the jQuery height/width functions? They don't work at all
for border-box. They also rely on getComputedStyle (or a long-winded,
over-complicated simulation). It's the worst of both worlds; also
confusing, relatively slow, poorly documented, failure-prone and
subject to change at any time on a whim. That's what *defines* jQuery
(and the like). In its favor... uh, lots of Web developers use it to
churn out horrible Websites.
To borrow a term from the jQuery fanboy resistance/marketing
department: does this sound like FUD to you? I think you should
certainly be afraid of such doubtful material as jQuery, at least
until you understand the employed techniques well enough to avoid it
for rational reasons. Fear of the unknown can be healthy and most
jQuery users have no idea what it does.
http://en.wikipedia.org/wiki/Cargo_cult_programming
* Use isHostObjectProperty (or the like) to detect
document.documentElement
http://www.cinsoft.net/
http://www.twitter.com/cinsoft
http://jsperf.com/browse/david-mark
Typically these functions fall into three categories: call them
getOuterDimensions, getInnerDimensions, and getCssDimensions. The
first two refer to the size outside and inside the border respectively
and the last the CSS dimensions (per the box model).
The first two have just one rendition each. With simplified feature
detection*:-
if (document.documentElement && typeof
document.documentElement.offsetWidth == 'number') {
var getOuterDimensions = function(el) {
return [el.offsetHeight, el.offsetWidth];
};
}
if (document.documentElement && typeof
document.documentElement.clientWidth == 'number') {
var getInnerDimensions = function(el) {
return [el.clientHeight, el.clientWidth];
};
}
Those never change. They work even in IE 4. Due to the host feature
detection and conditional creation of these functions, applications
that do proper API feature detection will degrade gracefully in IE 3.
Of course, if the application's script has a try-catch, the
degradation path for IE 4 and under is a parse error.
As for getCssDimensions, a GP solution may (and often does) use
getComputedStyle, but unfortunately that method has been notoriously
buggy over the years and the older versions of IE (under 9) don't
support it at all. You could try to string together a bunch of hacks
to emulate getComputedStyle with IE's various proprietary objects, but
it's a fool's errand.
Here is a relatively slow solution that works for all box models in
"all browsers":-
http://www.cinsoft.net/size.html
As with virtually everything in cross-browser scripting, defining a
specific context is the key to creating a reliable function.
What if the design decision was made to measure only elements with the
border-box box model? Then you could do this:-
var getCssDimensions = getOuterDimensions;
Unfortunately, that is an inappropriate solution for most contexts as
many browsers do not support that box model. For example, IE 5-8 will
do it only in quirks mode (which is always best avoided).
What if the design decision was made to measure only elements with the
content-box box model *and* without padding? Then you could do this:-
var getCssDimensions = getInnerDimensions;
This is an excellent (and relatively fast) solution as the default for
virtually every element in virtually every modern browser is content-
box. When designing an application's widgets, simply take care to only
measure elements without padding. It's not hard to do and the payoff
is a fast, concise and cross-browser solution. Just make sure to
document the context as the documentation is as much a part of the
rendition as the code.
How *Not* to Measure Element Dimensions
And what of the jQuery height/width functions? They don't work at all
for border-box. They also rely on getComputedStyle (or a long-winded,
over-complicated simulation). It's the worst of both worlds; also
confusing, relatively slow, poorly documented, failure-prone and
subject to change at any time on a whim. That's what *defines* jQuery
(and the like). In its favor... uh, lots of Web developers use it to
churn out horrible Websites.
To borrow a term from the jQuery fanboy resistance/marketing
department: does this sound like FUD to you? I think you should
certainly be afraid of such doubtful material as jQuery, at least
until you understand the employed techniques well enough to avoid it
for rational reasons. Fear of the unknown can be healthy and most
jQuery users have no idea what it does.
http://en.wikipedia.org/wiki/Cargo_cult_programming
* Use isHostObjectProperty (or the like) to detect
document.documentElement
http://www.cinsoft.net/
http://www.twitter.com/cinsoft
http://jsperf.com/browse/david-mark