Internet Explorer Doesn’t Evaluate Any More Than 31 Style Elements

Any version of Microsoft Internet Explorer will not evaluate any more than 31 CSS style elements. I’m not sure if many of you readers have come across this ridiculous bug, but we thought best if you were at least forewarned.

The Bug

The bug itself is described by Microsoft in the article listed below. The funny thing is that they say the number of style elements parsed is 30; however, it’s actually 31.

Normal Circumstances

Under normal circumstances, you would never really run into a situation that would require your page to have 31+ style elements on your web page. However, when one is developing in a portal environment, you would be surprised at how quickly that can happen; JSR-168 portlets and other 3rd party apps can have their own way of styling HTML that you have no control over.

We actually came across this when migrating the BI reporting tool BIRT from v2.2 to v2.3. In v2.3 we noticed that the reports displayed fine in Firefox/etc, but they looked like un-styled garbage in Internet Explorer. It took quite a while to figure out that BIRT v2.3 put all of their CSS properties inside <style/> blocks; BIRT v2.2 the CSS properties were inline attributes on the elements (i.e. style=”bleh…”).

Anyways, when you have a web page that has 31 style elements (either within <head/> or <body/>), everything displays fine in all browsers as you can see in the figure below.

Abnormal Circumstances…

Well, what happens to IE under these abnormal circumstances with web pages with 32 or more <style/> elements?

What does every other browser look like? They look correct.

The Code

Here is the code to see the bug yourself….

<html>
<head>
  <title>Style Element Test</title>

  <style type="text/css">
    .green_me { color: blue; }    /** Style block #1 */
  </style>
  <style type="text/css">
    .green_me { color: blue; }    /** Style block #2 */
  </style>
  <style type="text/css">
    .green_me { color: blue; }    /** Style block #3 */
  </style>
  <style type="text/css">
    .green_me { color: blue; }    /** Style block #4 */
  </style>
  <style type="text/css">
    .green_me { color: blue; }    /** Style block #5 */
  </style>
  <style type="text/css">
    .green_me { color: blue; }    /** Style block #6 */
  </style>
  <style type="text/css">
    .green_me { color: blue; }    /** Style block #7 */
  </style>
  <style type="text/css">
    .green_me { color: blue; }    /** Style block #8 */
  </style>
  <style type="text/css">
    .green_me { color: blue; }    /** Style block #9 */
  </style>
  <style type="text/css">
    .green_me { color: blue; }    /** Style block #10 */
  </style>
  <style type="text/css">
    .green_me { color: blue; }    /** Style block #11 */
  </style>
  <style type="text/css">
    .green_me { color: blue; }    /** Style block #12 */
  </style>
  <style type="text/css">
    .green_me { color: blue; }    /** Style block #13 */
  </style>
  <style type="text/css">
    .green_me { color: blue; }    /** Style block #14 */
  </style>
  <style type="text/css">
    .green_me { color: blue; }    /** Style block #15 */
  </style>
  <style type="text/css">
    .green_me { color: blue; }    /** Style block #16 */
  </style>
  <style type="text/css">
    .green_me { color: blue; }    /** Style block #17 */
  </style>
  <style type="text/css">
    .green_me { color: blue; }    /** Style block #18 */
  </style>
  <style type="text/css">
    .green_me { color: blue; }    /** Style block #19 */
  </style>
  <style type="text/css">
    .green_me { color: blue; }    /** Style block #20 */
  </style>
  <style type="text/css">
    .green_me { color: blue; }    /** Style block #21 */
  </style>
  <style type="text/css">
    .green_me { color: blue; }    /** Style block #22 */
  </style>
  <style type="text/css">
    .green_me { color: blue; }    /** Style block #23 */
  </style>
  <style type="text/css">
    .green_me { color: blue; }    /** Style block #24 */
  </style>
  <style type="text/css">
    .green_me { color: blue; }    /** Style block #25 */
  </style>
  <style type="text/css">
    .green_me { color: blue; }    /** Style block #26 */
  </style>
  <style type="text/css">
    .green_me { color: blue; }    /** Style block #27 */
  </style>
  <style type="text/css">
    .green_me { color: blue; }    /** Style block #28 */
  </style>
  <style type="text/css">
    .green_me { color: blue; }    /** Style block #29 */
  </style>
  <style type="text/css">
    .green_me { color: blue; }    /** Style block #30 */
  </style>
  <style type="text/css">
    .green_me { color: blue; }    /** Style block #31 */
  </style>
  <style type="text/css">
    .green_me { color: green; }    /** Style block #32 */
  </style>

</head>
<body>
  <h1 class="green_me">I Should Be Green!!!</h1>
</body>
</html>

Workarounds

Well, there aren’t any real “workarounds”.

UPDATE: 2008-11-04: Maybe I’m not making my point. The point here is NOT to condone using <style> tags like crazy and have 30+ on your page; let me say that again; the point here is NOT to condone using <style> tags like crazy!!! The point of this article is to make people aware of the issue and what a quick production hotfix might look like.

I’m sorry my diction sucked and I chose to use “bug” over “limitation“; sue me! Either way, I think Microsoft needs to fix it!

The server-side solutions options are pretty obvious:

  • Condense CSS into less (or a single) <style/> elements (good)
  • Put CSS into an external file and use the <link/> tag (best)
  • Add the correct CSS onto the inline atribute, “style”, on each element. (not as good)

UPDATE: 2008-11-04: Paul Davis mentioned below in the comments the most correct solution. I don’t know why I didn’t mention it. The solution is to have some response filter servlet or class that will condense the style tags for you. By doing this you don’t have to go to your 3rd party vendors and complain because they don’t use external stylesheets.

We all know what the best practices for CSS are; we just need to be aware of the limitations that will affect our judgment and implementation.

The client-side solutions options are non-trivial (and really should NOT be used unless a production hotfix is needed!!):

  • With JavaScript, manually parse the “forgotten” <style/> elements and add them to the last “unforgotten” DOM  stylsheet (document.styleSheets[ document.styleSheets.length ]).
  • With JavaScript, manually parse the “forgotten” <style/> elements and then apply the style to each respective element/selector.

Using jQuery, here is an example of how to temporarily fix this client-side

$(document).ready(function(){
  // If msie and we have more than the allotted stylsheets...
  if ( $.browser.msie && $('style').length != document.styleSheets.length ) {
    var ssAry = $('style');
    // Loop through the extra stylesheets not read and apply the styles found
    for ( var i = document.styleSheets.length; i < ssAry.length; i++ ) {
      var cssText = ssAry[ i ].innerHTML;
      // Replace newlines and then comments
      cssText = cssText.replace(/[\n\r]/g, "");
      cssText = cssText.replace(/\/\*\**[^\*\/]*\*\//g, "");

      // Loop over all CSS selector groups...
      var regex = new RegExp(/{[^}]*}/);
      for ( var value = regex.exec( cssText ); value; value = regex.exec( cssText ) ) {
        // Split the css grouping into the selector and the CSS properties
        var pair = cssText.substring( 0, regex.lastIndex )
                          .replace(/}/g, "").split(/{/);
        // Add it to the last DOM stylesheet
        document.styleSheets[ document.styleSheets.length - 1 ].addRule(
          pair[ 0 ].replace(/^\s+|\s+$/g, ""),
          pair[ 1 ].replace(/^\s+|\s+$/g, "")
        );
        // Strip off the applied CSS
        cssText = cssText.substring( regex.lastIndex );
      }
    }
  }
});

Make sure you fully understand the above code before you copy/paste it!!!

16 thoughts on “Internet Explorer Doesn’t Evaluate Any More Than 31 Style Elements

  1. Wow, and we just confirmed, the Knowledgebase article you point to only lists through IE v6, but we tested 7 and 8 beta, they do the same thing.

  2. bad bug to have but if you are putting that many style tags in your head tag then you should uninstall the al mighty dreamweaver and switch to a text editor. See how much you like to write those style tags then.

  3. The workaround would be to create a servlet filter to strip them all out and condense to a single style element.

    It’s a pretty small amount of work.

    Good luck

  4. Why 31? Simple, 42 is the answer to life, the universe and everything else. 42 – 31 = 11 and according to Aeon Flux movie in the year 2011, 99% of the humanity will be wiped out because of a deadly virus, so Microsoft is warning you!

  5. Using 31 style calls is insane. Why not put your CSS in some PHP script that checks to see what you really need and then dump it out all at once in 1 STYLE tag rather than in several?

  6. This problem may raise when you’re using component-oriented javascript development and a component instance does not do proper clean up upon it’s destruction. (i.e. ExtJS 1.x grid)

  7. > 31 style calls is insane.

    The web is insane! What if you are working on a complex information site with lots of advertising on it, and all the ads have their own style sheets?

  8. The point of this article was NOT “hey, you should use 30 or more stylesheets!!!”.

    The point was that the problem exists out there, and there may be circumstances where it may happen.

    Workarounds are not complete solutions! Workarounds are meant to temporarily fix the problem while you take the time to find the correct solution. I guess I should have stated that…

    Paul Davis has the most proper complete solution. Stick a servlet in the response pipeline that filters the style tags into a single style tag. This method combined with sticking CSS in fewer style tags and external stylesheets will be your best bet.

  9. Aw, this was a really good post. Finding the time and actual effort to produce
    a really good article… but what can I say… I
    procrastinate a lot and don’t seem to get anything done.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>