Jump to content

[SOLVED] flash of unstyled content


AmandaF

Recommended Posts

I'm having a problem with some js code on a site.  The site's menu is an unordered list, and some list items contain nested lists (submenus) which are supposed to be hidden from the user unless the user mouses over them (or tabs onto them from the keyboard).  The css class that hides the submenus is applied to them within the js when the page loads, rather than hard-coding the class name into the html itself, because I want the submenus to be accessible to users who have css enabled and javascript disabled.  (these users will see the menu fully expanded.)

 

Problem is, the expanded list flashes briefly when the page first loads, before the javascript kicks in.  I tried brothercake's solution (http://www.brothercake.com/site/resources/scripts/domready/) but it didn't help.  (I also tried decreasing the interval time in his function, but it didn't have much of an effect.)

 

Every other solution I've found on the internet either assumes that it's an IE problem (I'm having the problem with Firefox on a Mac) or involves coding practices that I try to avoid.  (putting js directly in the html, doing things that would invalidate my strict xhtml 1.0, etc.)

 

Any suggestions?

Link to comment
Share on other sites

Hmm...a quick look at the brothercake link shows that it's similar to something like jQuery's ready method.  Since I would follow John Resig into the bowels of hell simply because his code is beautiful, I recommend trying jQuery's version.  Why?  I trust his code, and I've never heard of brothercake before.

 

You can find jQuery here: http://docs.jquery.com/Downloading_jQuery

 

Since you probably don't want to port all of your code over to use jQuery's syntax, I suggest stuffing what you have now within the ready method like so:

 

<script type="text/javascript">
   $(document).ready(function()
   {
      /* rest of the script goes here */
   });
</script>

 

Obviously, there's no guarantee that it'll work, especially since you tried something similar, but it's worth a shot.

 

If that doesn't work, you could perhaps have two menus - one for JavaScript users, one for those with JavaScript turned off.  Have the entire JavaScript menu have a display attribute set to 'none' and put the other menu in a <noscript> tag.  Then, have your script set the display of the menu to 'block' when the document loads.

 

If JavaScript is disabled, the <noscript> version will be displayed.  Otherwise, the script will make the more dynamic version visible.

Link to comment
Share on other sites

I got an idea.

<html>
    <head>
         <title>Test</title>
         <style type="text/css">
              @import url('style.css');
         </style>
    </head>
    <body>
         <script type="text/javascript">document.getElementsByTagName("head")[0].innerHTML += '<script type="text/css">.dropdown { display: none !important; }</style>';
    </body>
</html>

 

If the class is dropdown, then that should execute fast enough.

 

Oh, and in style.css, you can have:

.dropdown { display: block; }

Link to comment
Share on other sites

Nightslyr, thanks for the jQuery link.  I don't think I'll be using it in this specific situation (a 56k js library just so I can use one function seems like overkill), but it is something I'd like to look into in the future.  (What made you choose jQuery over another library, like prototype?  I've been meaning to get around to learning about the various js libraries out there, and it seems like jQuery and prototype are the two most popular.)

 

Ken, thanks, I'll try that out and let you know if it works.

 

I wonder if part of the problem could be that, rather than using display:none, I'm using position:absolute;left:-999em;height:0;  I've been doing that so that screenreader users will still hear the menu options, even though sighted users won't see them.

Link to comment
Share on other sites

If you're going to have display: none, why need the positioning, left and height?

 

Actually, she said that instead of display: none, she was thinking of putting it off-screen (-999em) during the initial load.  I assume height 0 would be to ensure it didn't screw up other elements' positioning, since it'll be absolutely positioned initially.

 

Regarding jQuery, I like it because it has a good power-to-simplicity ratio - a small amount of code can do a lot - and its CSS selector engine is incredible.  That code written in it is very readable, and that the framework as a whole has a small footprint is icing on the cake.

Link to comment
Share on other sites

It worked! :)  Using javascript to insert the css to hide the menu did the trick.  Thanks, Ken2k7.

 

I ended up using the DOM instead of innerHTML, because IE doesn't allow innerHTML to insert things into the head.  I also ended up using display:none for IE instead of the css positioning thing I'd been doing, due to css bugs in IE7.  (I'll try to figure out how to get it working in IE7 later, but that isn't really relevant to the javascript problem I was having, so I'm flagging this thread "solved".)

 

In case anyone reading this is having similar problems, here's the relevant parts of the code.  (Note that it's not in a function to run on load.  It runs the moment it's found by the browser.)

 

var add_css = document.createElement('style');
add_css.setAttribute('type','text/css');
var css_text = document.createTextNode('ul#nav li ul{position:absolute;left:-999em;height:0;}');  //or display:none or whatever the css should be
try
{
add_css.appendChild(css_text);
}
catch(e)  //the above try block fails in IE6 and 7
{
add_css.styleSheet.cssText = 'ul#nav li ul{display:none}';
}

document.getElementsByTagName("head")[0].appendChild(add_css);

 

Thanks again, Ken2k7 and Nightslyr. :)

Link to comment
Share on other sites

Know what's sad? I actually forgot the NOSCRIPT tag.

 

Would this work also:

<html>
     <head>
          <title>Test</title>
          <style type="text/css">
               @import url('style.css');
          </style>
     </head>
     <body>
          <noscript><style type="text/css">.dropdown { display: block !important; }</style></noscript>
     </body>
</html>

 

CSS

.dropdown { display: none; }

 

?

 

If it does, awesome! JavaScript is tacky. Note: I also swapped the display around. ;)

Link to comment
Share on other sites

well, this way all the js and css is kept out of the html, so it's better for separation of content and presentation.  Also, is noscript valid xhtml?  I don't know why, but I was under the impression that noscript tags were sort of an archaic, hacky way to get around js problems.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.