I’ve tried my best to be a purist with my usage of Javascript/Ajax techniques, ensuring that all Ajax-y behavior is an enhancement of base functionality, while the site is also fully functional when Javascript is disabled. However, this causes some problems.
In some cases, a DOM node should only be visible when Javascript is enabled in the browser. In other cases, it should only be visible when disabled. Take for instance a submit button on a form that has a drop down with an onchange handler that auto-submits (using JQuery’s form plugin):
<form method='post' action='.'> <label for='id_state'>State:</label> <select name='state' id='id_state' onchange='$(this.form).ajaxSubmit(ajax_submit_handler);'> <option value='AL'>Alabama</option> <option value='AK'>Alaska</option> </select> <input class='with_js_disabled' type='submit' value='OK' /> </form>
and the Javascript:
<script type='text/javascript'> $(document).ready(function() { $('.with_js_disabled').hide(); }); </script>
When Javascript is enabled, the submit button is not required (due to the onchange handler). However, JQuery’s $(document).ready function (and the more direct document.onload) is only called after the page has been fully loaded and rendered – hence, the submit button is initially displayed and a ‘flash’ occurs when the Javascript is executed and the node’s display is set to ‘none’.
I’ve accepted this as the cost of doing business, and haven’t found a way around it. But is there a technique I’m not aware of that will minimize the effect, or even outright eliminate it?
EDIT:
The <noscript> solution mentioned by many people below seems promising, but isn’t working for me on Safari. However Prestaul’s 2nd suggestion works beautifully:
<body> <script type='text/javascript'> document.body.className += ' has_js'; </script> <!-- the rest of your page --> </body>
This can then be styled using straight CSS:
body .js_enabled_only { display: none; } body .js_disabled_only { display: block; } body.has_js .js_enabled_only { display: block; } body.has_js .js_disabled_only { display: none; }
This second line is just for reference and can (and should) be removed to avoid circumstances where your element shouldn’t be display:block. Likewise, you may need different variations on the third line for other display styles. But this solution is nice and clean, IMO, and in my tests entirely eliminates the flicker effect.
How about combining some of these solutions:
or I prefer adding a class to the body (place your
<script>tag at the top of the body and don’t use the .ready event):