Hide And Seek in The Head

12 Comments

Comments are ordered by helpfulness, as indicated by you. Help us pick out the gems and discourage asshattery by voting on notable comments.

Got something to add? You can leave a comment below.

  1. kentaromiura

    in alternative you can use a function like this one:
    http://webreflection.blogspot.com/2006/11/my-domcontentloaded-final-solution.html
    or this one:
    http://dean.edwards.name/weblog/2006/06/again/

    to change the dom before the onload but after the dom is totally loaded and parsed.

    your solution works well for little change,
    but for more than a simple hide and seek using a “behaviour function” is preferible
    for a “behaviour function” I mean a function where you have all the changes(hide and seek) and the hijack (onclick..) to the dom.
    Cheers

  2. Jake Archibald

    I’m probably being really dim… but why shouldn’t the noscript element be used in this situation?

    Wouldn’t you get the same result by just wrapping your submit button in a noscript tag? You wouldn’t have the problems with dom content loading etc.

    Jake.

  3. David Singleton

    There’s still a slight problem with the two methods mentioned above, they’re still going to fire once the DOM is loaded. If the page contains a large amount of content, or the user is on a slow connection than you can still have that flicker of non-js content while the page itself is loading (not external resources).

    That is a relatively niche case, but it means the method in this article is a little more robust. It’s the way I’ve been using this to handle the hiding/altering of elements for Javascript enabled browsers, although I’ve found it easier to use document.write to create a link to another specific CSS file, which keeps things a bit tidier.

  4. Isofarro

    noscript is rendered when JavaScript is not disabled. It doesn’t render when JavaScript is available. So it becomes a problem when JavaScript realises that the browser does not support the necessary objects/methods to actually run the application we’ve built. So its a case of “browser not good enough” – in these cases the noscript is not rendered, so a graceful degradation is not possible if critical markup that’s needed is inside the noscript element.

    A common occurrance of this case is a browser with JavaScript enabled, that uses a third party firewall to remove suspicious javascript. The browser doesn’t know JavaScript has been stripped out – so it won’t render the noscript.

  5. Ben Darlow

    These techniques touch on something I’ve been recently puzzling over; script.aculo.us effects require that elements which are hidden/shown using so-called ‘combination effects’ that are supposed to be initially hidden cannot be hidden using a stylesheet but instead only through inline styles (I’m not sure what the exact technical reasons for this are, but sure enough if you use a stylesheet to hide them, they’ll never be shown via scriptaculous). My solution was to add an onLoad event method which manually hid all qualifying elements. The problem there is, as you say; the equivalent of a FOUC – the elements are there as the page loads, but disappear as soon as loading finishes. Really they should be hidden immediately.

    Perhaps there’s something in your tips above that might work here…

  6. Nate K

    I would agree with what you (and others) have said here. I would avoid using document.write and create the element with the DOM, and I would avoid explicitly setting the styles in the JS file. Have classes setup accordingly for the situations and then reference the element.className.

    Of course, this isnt NECESSARY, it just my anal attention to the small details.

  7. Drew McLellan

    Nate – that only works once the DOM is loaded. The problem PPK is addressing here is specifically how to prevent unwanted items displaying before the DOM is fully available.

  8. Kabari Hendrick

    I think some of you missed the finer points of this article. Look at Problem: the load event carefully. The difference is that you are not waiting to check if the @Window@ has loaded before you fire your script. Using @document.write@ will print your simple CSS immediately to the page, thus hiding your elements whereas using any javascript functions like @getElementsByID@ etc. will not fire until the html content of the html on the page is already loaded, even if you use them in the same way. It’s as simple as this, @document.write@ doesn’t need any html to work, alll the other functions can’t work until the html exists.

  9. Jesse Skinner

    To have different stylesheets for people with and without JavaScript, I like to use a single link tag pointing to a CSS file, then dynamically change the href to point at the JavaScript-only CSS file that simply imports the original CSS file and adds a few extra things.

    To see a longer explanation with an example, check out No-JavaScript CSS

  10. Hikari

    Great tip and great comments!

    I believe ppl are afraid of document.write() because in the past it was used to <b>add HTML on the fly</b>.

    That’s the problem. What we must focus is that HTML must be loaded in the document always when possible, and have only the content; CSS must have the presentation and JavaScript the behavior.

    But our intelligence is above those rules. The best dropdown menus are built only with CSS, although that’s behavior.

    Saying that document.write() is bad, is the same as saying that weapons are bad. Weapons don’t kill ppl, ppl that uses weapons kill ppl.

    &amp;

    My suggestion is to add to HTML all noscript and scripted elements, and set on normal CSS (or split it, if it gets too large, anyway) the styles for all of them.

    Then, for noscript elements, add some class like <b>prefix-js-hide<b> – in the HTML, which will NEVER be referenced in CSS -, and for scripted elements add something like <b>prefix-js-show</b> – which will be set on CSS as <code>prefix-js-show{display:none;}</code>.

    And finally, in our marvelous js file, just in the beginning and outside any function, we test if the browser works as intended and if so (inside the if clause), we attach the startup function to body load and document.write():

    <code><style>
    .prefix-js-hide{display:none; !important}
    .prefix-js-show{display:block; !important}
    </style></code>

    Maybe add a third class for inline elements that should be shown. But the important thing is that this is the smallest style code that should be added by JavaScript, and everything else will be dealt by the normal CSS file. Clean and functional.

Impress us

Be friendly / use Textile