Stop using poor performance CSS expressions – Use JavaScript instead
Since the CSS support in Internet Explorer, especially in versions prior to Internet Explorer 7, has been lagging quite substantially, clever web developers have started using CSS expressions to mimic CSS functionality. However, few realize how this affects performance.
Explaining CSS expressions
The basic idea with CSS expressions is that you will have calculation and dynamic values for properties in the CSS code, something that people have found very useful. A simple example can be implementing max-width behavior in IE 6:
#container{
width: expression(document.body.clientWidth > 1100)? "1100px" : "auto";
/* For web browsers supporting it */
max-width: 1100px;
}
The code above evaluates the available width of the body element, and if wide enough, adapts the element named container so it stretches to a maximum width of 1100 pixels. If the area needed isn’t available, it scales down to what will fit within the context.
Basically, any way you can use one-line JavaScript code, it means a possibility to dynamically style something.
It uses JavaScript?
Yes, for those who don’t know: CSS expressions is purely based on JavaScript, and through the CSS implementation in Internet Explorer, it opens up the option to write scripts in the CSS code.
Sweet!
You’re probably thinking “Sweet!”, and immediately start planning everything you can fix with CSS expressions to touch up on your CSS code for Internet Explorer. Away with nasty hacks; enter clean, proper and cool solution.
Sweet?
I’m afraid, my friends, that it isn’t that sweet. To begin with, many web developers seem to completely underestimate that this requires JavaScript enabled in the web browser to function at all. And since you don’t want your layouts to be JavaScript dependent, you will have to provide a proper fallback which will work without JavaScript.
The other major reason is that CSS expressions are very resource intensive. The resulting value of an expression isn’t just calculated once, but consistently while you’re using the web page. Add moving the mouse pointer around to that, and it will trigger even more evaluation from the expression interpreter.
You’ve probably experienced some web pages being even more sluggish than expected in Internet Explorer, but haven’t known about the reason why. Look no further: usage (especially heavy such) of CSS expressions is most of the times the culprit you want to get rid of.
Why do people use CSS expressions?
I have complete understanding of people implementing CSS expressions to cover up for shortcomings in the CSS rendering engine in Internet Explorer. I also believe that since the syntax is very easy, web developers have (as always with easy code) adopted it without seriously analyzing any possible downsides to it.
Use “real” JavaScript instead of CSS expressions
You will never get around the dependency on JavaScript being enabled for having a layout which is dynamically calculated in the same manner. However, there’s a much better strategy to achieve the same behavior and result in Internet Explorer, but without the performance loss: JavaScript
And by JavaScript, I mean real, proper JavaScript code included in an external file, and instead tied to event handlers. This means that the behavior, and thus the calculation, will only take place when that event occurs. In between, there will be no performance affection due to CSS expressions desperately trying to find out what the annoying user (to CSS expressions, that is) is doing in the web browser window.
A JavaScript example
To get the same result as the above CSS expression code sample, you need this code (as a suggestion included in a file named maxWidthFixForIE6.js):
window.onload = checkAvailableWidth;
window.onresize = checkAvailableWidth;
function checkAvailableWidth(){
var container = document.getElementById("container");
container.style.width = (document.body.clientWidth > 1100)? "1100px" : "auto";
}
Too much code for your taste? No more tasty one-liners? Well, do you want funky looking code (which every web developer for some reason think is obliged to belong in the CSS file/-s), or do you want code which is reliable and gives the best performance for your users? I know what my pick is, at least…
For Internet Explorer 6 only
One more thing to note here is that you only want this example code triggered in Internet Explorer 6. Not version 7, and definitely not for any web browser provided by another vendor. Some will now cry out:
Web browser detection? That’s foul play, object detection for the masses!
Well, object detection is a great thing, and without a doubt the most suitable approach testing for feature support. However, in cases like this, there’s no proper way to check for lack of CSS support.
Since you also don’t want the JavaScript file included for every user and web browser either, you should address this by only serving it to Internet Explorer 6. The best way I think this can be done is by using conditional comments to filter out the web browser you want:
<!--[if lt IE 7]>
<script type="text/javascript" src="/js/maxWidthFixForIE6.js"></script>
<![endif]-->
Use JavaScript, if needed
One time or another, we get handled a case where there’s no way to accomplish a certain layout optimally for Internet Explorer 6 without JavaScript. And you know what? That’s just fine, shit happens.
But first, make sure it degrades properly without JavaScript. Second, implement it with JavaScript code instead of CSS expressions, for best performance and reliability.
47 Comments/Reactions
November 13th, 2007 at 1:01
A clean and simple solution … I like it. The only downside being that I feel rather stupid for not having thought of this myself.
November 13th, 2007 at 1:01
Excellent article Robert. I have indeed noticed some sites being unconventionally slow and even emailed a few and asked what they had done. Considering I have quite a good broadband connection it seemed odd to wait up to half a minute or more for a text page with 3 or 4 optimised images to load. So that might have been the likely culprit.
I haven’t used CSS expressions myself but mostly because I never felt good about them. Somewhere things need to be processed.
Thanks for sharing the javascript solution.
November 13th, 2007 at 1:54
I don’t use IE CSS expressions, but I always wondered what their downside, apart from relying on JavaScript, was. Thanks for clearing that up!
November 13th, 2007 at 6:58
I personally use the code that you wrote above. So now I guess I do not have any more excuses and can now use the proper JavaScript
November 13th, 2007 at 7:18
[...] After reading Roberts Talks post about this code, I would suggest still to use this code but use proper JavaScript and include it via a script [...]
November 13th, 2007 at 8:17
both CSS and Javascript have their unique behaviors.when we doing more complex designing, hope both are needed
November 13th, 2007 at 8:42
Excellent, I wonder why I didn’t think of this before. My reasoning about javascript usage for max-width is that it seldom breaks pages. Sure, lines will be very long, but they are still readable. I’ll use your script, not expressions, in the future. Thanks!
November 13th, 2007 at 10:38
Robert, just ask the people to stop using invalid CSS
OT: That’s probably intended, but abbreviations without a
titlecould benefit from having no border.November 13th, 2007 at 12:30
Personally, I do not believe expressions are simply evil. Expressions work, whether it is worth using them it on your site versus performance is up to you. I found some expressions to work very fast without affecting performance while some are really heavy. It’s all about testing and evaluating.
Besides that, events such as
onloadcan be tricky as well. If not used right, the onload triggers after the site is loaded causing an ugly flicker which can be very annoying.To be clear: there is no perfect solution for every project when handling specific limitations in IE. I find that the best thing to do is to find different solutions and evaluate which one works best for that particular project. And that can include expressions.
November 13th, 2007 at 13:43
Thanks everyone!
Jens,
Ah, well, invalid CSS is somethimes necessary to deal with certain things in IE 6. For instance,
zoom: 1;is at times a better approach thanheight: 1%;to triggerhasLayout(especially in conjunction withoverflow: hidden).David,
Personally, I see no downsides to using JavaScript instead. I didn’t think it was in the scope of this aricle to go into event handling, but I agree that
onloadis at times not the event you want to trigger something like this. No one wants the nasty flicker, right?Therefore, I’d encourage everyone to use some sort DOMContentLoaded approach to apply these things. I’ve written one approach in ELO – Encapsulated Load Object and it is also part of my DOMAssistant library in the DOMAssistantLoad module.
November 13th, 2007 at 17:47
I’d rather agree with “sometimes easier” since there often are alternative ways to trigger or avoid “hasLayout”. However, I just wanted to tease
November 16th, 2007 at 16:46
Interesting,
The funny thing is that I read about the performance problems with CSS expressions just today while reading the tips from YSlow regarding better page performance. I also came to the conclusion that i should use javascript to do this instead. YSlow, which I by the way know about from your blog.
So thanks for the nice, unobtrusive javascript solution and also, thanks for the tip about YSlow.
November 16th, 2007 at 19:51
Gabriel,
Funny coincidence! Anyway, I’m glad to hear that it helped!
November 19th, 2007 at 14:40
That IE-expressions can put heavy load on scarce resources, is a well-known issue. Performance-testing should definitely be high on the list whenever they are used.
However, I haven’t seen any good Javascript alternatives that can outperform the more complete (tailor-made) IE-expressions mainly used to “fix” IE6′ lack of CSS support, and I’m not sure what a good Javascript alternative should look like if it should perform the same task(s).
The “in-sync” performance is mainly what I’m after, since I use IE-expressions to emulate regular CSS support. Do you care to elaborate on what Javascript alternatives we have that performs the same tasks with less use of resources?
November 21st, 2007 at 10:57
Georg,
In-sync approach is a bit different, and I’d say fairly uncommon. But, at first thought, I don’t see why JavaScript couldn’t met the same demands with the proper events applied.
It gives you a more granular control, and hopefully just the possibility to have better performance by removing any constant but superfluos chance check.
November 21st, 2007 at 17:16
Robert,
thanks for the response.
Yes, most settle for what I call “lagging fixes”, where well-written Javascript with the right set of conditions is superior to IE-expressions.
CSS is (supposed to be) handled pretty instant (in-sync) though, and that’s why I ended up writing my own, conditional, IE-expressions since I wanted to emulate proper CSS-handling – making it appear as if IE6 supports the relevant CSS.
Besides, since we’re dealing with an obsolete browser-version, I prefer to waste some of its resources instead of mine.
I’m not proficient enough in Javascript to write anything better at the moment, and what I’ve found across the web doesn’t seem to work more seamless or light on resources. Always open for suggestions though.
November 21st, 2007 at 17:50
Georg,
I see where you’re coming from, and it’s a pretty complex situation. But in that case, how about Dean Edward’s IE 7 script?
November 21st, 2007 at 23:41
Robert,
I went through and tested a few layout-solutions with Dean’s script, a couple of years ago. I ended up neither pro nor con, but it seemed I had to tailor my CSS a bit for the IE7 script to make the most out of it.
I ended up not using Dean’s work for anything but inspiration.
November 22nd, 2007 at 0:59
Georg,
Well, inspiration counts too!
November 22nd, 2007 at 4:19
Robert,
Sure inspiration counts. Besides: inspiration is so easy to turn into something completely different
Thanks for the chat.
December 8th, 2007 at 8:43
The idea of CSS expressions reminds me of Adding Style and Behavior to XML with a dash of Spice, an old submission to the W3C (1998).
December 10th, 2007 at 10:44
Georg,
Thank you!
Christophe,
Ah, good connection. Thanks!
February 8th, 2008 at 9:59
Hi Robert, Thanks for your post –
I’m trying to implement this, but, well, I have no idea where to put the code…! I’m a complete javascript newbie. Do I put this in the css? Do I make it it’s own js file and then call it from my header? Sorry for being clueless, but I would greatly appreciate a quick nudge in the right direction.
Cheers –
February 8th, 2008 at 12:21
Zack,
As suggested in the post:
I also recommend reading up on JavaScript best practices, for instance in Unobtrusive JavaScript, since it’s a vital tool in developing web interfaces.
February 11th, 2008 at 22:20
[...] Nyman’s article about using JavaScript instead of CSS Expressions is a must [...]
April 17th, 2008 at 23:26
A follow up on the link to Spice: Daniel Glazman (invited expert to CSS WG) and David Hyatt (Apple) are working on a proposal for CSS Variables. (Discovered through Laurent Jouanneau’s blog.)
April 18th, 2008 at 9:35
Christophe,
Yes, we’ll see what happens with that.
May 10th, 2008 at 12:03
[...] http://www.robertnyman.com/2007/11/13/stop-using-poor-performance-css-expressions-use-javascript-ins... [...]
May 10th, 2008 at 12:09
[...] http://www.robertnyman.com/2007/11/13/stop-using-poor-performance-css-expressions-use-javascript-ins... [...]
July 10th, 2008 at 4:09
Hi,
This article is great. It help me with the expression problem. Thanks, Robert.
Best regards,
Inair
October 18th, 2008 at 12:05
Surely any script execution at the Style Sheet stack of the browser is a performance issue and more importantly a security threat. No wonder it makes IE the most insecure browser on the market.
Good news is Microsoft is ending expressions in Internet Explorer as announced on Thursday earlier this week.
A very nice move towards the standard-compliant browser.
October 18th, 2008 at 23:23
Inair,
Good!
flash tekkie,
Yes, I was very glad about that decision!
November 21st, 2008 at 6:53
Nice one, another Yslow follower here… I’m a js novice but I think this might work as another way of including the code (instead of using [if lt...]), no IE6 to test on here…
function checkAvailableWidth(){
// min/max works better with slightly different values?
var container = document.getElementById("container");
container.style.width = (document.body.clientWidth 1012? "1010px" : "auto");
}
// window.attachEvent only followed by IE6? or IE7 as well?
if (window.attachEvent)
{
window.attachEvent('onload', checkAvailableWidth);
window.attachEvent('onresize', checkAvailableWidth);
}
I have a big block of sitewide js so my idea is to just stick it in there instead of having a separate file. Not sure how those calls work when there are other ones looking out for ‘onload’ as well.
November 21st, 2008 at 10:07
waitangi,
The problem with using
attachEventis that it is present in IE 7 as well, + in Opera, who has tried to mimicked it.Therefore, using conditional comments is the best way to achieve this, and also, personally I prefer a clean separation in my code between real code and other code used to cover up for certain web browser flaws.
November 21st, 2008 at 14:32
Ah cool thanks for that info Robert, I’ve followed your advice and removed the ie-only code to a separate file inside conditional comments.
Almost at the holy grail of YSlow A! (just a few grand on CDN and it’s there
).
November 21st, 2008 at 14:37
waitangi,
Great!
That CDN thing is a bit off, I think. It’s really only valid for major web sites being accessed from all around the globe. Don’t worry to much about it.
December 14th, 2008 at 0:29
[...] maxWidthFixForIE6.js — Emuler la propriété max-width pour IE6 : [...]
February 14th, 2009 at 21:00
[...] found this article on the web, which says that reqular expressions are very expensive on the page, and you should use [...]
April 8th, 2009 at 16:58
Nice job. Works like a charm!
April 14th, 2009 at 21:12
Zac,
Happy it helped!
August 3rd, 2009 at 5:42
[...] maxWidthFixForIE6.js — Emuler la propriété max-width pour IE6 : [...]
August 16th, 2009 at 15:12
Hi,
I tried to use the above code but it doesn’t seem to work for me. Maybe I’m doing it wrong?
If you have IE6 you can check out the web address. It is giving me problems with both the left div and the right div.
My structure is something like this:
<code>
<html>
<head>
<style type=”text/css”>
#wrapper{ width:980px; margin:auto; background-color:#fff }
#header{ width:980px; position:relative }
#middle{
width: expression(document.body.clientWidth > 940)? “980px” : “auto”;
/* For web browsers supporting it */
max-width: 980px;
padding:20px;
overflow:hidden;
clear:both;
}
#left{ float:left; width:200px }
#main{ width:auto; margin: 0px 0px 0px 210px }
#content{
width: expression(document.body.clientWidth > 480)? “480px” : “auto”;
/* For web browsers supporting it */
max-width: 480px;
min-height: 400px;
margin: 0px 250px 0px 0px;
}
#right{ float:right; width:240px }
#footer{ clear:both; width:980px; margin:auto; padding:20px 0 }
</style>
</head>
<body>
< div id=”wrapper”>
< div id=”header”>
</div>
< div id=”middle”>
< div id=”left”>
</div>
< div id=”main”>
< div id=”right”>
</div>
< div id=”content”>
</div>
</div>
</div>
</div>
< div id=”footer”>
</div>
</body>
</html>
</code>
August 16th, 2009 at 16:59
Nevermind I fixed the problem. I changed some of the code and set a conditional statement for IE6 to change the div#middle padding to 10px.
August 17th, 2009 at 0:17
moleculezz,
Glad that it worked out for you!
September 28th, 2009 at 22:48
How did you track performance on css expression vs javascript ?!
September 29th, 2009 at 8:39
Olav,
I think the best resource on that is the statement from the Yahoo Performance Team on CSS expressions.
January 12th, 2010 at 3:55
[...] Rightly so, Microsoft has dropped support for CSS expressions with IE 8. The better choice is to use proper event handlers. Here is a great article further exploring the problem with CSS expressions. [...]
Write a comment
Twitter reactions