How to prevent jQuery onload flicker unobtrusively?
Asked Answered
D

5

6

I'm using jQuery UI Tabs. How should I prevent the flicker of loading content while also making sure that the content is visible when javascript is disabled?

I've tried adding a .js class to the body when the doc is loaded but as the tabs are loaded at the same time as the class being added there is still the flicker of content.

#container{display:none;}

<div id="container">
  <div id="tabs">
    <ul>
      <li><a href="#tabs-1">Nunc tincidunt</a></li>
      <li><a href="#tabs-2">Proin dolor</a></li>
    </ul>
    <div id="tabs-1">
       <p>Tab 1</p>
    </div>
    <div id="tabs-2">
      <p>Tab 2</p>
    </div>
  </div>
</div>
<script>
$(document).ready(function(){
  $('#tabs').tabs();
  $('#container').show();
});
</script>
Diamagnet answered 1/6, 2012 at 13:0 Comment(0)
C
5

this is what I do. put a class of no-js on your html tag and then put the following code just after the html tag:

<script>
    // Sets 'js' on html element and removes 'no-js' if present (here to prevent flashing)
    (function(){
        document.documentElement.className = document.documentElement.className.replace(/(^|\s)no-js(\s|$)/, '$1$2') + (' js '); 
    })();
</script>

This method allows you to have other classes on your html tag if required. Use the no-js class in your styles for pages that don't have js enabled.

styles example:

#container {
  display:none;
}
.no-js #container
{ 
  display: block;
}
Cristen answered 1/6, 2012 at 13:7 Comment(3)
inside head or between html and head?Darill
as long as its before the container div it doesn't matter. But I would put it just after the html tag (between html and head)Cristen
Thanks everyone for your answers. This works great and also allows for other classes in the html tag should they be required.Diamagnet
R
5
<html class="nojs">
  ...
  <head>
     <script>
       document.documentElement.className = "js";
     </script>
  </head>

  ...
  <style>
  #container {display:none;}
  .nojs #container { display: block;}
  </style>

this will make your content visible even when js is not available on your device. This approach is almost the same performed by H5BP + Modernizr and, as aside benefit, it will prevent the JS FOUC (flash of unstyled content due to js later execution).

Reconstructionism answered 1/6, 2012 at 13:2 Comment(7)
I didn't know that. I'm gonna try it now :)Darill
+1 Ensure that you embed it, rather than linking it as the external resource will again end up causing the FOUC.Bouffant
is <script> = <script type='text/javascript'>?Darill
type='text/javascript' is not necessary. See my answer below for a more robust solution.Cristen
type is not necessary, in all modern browser can be omittedReconstructionism
@DaveHaigh in what your solution is more robust? It seems really identical to this solution I wrote... or am I missing something?Reconstructionism
as explained in my answer - you can have other classes on the html tag and they won't be overwritten by your js class.Cristen
C
5

this is what I do. put a class of no-js on your html tag and then put the following code just after the html tag:

<script>
    // Sets 'js' on html element and removes 'no-js' if present (here to prevent flashing)
    (function(){
        document.documentElement.className = document.documentElement.className.replace(/(^|\s)no-js(\s|$)/, '$1$2') + (' js '); 
    })();
</script>

This method allows you to have other classes on your html tag if required. Use the no-js class in your styles for pages that don't have js enabled.

styles example:

#container {
  display:none;
}
.no-js #container
{ 
  display: block;
}
Cristen answered 1/6, 2012 at 13:7 Comment(3)
inside head or between html and head?Darill
as long as its before the container div it doesn't matter. But I would put it just after the html tag (between html and head)Cristen
Thanks everyone for your answers. This works great and also allows for other classes in the html tag should they be required.Diamagnet
A
2

You can do it like this:

<div id="container">
  <div id="tabs">
  <script>$('#tabs').addClass('js');</script><!-- added this line -->
    <ul>
      <li><a href="#tabs-1">Nunc tincidunt</a></li>
      <li><a href="#tabs-2">Proin dolor</a></li>
    </ul>
    <div id="tabs-1">
       <p>Tab 1</p>
    </div>
    <div id="tabs-2">
      <p>Tab 2</p>
    </div>
  </div>
</div>
<script>
$(document).ready(function(){
  $('#tabs').tabs().show(); // changed this line
  $('#container').show();
});
</script>
Albie answered 1/6, 2012 at 13:3 Comment(0)
F
1

Thanks for above ideas to solve the on load flicker. As browsers try to render markup as soon as possible, this should be avoided for some (huge) jquery-ui content elements as jquery-ui Tabs.

This solution works for me:

<html>
...
  <head>
  ...
    <script>
      $(document).ready(function() {
        $("#tabs_container").tabs();

        // force *initialized* #tab_container to be displayed
        $("#tabs_container").show();
      });
    </script>
  </head>
  ...

  <body>
    ...
    <!-- avoid unstyled tabs to be displayed using "display: none" at markup -->
    <div id="tabs_container" style="display: none;">
      <!-- (huge) tabs content -->
    </div>
    ...
  </body>
</html>
Fluviomarine answered 23/9, 2015 at 8:3 Comment(0)
C
0

You could try it this way:

<script>
$("#container").hide();
$(document).ready(function(){
  $('#tabs').tabs();
  $('#container').show();
});
</script>

The container is hidden as it is loaded and when the document is ready and tabs are done, you can show the container.

Chroma answered 1/6, 2012 at 13:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.