Hide And Seek in The Head

If you want your JavaScript-enhanced pages to remain accessible and understandable to scripted and noscript users alike, you have to think before you code. Which functionalities are required (ie. should work without JavaScript)? Which ones are merely nice-to-have (ie. can be scripted)? You should only start creating the site when you’ve taken these decisions.

Special HTML elements

Once you have a clear idea of what will work with and without JavaScript, you’ll likely find that you need a few HTML elements for the noscript version only.

Take this example: A form has a nifty bit of Ajax that automatically and silently sends a request once the user enters something in a form field. However, in order to preserve accessibility, the user should also be able to submit the form normally. So the form should have a submit button in noscript browsers, but not when the browser supports sufficient JavaScript.

Since the button is meant for noscript browsers, it must be hard-coded in the HTML:

<input type="submit" value="Submit form" id="noScriptButton" />

When JavaScript is supported, it should be removed:

var checkJS = [check JavaScript support];
window.onload = function () {
	if (!checkJS) return;
	document.getElementById('noScriptButton').style.display = 'none';
}

Problem: the load event

Although this will likely work fine in your testing environment, it’s not completely correct. What if a user with a modern, JavaScript-capable browser visits your page, but has to wait for a huge graphic to load? The load event fires only after all assets, including images, have been loaded. So this user will first see a submit button, but then all of a sudden it’s removed. That’s potentially confusing.

Fortunately there’s a simple solution: play a bit of hide and seek in the <head>:

var checkJS = [check JavaScript support];
if (checkJS) {
	document.write('<style>#noScriptButton{display: none}</style>');
}

First, check if the browser supports enough JavaScript. If it does, document.write an extra <style> element that hides the button.

The difference with the previous technique is that the document.write command is outside any function, and is therefore executed while the JavaScript is being parsed. Thus, the #noScriptButton{display: none} rule is written into the document before the actual HTML is received.

That’s exactly what we want. If the rule is already present at the moment the HTML for the submit button is received and parsed, the button is hidden immediately. Even if the user (and the load event) have to wait for a huge image, the button is already hidden, and both scripted and noscript users see the interface they need, without any potentially confusing flashes of useless content.

In general, if you want to hide content that’s not relevant to scripted users, give the hide command in CSS, and make sure it’s given before the HTML element is loaded and parsed.

Alternative

Some people won’t like to use document.write. They could also add an empty <link /> element to the <head> and give it an href attribute once the browser’s JavaScript capabilities have been evaluated. The <link /> element is made to refer to a style sheet that contains the crucial #noScriptButton{display: none}, and everything works fine.

Important note: The script needs access to the <link />, and the only way to ensure that access is to include the empty <link /> element before your <script> tag.

About the author

Peter-Paul Koch (ppk for those In The Know) is a JavaScript guru residing in Amsterdam, the Netherlands. His cunning masterplan to get filthy rich consists of pimping his book, ppk on JavaScript, without which it’s impossible to lead a succesful, or even happy, life.

More articles by Peter-Paul

Comments