Simulating Attributes Selectors in IE6

Simulating Attributes Selectors in IE6

  • Posted on 03/30/2007 at 08:30 AM by Sandra Clark
  • Categories: CSS / JavaScript

Especially now that IE7 supports attribute selectors, using classes in my HTML to reflect those items has become a real bummer. I really like the idea of not requiring people maintaining HTML to worry about classes. I think it makes for cleaner markup and for easier training. So, while I'm not a JavaScript maven by any means, I decided to play around with this and actually made it work.

What is an Attribute Selector Anyway?

An attribute selector is a CSS selector which says basically, "use these style rules if the value of an attribute is equal to something specific". I tend to use attribute selectors mainly with forms, so my sample function deals exclusively with the input element. It can however be extended to anything you want. So, if I want to target my CSS to only text inputs, or only select buttons, or only checkboxes. I can use an attribute selector instead of a class.

div#leftCol input[type="submit"]{}

Will only style submit elements within a <div id="leftCol"></div>

Pretty neat! and extremely useful. But IE6 doesn't recognize attribute selectors and we would still need to use classes for this browser. I could place a class="submitbutton" within every <input type="submit" class="submitbutton" />, but that is clunky and negates the power of attribute selectors.

What I can do however, is in my CSS, where ever there is an attribute selector, I can add a rule for a specific class as well.

So my CSS starts looking like: div#leftCol input[type="submit"], div#leftCol input.submitbutton {}

This is okay, since the complexity is in my CSS and not in my HTML.

To simulate the attribute selectors in IE6, I add some javascript. Prior to my stylesheets, I load a javascript within an IE conditional Statement

<head> <!--[if lt IE 7]> <script type="text/javascript" src="assets/js/ie6css.js" ></script> <![endif]--> <link rel="stylesheet" type="text/css" href="assets/css/styles.css" /> </head> <body onload="changeClasses(document)"> ... </body>

The JavaScript will only trigger if the browser is Internet Explorer and if it is a version earlier than 7. So it won't trigger at all for Gecko or other browsers and it won't trigger if the user is coming in with Internet Explorer 7. I call the javascript changeClasses() function on the body onload. Since it doesn't exist for any browser other than the one I am triggering, it works fine in all browsers and doesn't upset anything.

The JavaScript function called in "ie6css.js" works with the getElementsByTagName() function to retrieve an array of elements which are <input /> tags. It then loops through those tags and appends specific classes to those items, so they too can benefit from the CSS.

ie6css.js

function changeClasses(currentdoc){ var inputElements = currentdoc.getElementsByTagName('input'); for (var i=0; i<inputElements.length; i++){ if(inputElements[i].type == "submit"){ inputElements[i].className = inputElements[i].className + " submitbutton"; } else if (inputElements[i].type == "checkbox"){ inputElements[i].className = inputElements[i].className + " checkbox"; } else if (inputElements[i].type == "radio"){ inputElements[i].className = inputElements[i].className + " radio"; } else if (inputElements[i].type == "text"){ inputElements[i].className = inputElements[i].className + " textbox"; } } }

As you can see, it appends the new class to the className property (just in case there is a previously existing class). The CSS stylesheets pick it up and apply the rules and voila. IE6 simulated Attribute Selectors!

Add a Comment

  • Posted By Julian Halliwell
  • Posted On April 2, 2007 at 02:57 AM
Hi Sandy,

If you've got to support IE6 and have the "submitbutton" class anyway, is there any point in using the CSS attribute selectors? It makes the stylesheet more complex, as you say, and you've got the conditional javascript to manage as well.

Simpler would be just to unobtrusively add the "submitbutton" class to all input type="submit" elements regardless of browser, no?

And if you haven't checked it out, jQuery is fantastic for this kind of thing:

$(function(){ var arraySubmitButtons = $("input[@type=submit]").get(); $(arraySubmitButtons).each(function(){ $(this).addClass("submitbutton"); }); });

The above in a script block preceded by the jquery core js (19kb) is all you need to add all the classes when the document loads. Body onload not necessary so your HTML is even cleaner.

http://simplicityweb.co.uk

  • Posted By Sri Sankaran
  • Posted On July 31, 2007 at 09:17 PM
Thanks for this hint on how to possibly get attribute selector "working" in IEn<7.

I am still having problems with having

input[type="text"],input.text_foo { ...}

The only way IE seems to be happy is if I have *only*

input.text_foo {...}

I am working through this. (Fingers crossed).

AFA using jQuery (Julian's comment) I prefer the slightly more verbose but highly more human-readable version. Yes, one can can completely eliminate the if-else in the changeClasses() function with something like

inputElements[i].className + " " + inputElements[i].type + "_foo";

but that's implementation details.

  • Posted By Ryan
  • Posted On February 29, 2008 at 12:53 AM
Have you played around with object.className ? it's the javascript way of changing style classes, but it doesn't work well on ie6???

...

  • Posted By Kirk
  • Posted On April 26, 2008 at 02:41 PM
fyi, with Prototype these are all one-liners

$$('input[type="text"]').invoke('addClassName', 'text'); $$('input[type="password"]').invoke('addClassName', 'password'); $$('input[type="checkbox"]').invoke('addClassName', 'checkbox'); ...

However.. you'll notice that implementing this type of fix in javascript will cause flicker on page load. There's no way around placing it in the html if you don't want to see this flicker.

On my most recent site, I've opted just to ignore ie6 input styling. I'd rather move forwards than have to place all of the logic necessary to support it and it's not critical to page functionality.

  • Posted By Phillip
  • Posted On April 25, 2008 at 09:23 AM
Not a bad idea, i've modified it for use on a project im doing. Heres my final code:

//Function for IE 6 since it doesn't support Attribute Selectors function addClassNames(){ var elements = document.getElementsByTagName("input"); for (var i=0; i < elements.length; i++) { var element = elements[i]; if (element.type == "submit" || element.type == "submit") { element.className = element.className + " button"; } else if (element.type == "text" || element.type == "password") { element.className = element.className + " textbox"; } else if (element.type == "checkbox") { element.className = element.className + " checkbox"; } else if (element.type == "radio") { element.className = element.className + " radio"; } } }

//Automatically run the script on page load window.onload = addClassNames;

www.philliphaydon.com

  • Posted By Phillip
  • Posted On April 25, 2008 at 09:24 AM
Not a bad idea, i've modified it for use on a project im doing. Heres my final code:

//Function for IE 6 since it doesn't support Attribute Selectors function addClassNames(){ var elements = document.getElementsByTagName("input"); for (var i=0; i < elements.length; i++) { var element = elements[i]; if (element.type == "submit" || element.type == "submit") { element.className = element.className + " button"; } else if (element.type == "text" || element.type == "password") { element.className = element.className + " textbox"; } else if (element.type == "checkbox") { element.className = element.className + " checkbox"; } else if (element.type == "radio") { element.className = element.className + " radio"; } } }

//Automatically run the script on page load window.onload = addClassNames;

Edit: That script is for the IE6 javascript file. The window.onload runs the script without the need of putting it into the tag. So no javascript errors.

www.philliphaydon.com

  • Posted By D Jackson
  • Posted On January 18, 2008 at 05:45 AM
Running onload="changeClasses(document)" on browsers that are not IE6 will generate a JS error.

Post Your Comment Here