David Mark's Daily Javascript Tips - Volume #3 - Tip #8 - How toCompute Styles

D

David Mark

How to Compute Styles

In a word, don't. The recommendation followed by the browser vendors
is long-winded and vague and historically browsers have varied in
their interpretations. The variety of results that must be parsed to
derive meaning is a huge burden to bear and most applications don't
need to compute any styles (let alone all possibilities!) in the first
place.

var getStyleComputed;

// No "float" styles
// Requires camel-case style names
// Fades away in IE 8- and compatibility modes

if (document.defaultView && document.defaultView.getComputedStyle) {
getStyleComputed = function(el, style) {
return document.defaultView.getComputedStyle(el, null)
[style];
};
}

What's missing? Can't handle "float" as it is a reserved word
(property is "cssFloat" or "styleFloat", depending on
implementation). That's easy enough to detect, but how often do you
need to compute the float style?

Add a line during development:-

if (document.defaultView && document.defaultView.getComputedStyle) {
getStyleComputed = function(el, style) {

if (style == 'float') {
throw new Error('RTFM! The "float" style is not
supported by this rendition!');
}

return document.defaultView.getComputedStyle(el, null)
[style];
};
}

....and remove on release.

Note that this function requires camel-case style names, not
hyphenated. That will save you a keystroke/byte. ;)

Add another line during development:-

if (document.defaultView && document.defaultView.getComputedStyle) {
getStyleComputed = function(el, style) {

if (style.indexOf('-') != -1) {
throw new Error('Camel-case style names, please.');
}

if (style == 'float') {
throw new Error('RTFM! The "float" style is not
supported by this rendition!');
}

return document.defaultView.getComputedStyle(el, null)
[style];
};
}

....and remove on release.

Instead of adding additional logic for your users to *download*,
simply corral your developers prior to release.

if (getStyleComputed) {
// Put app that must compute styles here
}

But what of IE8 and under? At this point, you have to consider what
this function is to be used for. There's not a chance in hell in
creating a general-purpose getComputedStyle emulation for legacy IE
versions (which lack the required host method). And no, that fact has
not stopped the library ninjas from trying to outdo each other, year
after year, on this front. Even worse, these teetering piles of hacks
are often tangled up with other library functionality (e.g. jQuery's
height/width methods). The situation is a mess that can only be
cleaned up by starting over from scratch (as jQuery is rumored to be
contemplating).

Historically, the primary use of such "cross-browser" wrappers has
been to support scripted effects. Well, scripted effects are dead
these days (somebody tell jQuery) and even if you need to offer
fallback effects for legacy IE versions, you don't need a cross-
browser getComputedStyle wrapper. You just need to concentrate on
whatever handful of styles your current project must animate.

Left, top, right, bottom, height, width and borders can all be easily
figured without a getComputedStyle dependency. Margins can be figured
in some contexts, but who would need to do such a thing? And I can
hear it now: what about padding?! Unless you are doing something very
wrong, you should never need to compute the padding. Granted, that's
exactly what jQuery's height/width methods try to do. :(

Here are solutions for size and position:-

http://www.cinsoft.net/size.html
http://www.cinsoft.net/position.html

Borders should be an easy exercise if you have been following along;
yes, even the right and bottom borders. But why would your script be
interested in such styling, unless it is going to do scripted effects
involving borders?

I've been using the CSS3 transitions/animations for some time now.
I've seen Opera, then Firefox (and finally IE 10) reproduce what
Webkit started and have been quite pleased with the consistency and
performance. It takes little or no code to use those features. So
use them and stop worrying about computed styles.

Take out effects, computing styles, queries, and all of the other
topics covered so far in this series and what is there left for a
script like jQuery to do; other than take up space? Pretty hard to
believe that ostensibly experienced developers are now trying to build
a "mobile framework" on top of jQuery. All I can figure is they have
no idea what is in that script. For them, I guess it's all about
marketing a name. :(

http://www.cinsoft.net/
http://twitter.com/cinsoft
http://jsperf.com/browse/david-mark
 
D

David Mark

How to Compute Styles

In a word, don't.  The recommendation followed by the browser vendors
is long-winded and vague and historically browsers have varied in
their interpretations.  The variety of results that must be parsed to
derive meaning is a huge burden to bear and most applications don't
need to compute any styles (let alone all possibilities!) in the first
place.

var getStyleComputed;

// No "float" styles
// Requires camel-case style names
// Fades away in IE 8- and compatibility modes

if (document.defaultView && document.defaultView.getComputedStyle) {
          getStyleComputed = function(el, style) {
            return document.defaultView.getComputedStyle(el, null)
[style];
          };

}

What's missing?  Can't handle "float" as it is a reserved word
(property is "cssFloat" or "styleFloat", depending on
implementation).  That's easy enough to detect, but how often do you
need to compute the float style?

Add a line during development:-

if (document.defaultView && document.defaultView.getComputedStyle) {
          getStyleComputed = function(el, style) {

            if (style == 'float') {
              throw new Error('RTFM! The "float" style is not
supported by this rendition!');
            }

            return document.defaultView.getComputedStyle(el, null)
[style];
          };

}

...and remove on release.

Note that this function requires camel-case style names, not
hyphenated.  That will save you a keystroke/byte.  ;)

Add another line during development:-

if (document.defaultView && document.defaultView.getComputedStyle) {
          getStyleComputed = function(el, style) {

            if (style.indexOf('-') != -1) {
              throw new Error('Camel-case style names, please.');
            }

            if (style == 'float') {
              throw new Error('RTFM! The "float" style is not
supported by this rendition!');
            }

And how about:-

if (el.style.display == 'none') {
throw new Error('Element not in layout. Cannot compute
styles.');
}

....as any calling code that passes an element that is not part of the
layout (presumably removed by the script) is clearly making a
mistake. Computed styles have no meaning in that context.

Best to fail immediately so the developer can follow the stack trace
back to the offending code.

Again, remove such "scaffolding" on deployment, at which time should
be rendered no-ops anyway (else testers missed something).

And, of course, some libraries and frameworks will try like hell to
make sense out of such illogical situations, shielding the developers
from fundamental misunderstandings in their own code. They call it
being "forgiving". In general, it's just stupid to write an API like
that. For browser scripting, it's certainly ill advised and writing
things like UI widgets with such a "forgiving" API is madness.

And that's where the lists of "approved" browsers creep in, to let
developers know these monoliths can't possibly be expected to work in
anything but the last five or six browsers tested. They just have no
idea beyond that (and refuse to find out). Anything else, past or
future, is your own problem; you saw the browser icons when you
downloaded the library. :(
            return document.defaultView.getComputedStyle(el, null)
[style];
          };

}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,961
Messages
2,570,131
Members
46,689
Latest member
liammiller

Latest Threads

Top