Let Them Eat Cake

There has been a growing debate lately that pits accessibility against usability, but there’s no reason we can’t have both. If you can make a page more usable without making it less accessible, by all means do so; do not let your inability to translate certain usability enhancements into accessible functions or features restrict your use of those enhancements. As long as the enhancements do not restrict accessibility, go for it.

Article Continues Below

As many of you know, with JavaScript and the DOM, we have the ability to control every element on a well-structured web page. It is my feeling that, using the DOM, we can improve the usability of a page without restricting its accessibility. Sprinkle in a little CSS, and we have the recipe for a wonderful experience all around, regardless of the browser, platform or device being used.

Ingredients: a well-structured document#section2

To begin, we need a well-structured document. My example will be an article, this one in fact, consisting of a single page with jump refs to the various content sections.

Let’s establish that our goal is to present this article in a highly accessible, yet entirely usable way. The article is divided into sections and, as human psychology demonstrates, information is easier to digest in chunks. One way to make a lengthy article easier to follow is to display the content section by section. This not only aids in digesting the information but reduces scrolling (which appeals to the many who remain convinced that the general population still has no clue how to scroll).

How do we meet this usability goal without causing accessibility issues? Enter the DOM.

Preparation: pour in the DOM; mix and bake#section3

As you have probably noticed, the navigation links within the header section of the document are jump refs to the different sections (divisions) of the article. The first link (“Introduction”) takes you to the introduction of the article (wrapped in <div id="intro"></div>). This not only makes the page easier to navigate, but it also makes it easier for other people to reference particular sections of the article from their own work (via citations or links). The helpful “Back to top” links also reorient users as needed.

Glancing at the source, we can see that the whole document uses semantic ids for divvying up the document into manageable chunks. This offers us a world of possibilities. With the aid of the DOM, we can easily traverse the page, looking at the ids of the divisions, hiding the ones we don’t want immediately visible. The basic code would look something like this:

  function hideDivs()
  {
    var divs =
      document.getElementsByTagName("div");
    for(var i=0; i < divs.length; i++)
    {
      var div = divs[ i ];
      var id = div.id;
      if ((id != "header") &&
          (id != "footer"))
      {
        div.style.display = "none";
      }
    }
  }
  
  window.onload = function()
  {
    hideDivs();
  }

First, we collect all of the <div>s on the page into an array, and then we loop through the array, hiding all of them with the exception of the ones with ids of “header” and “footer”. In the interest of hiding the script from older browsers which don’t understand document.getElementsByTagName, we should add the following line to the beginning of the function:

if (!document.getElementsByTagName) {
  return null;
}

Now we have hidden everything from the browser (with the exception of the header and footer <div>s), which means that no article content is available for the user to read. We should show the introduction right off the bat, so we need to make a slight modification to the hideDivs function. We could hard code a conditional statement for id == "intro" into the function (alongside the header and footer ones), but that doesn’t give us much flexibility. If we add an argument to the function called exempt, we can specify a <div> to exclude from the function on the fly:

  function hideDivs(exempt)
  {
    if (!document.getElementsByTagName) {
      return null;
    }
    if (!exempt) exempt = "";
    var divs =
      document.getElementsByTagName("div");
    for(var i=0; i < divs.length; i++)
    {
      var div = divs[ i ];
      var id = div.id;
      if ((id != "header") &&
          (id != "footer") &&
          (id != exempt))
      {
        div.style.display = "none";
      }
    }
  }
  
  window.onload = function()
  {
    hideDivs("intro");
  }

We pass the value “intro” to the function upon page load as the exemption, and that sets up our document for its initial state. But how do we allow the user to view other sections? If we take a look at the document structure, we already have links to the varying sections as jump refs. This is perfect, because each jump ref link (e.g. #ingredients) already contains the id of the <div> we want it to show. All we have to do is find a way to change the link so that it triggers a JavaScript funtion to show the chosen section and hide the others. Enter the DOM again:

  function fixLinks()
  {
    if (!document.getElementsByTagName) {
      return null;
    }
    var anchors =
      document.getElementsByTagName("a");
    for(var i=0; i < anchors.length; i++)
    {
      var a = anchors[ i ];
      var href = a.href;
      if ((href.indexOf("#") != -1) &&
          (href.indexOf("header") == -1))
      {
        var index = href.indexOf("#") + 1;
        href = "javascript:show('" +
          href.substring(index) + "');";
        a.setAttribute("href",href);
      }
    }
  }

In this function, we parse the document looking for <a> tags which contain “#” in the href attribute. In order to avoid grabbing the “Back to top” links, we add in an exclusion of links containing the term “header”. The id of the <div> the link was referencing is separated from the #, and the href is then reconstituted as the target <div> id wrapped inside a JavaScript function called show. We add fixLinks to the list of functions called upon in the onload function, and we’re halfway there.

The brilliance of having JavaScript rewrite the link as a JavaScript call is that we already know JavaScript is operating on the user’s device, so we are assured that <a href="javascript:show(‘ingredients’);"> will not be meaningless to the browsing device. If a user’s browsing device does not support JavaScript (or does not support it to the extent that it understands document.getElementsByTagName), the links remain unchanged, jump refs to the different divisions of the page. Likewise, the divisions all remain visible, so both accessibility and usability are well-served.

Now, about that show function… This is a simple function that uses the DOM to show an identified node and hide the rest. We already have a great multi-purpose hiding function in hideDivs, so all we need is the “show” part. Here’s the code:

  function show(what)
  {
    if (!document.getElementById) {
      return null;
    }
    showWhat =
      document.getElementById(what);
    showWhat.style.display = "block";
    hideDivs(what);
  }

We begin by testing to be sure document.getElementById is supported, and then we display the <div> with an id equal to the value we passed to the function. We wrap it all up with a call to hideDivs, passing it the value of the newly shown <div> as the exemption. The resulting page only needs us to make it a little more attractive.

Decoration: liberal application of CSS#section4

This part is up to you; decorate as you see fit. My basic example has a cakey theme with minimal decoration. Apart from aesthetics, however, there are some improvements we can make to what we have done so far using CSS.

A problem with the code we’ve written becomes clear when a user goes to print the article (which I hope they do). You see, having JavaScript change the display style of a node causes most (if not all) browsers to treat the style application as an inline style. According to the cascade rules of CSS, inline has the greatest precedence, so it overrides all other styles. If we want someone to be able to print the entire article and not just one section at a time, we need to make sure that all sections of the page are visible. This is accomplished by creating a class (let’s call it “hidden”) within a stylesheet that is applied to the screen media type only, and hides the content:

  .hidden {
    display: none;
  }

In your print stylesheet (if you have one), leaving out this class would cause anything classed with it to be displayed by default.

Now we can go back and fix the JavaScript functions accordingly:

  function hideDivs(exempt)
  {
    if (!document.getElementsByTagName) {
      return null;
    }
    if (!exempt) exempt = "";
    var divs =
      document.getElementsByTagName("div");
    for(var i=0; i < divs.length; i++)
    {
      var div = divs[ i ];
      var id = div.id;
      if ((id != "header") &&
          (id != "footer") &&
          (id != exempt))
      {
        div.className = "hidden";
      }
    }
  }
  
  function fixLinks()
  {
    if (!document.getElementsByTagName) {
      return null;
    }
    var anchors =
      document.getElementsByTagName("a");
    for(var i=0; i < anchors.length; i++)
    {
      var a = anchors[ i ];
      var href = a.href;
      if ((href.indexOf("#") != -1) &&
          (href.indexOf("header") == -1))
      {
        var index = href.indexOf("#") + 1;
        href = "javascript:show('" +
          href.substring(index) + "');";
        a.setAttribute("href",href);
      }
    }
  }
  
  function show(what)
  {
    if (!document.getElementById) {
      return null;
    }
    showWhat =
      document.getElementById(what);
    showWhat.className = "";
    hideDivs(what);
  }
  
  window.onload = function()
  {
    hideDivs("intro");
    fixLinks();
  }

One final housekeeping note: we should re-examine those “Back to top” links. Now that we have a page which only shows sections based upon the link we click, we simply don’t need them around, confusing people. Additionally, we don’t want them popping up in a print version of the page, where they really don’t serve any function. One quick addition to the fixLinks function can solve this:

  function fixLinks()
  {
    if (!document.getElementsByTagName) {
      return null;
    }
    var anchors =
      document.getElementsByTagName("a");
    for(var i=0; i < anchors.length; i++)
    {
      var a = anchors[ i ];
      var href = a.href;
      if (href.indexOf("#header") != -1) {
        a.className = "alt";
      } else if ((href.indexOf("#") != -1) &&
        (href.indexOf("header") == -1))
      {
        var index = href.indexOf("#") + 1;
        href = "javascript:show('" +
          href.substring(index) + "');";
        a.setAttribute("href",href);
      }
    }
  }

With the addition of an .alt style to the screen and print stylesheets…

  .alt {
    display: none;
  }

...it all comes together nicely. I encourage you to explore print stylesheets further by reading Eric Meyer’s superb reference on the subject, CSS Design: Going to Print.

Suggested serving: one document, infinite possibilities#section5

This article, though by no means meant to be the end-all, be-all on the concept of helping usability and accessibility play nicely together, will hopefully give you inspiration and methods to improve your own projects, in order to meet diverse needs, while excluding no one. As accessibility becomes a greater concern in the private sector, we need to keep usability fresh in our minds as well. The examples created here are meant to give you ideas for rewriting your usability enhancements with accessibility in mind and designing accessible pages with usability in mind. There are infinite possibilities out there… bake your own and enjoy.

85 Reader Comments

  1. Please do not soil the whole idea of this article by using javascript: links which are dead without javascript turned on!

    Why not point the links to the anchor in the headline of the section and add the javascript functionality onclick and onkeypress?

    Link to headline

    or

    Headline

    you can either add the handlers inline or you can do that with a nice loop like I explained here:
    http://www.evolt.org/cleanmeanjs/ and used for example here:

    http://www.onlinetools.org/articles/tourism/

  2. Aaron,

    The topic of reshaping HTML using DOM has been discussed a few times and it is very tempting to think that by augmenting HTML code with extra features after it is loaded you will be able to coerse certain applications such as accessibility readers into reading the original HTML code that was loaded, not the final version (the one that was modified with JavaScript). Unfortunately, it doesn’t work that way. While it may fool primitive validators such as Bobby, most modern readers will rely on DOM rather than original HTML text to parse the structure of the document.

    What this means is that all of your JavaScript spaghetti will end up being read aloud by JAWS and confusing the poor souls who dared to step onto your page.

    Don’t mean to be a party-pooper, but thanks but no thanks on the spaghetti-cake.

  3. Aaron,

    Are you sure you want to venture into the territory of simulating a common browser behavior?

    When the users click on a link, they typically expect the page to change and view content at the new location. Unless, of course, there is a visual indication (hint) of some sort that the click will reveal a menu or another gadget of that kind.

    What you are doing is creating a “virtual browser” — clicking on tabs does not change the URL, but it does change the state of the page. It really is a cool trick, and I can see how this type of sub-navigational freature can be (and is) used in some places, but creating an illusion of a page change, IMHO, is going a little too far.

    There are several other questions that arise from implementing such a solution (some of them are easy to address):

    * What if I want to see the whole thing and scroll?
    * What if I want to bookmark the “Decoration” part? I can do it with other pages on the World Wide Web, why not here?
    * What if I click the back button while I am in the “Preparation” page? Why don’t I get to the “Ingredients” page?
    * What if I try to open the “Prepartion” link in a new window (shift-click in IE)?

    I am not against creating an illusion, but when everyboday can see right through it, they tend to throw rotten eggs at the magician.

  4. this does not seem like a good idea. As mentioned you are recreating a standard browser functionality. Prior to adding the CSS it was a good example of progressive disclosure and, with some tweaking making the entire text visible as an option, potentially useful.

    I hate to criticize this as I have done little to actually build the soap box I’m preaching from., but I cringed when I got to the CSS example. It was as if I was using frames again. You’re seemingly simulating multiple pages as far as the user would spatially understand but killing niceties such as being able to bookmark a section.

    In a larger scenario a user might want to send a section to a colleague only to end up sending them a link to the parent page; much like the curse of framed content.

    It’s a nice and the DOM is great and all-powerful but the examples in this piece may only lead the uninitiated to copy them verbatim and assume they’re doing something good.

    In short, maybe I’m letting the examples weigh in too heavily in my reading of this but I’m not seeing the benefits you’re touting.

  5. I agree that rewriting the whole page paradigm with some Javascript seems weird. I used my Back button out of habit when I read the examples and I *knew* how it worked. It would be surprising for most readers.

    But this kind of thing might be perfect for a tabbed-container widget within a page. See SAP’s example (click on Application iViews for an example).

  6. In the future when :target is better supported, you won’t even need scripting for this sort of thing. This works in Mozilla now and I’m sure will be in Opera soon enough:
    div {
    display: none;
    }
    div:target {
    display: none;
    }

  7. Chris,

    I understand your suggesting against using javascript: in links. However, I think you are missing an important point of the article: The original HTML uses anchors and Javascript is used to rewrite the links.

    If users have javascript turned off, then the script that rewrites the links is never run, so all the links use anchors.

  8. Chris,
    Did you even look at the example with javascript off? It functions very nicely.

    One of the greatest benefits of this technique is the ability to break up long sections of information, removing the need to scroll (which many clients of mine have expressed distaste for), while still allowing for a complete printout.

    As far as Mike’s comment about the inability to send section link’s to collegues. Perhaps the script could be extended to show the div referenced in the query string. This would allow the sections to be bookmarked as well as emailed.

  9. I love ALA, really I do. I find their articles informative and interesting. I think, however, that an astoundingly overwhelming percentage of their articles use a sort of “spice” metaphor for discussing CSS, JavaScript, et al.

    “sprinkle in a little CSS”, “add a pinch of javascript”, “just a dash of XSLT”, et cetera, ad nauseum. these colorful, yet contextually prosaic phrases will be all to familiar to longtime ALA readers.

    I am no english teacher; god knows I suffer with my own fair share of writing and communication deficiencies. as such, I mean this comment not as a vitriolic barb, but rather a simple plea for understanding. I am sure JavaScript, CSS, DOM, XSLT, and other web tech acronyms can be personified in a bracing new manner, and I have little doubt that the brilliant minds behind this website could bring such theorized syllogisms to life.

    thank you for your time, and for the wonderful information you guys disseminate. wordup.

    -fish

  10. I’ll be probably be labeled a troll for this but oh well…
    First of of all I didn’t like:
    if ((divs[i].id!=”header”) && (divs[i].id!=”footer”)) }
    divs[i].style.display=”none”;
    Isn’t
    if (divs[i].id!=”header” && divs[i].id!=”footer”) divs[i].style.display=”none”;
    easier?
    Even easier would be
    if (divs[i].id==”header” || divs[i].id==”footer”) continue;
    divs[i].style.display=”none”;
    It is my suspicion that ALA is publishing all these new (sometimes great) DOM articles after PPK said that the average Javascript article on ALA was “mediocre at best”.
    I’d recommend http://www.digital-web.com/columns/keepitsimple/accessibility_and_usability.shtml for accessibility and usability. This was good as well. Overall very good.

  11. The first code example should have read
    if ((divs[i].id!=”header”) && (divs[i].id!=”footer”)) {
    divs[i].style.display=”none”;
    }
    “Javascript Spaghetti”? Why isn’t Javascript being taken seriously? I think I just stop trying. No one can see beyond inaccessibility to a practical use of Javascript.

  12. Ok, I missed the point at first but then I was even more astounded to see that you are actually using Javascript to write out Javascript links! Why do that when you can apply an event handler instead? These will also prevent users from thinking that these really are links, provided they do look at their status bar.

  13. Despite what people are saying, I like it.

    I do think, however, that you should use a Tab Type navigation when styling the list. the navigation you use looks too much links to new pages, confusing users. But tabs would give a better effect, and look more like you are viewing a different section of a current page.

  14. I’m of two minds on the subject — on the one hand, I think the technique has merit, on the other, breaking the back button and other browserly-expected-functions (as delineated by Dimitri Glazkov on p.1) seems to make dubious the claim that this enhances “usability.”

    I think it’s key to note that this method really can only apply to lengthy documents like this article … beyond that the issues definitely outweight the merits.

    I also have to note that I got a giggle out of your JS function:

    hideDivs(“intro”);

    What does that look like it should do? Hide the “intro” div or hide everything BUT the “intro” div?

  15. A user would expect the back button to do that. The hideDivs function looks like it should hive all intro divs, but in my opinion ids are unique. They must be used only once on a whole page.

  16. I’m going to rewrite this script so that:
    1. It will include a “Back” and “Forward” functionality.
    2. It will use no inline event handlers.
    3. The names of functions will not be misleading

  17. Yes, it is a cool trick, and works, but how does the user know that when he hits print, the entire content will print? I would expect as a user only the currently selected section to print. This means you have to have additional information given to the user to explain how to use the page. Hardly good usability technique.

    I use a similar technique for an image gallery, but that is as far as I would take it. This just confuses the end user, imo.

  18. I did a rewrite of this script from scratch. Take a look at http://www.geocities.com/seanmhall2003/SeanSoft/cake.html
    It has a “Back” functionality and you can also use URL queries (like http://www.geocities.com/seanmhall2003/SeanSoft/cake.html?tab=ing will take you the the same page but the “Ingredients” div will be shown).
    It only works perfectly in IE6 (can’t test Safari). The back button always goes to the “Serving” div in Opera, and Mozilla has trouble with the URL query part.
    Is switchDiv a more appropriate name for the main function?
    The only thing I didn’t do was add a printsheet. I was focusing more on the Javascript/DOM part.

  19. The original article has one big advantage, try to search for word ‘Sprinkle’ regardless what page you are looking for, browser will find it. Not try with the alternative approach go to any other section but the first one and search for ‘Sprinkle’. browser will not find it since it is in the hidden section. 🙂 Seems like breaking something which worked just fine.

  20. It took me a few hours to follow through this tutorial – i’m not much of a javascript expert – but i found it very well written and informative. Thank you for taking the time out to write and share this with the CSS3 community.

  21. I guess the idea gets obscured by the execution of the example.

    I really dislike javascript or ECMA-script or what the lastest correct label might be, because its application often reduces the usability for me as a user, unless I would buy a windows box and stick with IE6. Too many webmasters haven’t got a clue what they are doing when applying it.

    But the example of the rewrites of the links using javascript is brilliant: for me its the first glimpse under the hood of DOM that implicates its real power. If javascript is of, you are still having a valid functioning document!

    The example of application though isn’t exactly wonderful. If ALA would structure all its tutorials this way, I never would read it again.
    Maybe I’m the odd fellow, but I like to be able to scroll back and forth on the same page when reading a tutorial, I dislike having to “tab” through it.

    I guess that with a little more ado you could give your user the option to get 5 slices or a whole cake when served, so thank you for showing us the receipe of baking cake.

  22. This script assumes there will be no external links with a # in them.

    Eg: an anchor with a href of “http://alistapart.com/#footer”
    becomes
    “javascript:show(‘footer’);”

  23. It’ a nice implementation but there is already a method for chunking content: it’s called a “page”.

  24. I usually find chunked tutorials annoying for the following reasons:

    1. The tutorial cannot be saved in one go, each page must be separately saved (admittedly this technique does not suffer this problem).

    2. If I want to come back to a specific piece of information in the tutorial I have to repetitively open each page to be able to scan or find text in it.

    3. I read a webpage by scrolling with the keyboard down arrow. Yet to continue on to the next page I have to break my flow by picking up the mouse and moving the cursor to the “next page” button, which sometimes is a tiny little number (ALA I’m looking at you!). In the example of this tutorial I even had to scroll back to the top of the page before I could find the link to the next “page”.

    The link in the article about chunking states:
    “The main purpose of chunking is to enhance learning by breaking tasks into small, easy-to-manage pieces.”

    I believe sub-headings do just that, and would advocate using them instead of page splits for the above reasons. But as each user is different, maybe we should be giving them a choice?

  25. Simon, as stated I did realise my error later.
    But it does not change the fact, that it is misleading and superfluous to write out javascript: links when you can assign an event handler IN javascript instead.
    I don’t see a point to change the href when a return false does the same and cleaner.

    as[i].onclick=function(){show(this);return false}

    As explained here: http://www.evolt.org/cleanmeanjs/

  26. I’m on the side of Mister ‘guy’ (cf. supra), who wrote :

    >> It’ a nice implementation but there is already
    >> a method for chunking content: it’s called a “page”.

    How right !

    Okay this script is 200% nice. But some books I have at home are huge 600-page books, and still, they come in one volume.
    You can imagine splitting info in chunks is sometimes an obligation for physical structures. But a HTML page can be as long as you want.

    Plus, I guess the article gives the wrong example : it splits one article into many tabs. Information coherence asks for the same article to be placed one just one single page, so it can be viewed as a whole.
    Remember that the forst thing your eyes does when you read something on the Web is looking at the side of the browser’s scrollbar !

    This article would have been more logical if it had been splitting not an article but a book or a series of articles (episode 1, 2, 3, and so on).
    Long stroy short, this article technical aspects are great (I’m so useless at Javascript I quite doubled my knowledge.js on this one). But that’s all in my own opinion. Follow the wheel — use pages !

  27. I’d have to agree with Francois. The reason why this article is getting so much critism is because it gives a bad example of it’s use.

    And i think that people should understand that taken in a different context, this is actually a very good article.

  28. This is really good article, but the final presentation is wrong and as it has been said it doesn’t work with JS disabled.

    Otherwise this is great idea, since it worked without the final change. It could be used on page in some smaller box or so.

    Also be sure to check:
    http://www.absolutengine.com

    It uses WYSIWYG editor to create valid XHTML Strict!

  29. I’m part of the CSS3 community as well. No one else found it funny that Aaron used the text-shadow property when no browser supports it yet? For up-to-date CSS3 support info, see my CSS3 Tests site: http://geocities.com/seanmhall2003/css3/ (I may be wrong, Safari 1.2 might support it, can’t test).

    Javascript is an extremely powerful and useful language to use, supported by Netscape 2+, ideal for adding usability. If you are too foolish to see the advantages of Javascript while focusing on people who have used it irresponsibly in the past, that is your problem. Silly DHTML nonsense is as dead as Disco (though I wish Disco hadn’t died).

  30. Alot of interesting ideas, thanks Aaron. And it works with javascript either on or off in firefox anyway. I like it.

  31. What if you had a way to check what section is shown, so you can add a URL query (like cake.html?section=info). My script allows you to come to the cake at a certain section, but it doesn’t solve the bookmark problem.

  32. For everyone griping about how a “page” is the chunk – what are paragraphs then? – all you need is a “show all” link.

    They way I’ve done the same is to take all headers on a page and restyle them into tabs (a link bar looks like site sections) at the top along with a “show all” link. The method above takes care of bookmarks. Event handlers do the rest.

    Voila: no need for scrolling and an effective method for immediately seeing what’s on a page – useability! – and choosing the sections you want to read (particularly good for discrete sections such as reviews, or model info). Not always the best method, but a great one sometimes.

    Dante: your page doesn’t work in my Firefox.
    Error: missing variable name
    var goto = text.substring(location.href.indexOf(“=”)+1,location.length);

  33. ‘No one else found it funny that Aaron used the text-shadow property when no browser supports it yet?’

    Heh 🙂 But you were right about Safari; it does support text-shadow from 1.1.

  34. One of the better articles I’ve read in a while, an interesting idea with loads of potential 🙂

    (btw: a.href should be a.getAttribute(‘href’))

  35. I know it doesn’t work in Firefox. Only IE 6 gets it right. I could get it to work in Firefox, but then you couldn’t enter at a specific section (like ?section=bake).

  36. I was wondering if there was any easy modification that could be done to the script to make it just toggle the div clicked on from display:none to display block back and forth instead of just showing the one clicked on and collapsing all others? Sorry my scriping is horrible.

    I’m making a program that will ideally generate a html list of the files on a person’s hard drive in a directory tree. when you click on a node of the tree, it will reveal the files in that node and their file information in a table. If you click on a child node with this kind of script, it will collapse the parent div when hidedivs is called.

    All of the other scripts i’ve been able to find for toggling don’t include a function to collapse all nodes on page load, so i was trying to use this one for cross platform compatability without having to put inline display:”none” everywehre.

  37. Everything seems to be very smart but pressing the back button to get back to the previos section (Introduction, Ingredients…) you “jump” back to ALA site.
    The document behaves in an unexpected way, this could create confusion and disapoint among users (the same it happes with Flash sites)

  38. Speaking of usability and accessibility, wouldn’t a good practice be titling one’s articles with something a bit more descriptive than “Let Them Eat Cake,” especially when said article titles appear in syndicated RSS feeds?

  39. Earlier in the discussion, Dante-Cubed introduced a link to his DOM-based AccessKeys method, as a better example of adding accessibility and usability. Is this to suggest that AccessKeys isnt as useless for accessibility as I’d beleived until now for the reasons decribed at http://www.wats.ca/articles/accesskeys/19 ? “So while it seems that Accesskeys is a great idea in principle, implementation brings with it the possibility that it either will not be available to all users, or that the keystroke combination encoded within the web page may conflict with a reserved keystroke combination in an adaptive technology or future user agent.”

  40. in one hand i agree the arguments about ’emulating a browser is bad’….and that this trick is only good for cool visual affects like collapsing the content of a long article…

    But with all the arguments about ‘if my browser doesn’t support javascript’ all i can say is …. GIVE ME A BREAK!!!!!

    come on, trash your PREHISTORICAL browser and Download a brand new SHINY one.

    Who can be creative without considering the best tools available …. and i’m not talking about ‘HIGH END GEEK TOOL’…i’m talking about THE WELL KNOW JAVASCRIPT…

    a good article … with a bad example… but tools exists just to serve your imagination… if you don’t have imagination…STOP READING THIS BLOG….no?

  41. Hello all,

    I am really amazed and thrilled at the amount of discussion this article has generated. And I am please with all of the comments (even the ones which paint me as out of my mind — perhaps because I’m nearly there). Anyway, just some quick thoughts, responses and background.

    First off, this article is less about the tabbed viewing (in retrospect, perhaps a poor example, but one I figured everyone could easily grasp) and more about the power of using JavaScript only when you know it will be supported. Some people got this right off the bat, others… not so much, but anyway, that was the concept. It was meant to get you thinking, which many of you have.

    Dante-cubed has come back to this again and again with some great ideas, as has Eric L. I really like the idea of implementing a “show all” as stylo suggested. But Vinnie Garcia is right in looking forward toward CSS3 support. Once this is supported, using the :target selector, there would be no need for the inline JS Sam suggested and Eric L implemented. But, being that full CSS3 support is a long way off (at least in the Windows world as IE will now be inextricably tied to the OS), I would recommend taking Sam’s suggestion, but wrapping it in a function which would write out the onclick behavior on the fly (and only if javascript is enabled).

    Anyone who has problems with my JS can feel free to gripe all they want, I am certainly no master. Keep in mind, however that these examples were meant to be readable by everyone (even my wife, who has no clue what I do). Think of it as code on a 4th grade reading level — the USA Today of the JavaScript world. I think using behaviors assigned by JS is great, but wanted this to be very easy to follow.

    As for those of you who found the errant CSS3 text-shadow, that was a wink to the Safari community (which I am not a member of, being PC-based). I realized support for it wasn’t good, but threw it in as a dream (of sorts) that some day browsers would be up on their CSS support.

    Thank you all for reading and keep adding to the discussion. I am really glad you all have taken the time to add your input to the article. I wish all articles existed in this sort of forum.

    Cheers.

  42. I have set up a compatibility table containing up to date CSS3 compatiblity info, and you’d be suprised.

    CSS3 Tests Site: http://geocities.com/seanmhall2003/css3

    CSS3 Compatibility Table: http://geocities.com/seanmhall2003/css3/compat.html

    Safari 1.2 has excellent CSS3 support, and I thank Aaron for acknowledging that fact.

    Those looking for a back button: My rewritten script has one: http://geocities.com/seanmhall2003/SeanSoft/cake.html

    My cake only works perfectly in in (no suprise) Internet Explorer.

    Everyone yells at Microsoft for tying IE7 to the new OS. Apple does the same thing with Safari and everyone…says nothing…??

  43. I really like where you’re going with this, but I have a few improvements I’d like to share with you. I gave each section an id, and the links of the navigation will change the style of that particular section. In addition, I’ve modified the onload of the document in case such a hash has been made–you can check it out here http://www.ilstu.edu/~jcpeter/eatcake.html

    Forgive the ugliness of the page, but it’s really just a technical demo anyhow.

  44. It’s ok. I mean, the only thing that bugged me was

    This does not seperate behaviour and structure. In the JS file place this at the end:
    window.onload = init;
    Also instead of
    return false
    for the support detect, you can just do
    return;
    The latter is probably safer.

  45. The idea of having all information on a single document and then simulating paged content i.e. only showing parts of the document naturally arise an accessibility question from my part. Imo “accessibility” also covers load time (at least for people on slow connections), and if your document spans over endless paragraphs of text and perhaps a few images you user will be very confused when the page finally loads revealing 4 lines of text.

  46. Right on Anders. I just read through all the comments and was about to say something similar.

    I also agree with the sentiments of a page being a page; this example attempts to simulate the paradigm of multiple pages within what is in fact a single page.

    For me, KISS (keep it simple stupid) still reigns supreme.

  47. I agree with Anders and James. I’ve used this technique before, and it works well, though as noted it’s a good idea to put real links in the href and add the javascript to an onClick or something.

    The problem is that this method doesn’t scale well. Not only is page load time significantly impacted, but what happens when your content changes and you have to add sub-categories. Then you have to start setting cookies or something to track sub-states, and things start going south quickly.

    It’s just not a good idea, as it adds a level of complexity that really isn’t necessary. My 2 cents.

  48. This technique does not improve usability. These two articles explains why:

    J. Ryan Baker (2003) – “… participants using the paging condition took significantly longer to read the passages than either the full or scrolling conditions”:
    (2003)http://psychology.wichita.edu/surl/usabilitynews/51/paging_scrolling.htm

    Jakob Nielsen (1997) – “Scrolling Now Allowed”:
    http://www.useit.com/alertbox/9712a.html

  49. This point is not so much related to the general concept of the article but to the tendency for the centered fixed page to jump/reposition itself when it increases in length and needs to be scrolled – I find this an unattractive feature of the site. The ALA pages are always longer than the browser so this does not happen.(IE has scroll bars permanently positioned).

    Is there a simple script to enforce scroll bars in Mozilla even when they are not needed so that when they are needed the page does not jump?

    I love ALA but am a beginner!

  50. I’ve never found a good way to do that in javascript (i thought I had to tie onload to the document object, which never worked for me). I totally agree with you that the more seperation you can get, the better. Anything that minimizes the risk of not being able to use the page is good in my book.

  51. Although I agree with many of you concerning this article’s usefullness and usability in that it may be a stumbling block to some, there are occasions where this approach comes in very handy. I, for one, use almost an identical script to toggle the answers to a list of questions on a FAQ page. It is ideal for a task such as a FAQ page where there is no need to view all at once, and such a page can grow to great lengths. There is also little need for bookmarking of specific sections, or even the need for a back button. However, as a catch-all, at the bottom I do include a tiny section to email the webmaster on any compatibility problems thus ensuring that one always has a way of getting the information they need. *g*

  52. An excellent article on DOM and JavaScript, but not so good for accessibility. As was pointed out earlier, modern tools like JAWS won’t handle a page like this properly. The first rule of achieving true accessibility: keep it simple. (That doesn’t mean keep it DUMB.)

    I do think this code snippet would be excellent, however, for publishing. I used to post multi-page articles all the time, to minimize scrolling, but the process of rewriting one long page when I was done into several smaller pages took a lot of time and led to clumsy mistakes. A script such as this would allow me to post as long a page as I want, and have it automatically be broken up into chunks (I’d still have to add the div’s, but that’s easy.) Fortunately, my articles are never so long that download time would be an issue, although one should bear that in mind as a disadvantage to this approach if you are serving to a broader user base that isn’t necessary broadband-saavy. Two improvements I would make: first, a “Next” link at the bottom of the page to go to the next div without having to go back to the top (too much eye scanning), and maybe “Prev” button to replace the lost “Back” functionality. Second, a link to “Show All” that would display the entire page at once, for those who LIKE to scroll, or want to use full-page text search.

    What I found most interesting in this article, though, was what you didn’t discuss and what other people have been wondering about. I, too, wondered why you didn’t use onClick handlers instead of rewriting the links with fixLinks(), until I tried it, and realized that the Back button failed to redraw the correct div (even with an onLoad handler, it fails in Mozilla). I also wondered why you were rewriting the div’s to use the .hidden class, when you could have just had a class defined for every div, but separate definitions for screen/print media. Then I realized that order of precedence broke that idea, too.

    These would have been excellent additions to the article. Many times, knowing why a more “obvious” solution doesn’t work is just as instructive, if not more so, than the solution that does. But thankfully, that’s why we have the discussion board on ALA — looking past the flamage, most of this was discussed here. Even my suggested improvements. Gotta love it.

  53. I found a seemingly perfect script for what I wanted in this thread http://forums.devshed.com/t77556/s.html

    The opening script tag is malformed, but the rest of the script works perfect in every browser i’ve tried it in and it leaves the content accessable to people who do not have javascript enabled / working properly. I had to remove one line from the script (the //contractcontent(cid) line in the expandcontent section) but otherwise it works out of the box.

    Thanks for the sample reply. I will study it for future reference.

  54. You make it look like the information is devided into multiple pages. A search engine bot will see it as one page and may take some sentences of the content on their search results page. The visitor will get frustrated when the shown part is not found immediatly at the devided page..

  55. There’s a significant issue with taking this approach for people with JavaScript: as the page loads all the content is displayed, and when it finally loads content disappears! Where’s it gone? What’s happened? I didn’t do anything to ask the content to disappear?

    This is a severe usability issue, especially for those using pages over slower connections (as I am now).

    Gabe

  56. i’ve used this with a tabbed list and replaced divs with fieldsets. this is within a CMS interface where theres no need to bookmark or print the sections. being able to break up forms makes a huge difference as these can often be overwhelmingly long.

  57. i’ve implemented the technique in this article on gmail, something of a proof of concept for the article’s example. readers have commented that the page is “much much better and easier to read than most online articles.” so i think this sort of tabbed navigation (especially given the fact that it is also usable without javascript) is very usable.

    the article:
    http://vault.silversand.org/pages/gmail_beta.php

  58. On browsing through this article I got the impression that it would eliminate scrolling. On viewing the finished thing I still had to scroll to read all the text (1280 x 1024 res). So I don’t quite get the point of the script – brilliant as it may be.

    There’s nothing wrong with scrolling, as long as you are either interested in the article or know what you are scrolling too. It’s certainly far better than clicking ‘next’ buttons all the time. I sometimes get the impression that breaking text into chunks has ultimately only one purpose – pushing more adverts at you!

  59. Regarding cocerns for users with slow access, when I use dial-up, I opening several pages in various windows so I can be loading one while reading another. This technique does this automatically.

    Unlimited local calling is relatively rare outside the US so slow speed users are usually concerned about the total time online. I love this technique for it’s potential for entire sites to be viewed offline easily.

    But the designer would have to find a way to let users know that the entire site is loaded and can be viewed offline.

  60. I know I’m coming in three months late here, but if anyone’s still tracking the thread, I wonder that no one has noted (and provided the, perhaps, super clever solution which escapes me still) the quick flash-of-text you get in many browsers when deploying this technique.

    Sure, it’s just all the IEs and definitely a by-product of bandwidth, but it happens even to a relatively meager 20K glossary (for instance). The javascript can’t go to work until the document loads, which means that the body of the text flashes quickly before your eyes before it’s mostly rewritten to “display: none”.

    This flash is esthetically unacceptable. The “obvious” solution (set to “display: none” in CSS and wait for the javascript to display the first element, or whatever) is also unacceptable as anyone with CSS capabilities and disabled javascript won’t see a thing.

    Am I missing something or is there a workaround for that?

    — H

  61. In response to Heidi’s question, as this script relies on an onload event, that is why you see the flash. The only solution I can think of off-hand would be hiding the whole page until the whole thing is loaded and revealing it all in the onload event. To make this work with JS on or off, I would write some JS in the head which wraps an if document.getElementById() around a document.write JS line which writes a css rule stating “body {display: none}” or something similar to hide the page. You could then add a JS function to the onload event to undo this.

    Again, this is purely hypothetical, I have not tried it out for sure, but in theory it should work.

Got something to say?

We have turned off comments, but you can see what folks had to say before we did so.

More from ALA