the Future of the Web
  • Articles
  • Contact
  • No-JavaScript CSS

    Nov 28 2005

    On one of my web sites, I use JavaScript to show/hide div layers containing each section. I have links to "#section-five" for example, but the onclick event changes the section-five div to display: block; and the previous div to display: none;. This is designed so that browsers without CSS or JavaScript will still be able to use the links as regular anchor links. This assumes, though, that the visitor would either have both CSS and JavaScript, or neither.

    Since I wrote this, I've been struggling with how to deal with visitors who have CSS but not JavaScript. Today I figured out a way to do this.

    The typical solution would be to have display: block; set by default, then to use JavaScript to set display: none; onload. I tried this solution, but I didn't like how all the layers appeared at first, then suddenly disappear. I wanted a solution that wouldn't affect the experience for most users.

    All I needed to do was display different CSS to users without JavaScript. To accomplish this, I first considered setting disabled on the style sheet, then using JavaScript to enable the CSS link. This didn't work right in Firefox because Firefox ignores the disabled attribute of link tags.

    Next, I tried setting the href on the link tag to href="", then dynamically setting the href using JavaScript. This worked good, except then users without JavaScript would be forced to see the page without CSS. It was perfectly usable but looked pretty boring.

    Finally, I came up with this compromise. The link tag on the page is:

    <link rel="stylesheet" type="text/css" media="screen"
     href="nojavascript.css" id="stylesheet"/>

    so by default, visitors will get a "nojavascript.css" CSS file. This file contains:

    @import "screen.css";
    div.section { display: block; }
    #ads { display: none; }

    So without JavaScript, the page has all the div layers displayed, except the ads. (Adsense and Chitika won't work without JavaScript anyway.) Also, by using an @import, I won't have to maintain two almost-identical CSS files.

    Next, I added a line to the JavaScript file attached to the page:

    document.getElementById('stylesheet').href = "screen.css";
    

    Note that I didn't put it in an onload function. I don't want the page to change once it's been loaded; I want it to look right from the start. If you do this, you'll have to make sure that the <script> tag comes after the <link> tag.

    The other nice thing about this method: it ensures that users with browsers that doesn't support getElementById will still get the nojavascript.css file. This is important because it is the only method I use for handling the onclicks.

    That's it. Simple, yet powerful.

    View 4 Comments | Add a comment
  • Comments

    1. kontur at 9:59am on June 28, 2006

    nice article ;)

    2. Matthew Taylor at 1:18am on June 7, 2007

    I've been looking for a solution like this for ages, finally I've found it!

    It's a pity we can't use the noscript tags in the head of an html document, if we could, a non-JavaScript-CSS file could be linked to in this way without using JavaScript at all. That is obviously too good to be true.

    3. mike foskett at 1:35pm on November 8, 2007

    Have you considered doing this instead:

    <script type="text/javascript">/*<![CDATA[*/document.documentElement.className="hasJS"/*]]>*/</script>

    Add the script directly after the page title. Now refernce the hide div like so:

    .hasJS div.hide {display:none}

    html.hasJS only exists if JS is available.

    The real beauty is the speed of it. Because it's ran before the style sheet there is zero delay in both loading and implementation. Oh, and it's valid W3C grammar to boot.

    4. Dan Lim at 10:44am on July 26, 2010

    This is a nice solution. I'm surprised google didn't bring more results, would have thought this would be a common problem found by developers.

    Commenting is now closed.

  • Jesse Skinner

    Jesse Skinner
    • About Me
    • Email Me
    • RSS Feed RSS Icon
    • @JesseSkinner
  • Recent Articles

    • Free eBook: Unobtrusive Ajax
    • Official jQuery Templating Plugin
    • jQuery Live Events
    • buttons need type="submit" to submit in IE
    • Use Arrays in HTML Form Variables
    • 5 Reasons Freelancers Can Succeed in a Shrinking Economy
    • Keeping a Live Eye on Logs
    • Using PHP's empty() Instead of isset() and count()
    • Testing Web Pages with Lynx
    • Stop CSS Background Flickering in Internet Explorer 6
    • See All...
  • Categories

    • javascript (41)
    • about (17)
    • links (17)
    • web (14)
    • html (12)
    • server (11)
    • css (8)
    • browsers (8)
    • carnival (7)
    • work (5)
    • design (4)
    • seo (4)
    • ads (4)
    • standards (4)
    • events (4)
  • Older Articles

    • October 2010
    • February 2009
    • January 2009
    • December 2008
    • November 2008
    • October 2008
    • July 2008
    • June 2008
    • May 2008
    • April 2008
    • February 2008
    • January 2008
    • December 2007
    • November 2007
    • September 2007
    • August 2007
    • July 2007
    • June 2007
    • May 2007
    • April 2007
    • March 2007
    • February 2007
    • January 2007
    • December 2006
    • November 2006
    • October 2006
    • September 2006
    • August 2006
    • July 2006
    • June 2006
    • May 2006
    • April 2006
    • March 2006
    • February 2006
    • January 2006
    • December 2005
    • November 2005
    • October 2005
    • September 2005
    • August 2005
    • April 2005
    • See All...
Copyright © 2013 The Future of the Web