hasLayout.net

32 Styles Limitation

Affected Versions

This bug affects: IE8, IE7

Symptoms

Styles are ignored when they are set in the 32nd (or later) style method (i.e. <style>, <link> or @import)

Date of the Tutorial

Wed Aug 12 14:58:58 2009

Description

Here's something that may drive you up the wall if you are working on a site with a lot of 3rd party ads or applications that want to stick their own ' element"><style> (or ' element"><link>) elements... and by a lot I mean 32. Let's glance at the demo and I'll explain:

Demo

Due to the nature of the bug, the demo is available on a separate page

HTML Code:
<style type="text/css"></style> <!--1-->
<style type="text/css"></style> <!--2-->
<style type="text/css"></style> <!--3-->
<style type="text/css"></style> <!--4-->
<style type="text/css"></style> <!--5-->
<style type="text/css"></style> <!--6-->
<style type="text/css"></style> <!--7-->
<style type="text/css"></style> <!--8-->
<style type="text/css"></style> <!--9-->
<style type="text/css"></style> <!--10-->
<style type="text/css"></style> <!--11-->
<style type="text/css"></style> <!--12-->
<style type="text/css"></style> <!--13-->
<style type="text/css"></style> <!--14-->
<style type="text/css"></style> <!--15-->
<style type="text/css"></style> <!--16-->
<style type="text/css"></style> <!--17-->
<style type="text/css"></style> <!--18-->
<style type="text/css"></style> <!--19-->
<style type="text/css"></style> <!--20-->
<style type="text/css"></style> <!--21-->
<style type="text/css"></style> <!--22-->
<style type="text/css"></style> <!--23-->
<style type="text/css"></style> <!--24-->
<style type="text/css"></style> <!--25-->
<style type="text/css"></style> <!--26-->
<style type="text/css"></style> <!--27-->
<style type="text/css"></style> <!--28-->
<style type="text/css"></style> <!--29-->
<style type="text/css"></style> <!--30-->
<style type="text/css"></style> <!--31-->
<style type="text/css">p { border: 5px solid #000; }</style> <!--32-->
<p>I should have borders!</p>

First of all, despite the fact that I've used 32 ' element"><style> elements in the demo, the limitation affects ' element"><link> elements as well as using @import url() to link in the sheets; all these can be used together to "reach" the 32-style limit (although with @imports the limit seems to be 35.

In the demo, the 32nd ' element"><style> element is applying border to the ' element"><p>; in IEs no border is set unless we delete some of the previous ' element"><style> elements.

Solutions

Below are solutions for the above bug ordered by the solution type.

Solution (Pseudo Bug)

Date of the Solution

Wed Aug 12 15:28:11 2009

Fixed Versions

All of the affected

Description

If you encountered this limitation in in a "real" website, it is likely that "simply use less ' element"><style> elements" may not be an option and the solution to the problem will be much more complex. Due to that fact, on the "fixed demo" I'll only show that the limitation is indeed present:

Due to the nature of the bug, fixed demo is available on a separate page

HTML Code:
<style type="text/css">p { border: 5px solid #000; }</style> <!--1-->
<p>I should have borders!</p>

If you cannot apply the "use less styles" solution, things get more complex. The best solution would be to employ some kind of post-processor that would strip off all the excess style elements and merge them into one style.

If the contents of ' element"><style> elements are of static nature, you can simply duplicate the code and put it in the ' element"><link>/' element"><style> elements that appear before the limit.

If the deadline is breathing onto your neck and you really need a fast fix; below is a jQuery code that I found on the page where I found the bug; I have not tested this code, so use at your "own risk" so to say:

$(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 );
      }
    }
  }
});

Note that you shouldn't be using this code as a permanent fix.