with Imagination: by Dustin Diaz

./with Imagination

A JavaScript, CSS, XHTML web log focusing on usability and accessibility by Dustin Diaz

Input Element CSS woes are over

Thursday, June 30th, 2005

Somewhere between January and now, my head has been so far stuck up the DOM, I’m out to figure out every last browser annoyance I’ve ran into and fix it with javascript.

First off; The problem. I want to style my <input /> elements differently depending whether they are type=”text” or type=”input” (or “button”).

If we all lived in the future of css 3, we could easily do the following…


input[type="text"] {
font:bold 10px/12px verdana,arial,serif;
padding:3px;
}
input[type="button"],input[type="submit"] {
/* you know what to do */
}

Get over it. Use CSS 2.1

Being the “non-browser Elitist” I am (meaning, I’m not going to ignore the fact that 85% of users are browsing with a device that won’t understand CSS3), I decided to fix this.

Quick solution

Let’s just change our HTML to this.


<input type="text" class="text" value="" />
<input type="button" class="button" value="I am a button" />
<input type="submit" class="button" value="I am a submit" />

Then have the complimenting CSS:


input.text { /* my text css */ }
input.button { /* my button css */ }

Simple enough… but I’m still not satisifed. I’m thinking to myself, What a hassle. Who really wants to append all those classes.

Javascript will do it for you

Need I say more….


function changeInputs()
{
var els = document.getElementsByTagName('input');
var elsLen = els.length;
var i = 0;
for ( i=0;i<elsLen;i++ )
{
if ( els[i].getAttribute(’type’) )
{
if ( els[i].getAttribute(’type’) == “text” )
els[i].className = ‘text’;
else
els[i].className = ‘button’;
}
}
}

With this, simply keep your CSS as it was with the input.text and input.button, but this time you don’t need to write the class names in your HTML. It works out just great.

Oh. And don’t forget to attach this function to an onload event handler.

Eg.


window.onload = function() { changeInputs(); }

There ya go.

27 Responses to “Input Element CSS woes are over”

  1. Elliot Swan

    But what about those without Javascript enabled? I’d rather just to bite the nail and apply the classes, letting all (minus those without CSS enabled) see your styles rather than saving myself a few minutes.

  2. Dustin

    oh right… what about that 1%?
    They’re purely missing out on better asthetics. I say it’s well worth it.

    The page still works doesn’t it?

  3. Justin P.

    Nice, cool idea Dustin.

    I tend to give my buttons a class of “btn” and then give global stylings to all input controls, then some targeted rules to the input.btn to differentiate it from the other input controls. I know it’s wacky, but it does the job for me.

    To add to your code, I think it should append the class name, not overwrite the class name…

    if ( els[i].getAttribute(’type’) == “text” )
    els[i].className += ‘ text’;
    else
    els[i].className += ‘ button’;

    Really cool though, make that DOM work for you!

  4. Dustin

    Justin. I like your suggestion. I’m going to ammend it to do just so.

  5. Jonatan

    I was just figuring.. will

    if ( els[i].getAttribute(’type’) == “text” )

    identify any inputs initiated with no such attribute?

    (i.e.

    )

  6. Jonatan

    (html stripped..)

    <input name=”whatev”>

  7. Dustin

    technically, without a type attribute, you have malformed html.

    if you want your js to validate against such an error, you could check to see if the type exists first…

    eg.

    if ( els[i].getAttribute(’type’) && els[i].getAttribute(’type’) == ‘text’

  8. Amol

    I like this hole concept of changing things with js.
    Could you guys also help me and tell how do i make the js external file and call it on onload and where?

  9. Matt

    I’ve been a web admin at several companies over the last 8 years. I keep hearing this idea of people having javascript disabled and yet to find one person who actually disabled their javascript.

  10. trovster

    BTW, attribute selectors are CSS2.1.

  11. meindert

    Amol,

    How to put it in a external file and how to call onload;

    window.onload = function() { changeInputs(); }

  12. Andrew Pollack

    Damn, I missed one paren. sorry.

    -
    
     function changeInputs() {
    	var els = document.getElementsByTagName('input');
    	for (var i=0; i <  els.length ;i++ ){
    		if ( els[i].getAttribute('type') ) {
    			if ( els[i].getAttribute('type') == "text" ) {
    				if(els[1].className ) { els[i].className = els[i].className +  ' text '; } else { els[i].className = ' text '; }				} else {
    				if(els[1].className ) {els[i].className = els[i].className +  ' button ' ; } else { els[i].className = ' button '; }
    }	}	}	}
    
    

    -

  13. Simon

    Just found this and having heard of you though boagworld, this is a great tip - thank you.

    I know this may increase the number of classes, but why not do the following instead of the if statements.

    
    classToAdd = " " + els[i].getAttribute('type');
    els[i].className += classToAdd;
    
  14. ionut

    Hey guys it was posted earlier! It is possible to do this: attribute selectors are CSS2.1! This is great, thank you trovster! \n ex: input[type=text]{//css}

  15. Chris

    What a great method. It’s so obviouse… I used alot of your ideas in a project I’m currently working on. For my purposes, I ammended your script to check if the input element is already assigned a style class name, if so I leave it alone, otherwise assign the default style name “textbox”. Great solution, can’t wait until CSS 3 is better supported so we dont have to worry about this anymore.

  16. Sean

    As of July 1, 07 Firefox 2.0.2, Opera 9.1, Safari’s 3.0 beta and even IE 7 can handle this kind of form styling. No need for javascript or extra classes anymore. Move on and give users a reason to upgrade instead of coddling their laziness.

  17. Matt

    Hey, with your code you also get password fields marked as buttons. One fix is to change the if statement to if:

     ( (els[i].getAttribute('type') == "text" ) || (els[i].getAttribute('type') == "password" ) )
  18. dan

    Ahhhh!!! Been beating my head on the keyboard all morning. We are migrating a HUGE site, and the nimrod that did the site before me didn’t use CSS AT ALL!.
    This script works great. You ROCK!

  19. Igor

    Damn :)

    window.onload = function()
    {
      var coll = document.getElementsByTagName("input");
      for(var i=0; i<coll.length; i++)
      {
         if(coll[i].type == "button" || coll[i].type == "submit" || coll[i].type == "reset")
         {
            coll[i].className = "myclass";
         }
      }
    }
  20. Gary

    Lets not forget that this does not work on the “browse” button that the input type file creates. This button is not accessible at all… grrrrrr

  21. Movie Man

    I’m just getting nuts trying to apply some style to that “Browse” button… Damn it…

  22. Tony

    You could also decide NOT TO USE javascript….Why?
    It only causes problems if you try hack solutions like the one above. BTW…less javascript on a page and less memory stack problems in your browsers.
    Use javascript to solve every little quirky problem and you end up slowing down the page download. Remember that to this day people don’t have superfast machines to render pages fast enough. If it takes a page more than 5 seconds to upload then that’s only driving “consumed” internet users away.
    So the trick is to use more of the css without id’ing everything as this also requires memory in your browser especially IE and less of the javascript.

  23. Ross

    @ionut:
    Attribute selectors are part of CSS2.1, but they don’t work in IE6. http://www.quirksmode.org/css/selector_attribute.html

    Regrettably, this will rule them out for most people.

  24. Brandon

    @Tony: You’re an idiot. Javascript doesn’t cause memory stack problems any more than C++ causes the Blue Screen of Death. It’s just a programming language, and a well-written bit of Javascript can improve the user experience, save on download times (because external Javascript files can be cached and reused site-wide), and can offer features that static pages can’t.

    Images increase download time. Perhaps you’d recommend that we do away with those, too?

    If it takes a page more than 5 seconds to load, and this drives you away from sites you’d otherwise want to visit, perhaps you should: a) clean out any spyware you’ve accumulated, b) invest in a faster Internet connection, and/or c) try to cultivate a little patience.

  25. David

    You guys are amazing.

    I wanted a “global” solution to style my buttons (submit and otherwise) with my CSS file but DID NOT want to have to rely on tagging every single input control with an class ID tag… not only would that be a pain and I’d forget to include the tag invariably, but many .Net controls (like the gridview) create button controls as part of their featureset but don’t let you add any style class reference to the dynamically generated buttons! I needed something that would just “see” every button for what it was… and style it (just like I can do for A tags, H1 tags etc).

    And you guys solved the riddle. Thanks.

  26. David

    Awesome snippet man, exactly what I needed.

    Re: Tony’s comment - keep in mind that a LOT of developers do corporate in house work where download speeds are not an issue because the only users are on the local network. I use EXT’s entire library and the initial page load comes at at near 1MB. From my user’s POV though, it takes maybe 1-2 seconds - which is sometimes what it takes them for Google or MSN during peak times, so nobody notices. As mentioned, it is cached after that and performance is lightning fast. Point is - just because there are a handful of people that will or can NOT use javascript doesn’t mean there aren’t millions of others - on high bandwidth pipes - that will.

  27. Angel

    Hey, thanks, seriously, for the snippet. Never thought anything like it.

    A plus i added to the code is that instead of hardcoding in text strings the types, you the type assign as the class for each element, like:

    window.onload = function()
    {
    var coll = document.getElementsByTagName(”input”);
    for(var i=0; i<coll.length; i++)
    {
    if(coll[i].type)
    {
    coll[i].className += ‘ ‘ + coll[i].type + ‘ ‘;
    }
    }
    }

    That way, all inputs are asigned classes with their own names (without overwritting any additional clases the input might have)

    Thanks for everything!! Keep the cool ideas up!!!

Get "JavaScript Design Patterns"

"As a web developer, you'll already know that JavaScript™ is a powerful language, allowing you to add an impressive array of dynamic functionality to otherwise static web sites. But there is more power waiting to be unlocked--JavaScript is capable of full object-oriented capabilities, and by applying OOP principles, best practices, and design patterns to your code, you can make it more powerful, more efficient, and easier to work with alone or as part of a team."

Buy JS Design Patterns from Amazon.com Buy JS Design Patterns from Apress

Submit a Prototype

All content copyright © 2003 - 2007 under the Creative Commons License. Wanna know something? Just ask.

About | Archives | Blog Search

[x] close

Loading...

Submit a prototype

By checking this prototype I agree that I am not submitting false credentials, pornography, or a hate crime website. I also understand that by submitting my entry I may or may not be accepted, and if accepted, my entry may be taken down at any given time if I violate these terms.