One of the challenges that comes with pure JavaScript UI is a nasty little user experience problem that I'm calling "Flash of Uninitialized JavaScript UI," or FOUJUI (rolls right off the tongue).

FOUJI, similar to FOUC, occurs when:

  • Your rich UI is initialized by JavaScript
  • You rely on JavaScript to render some of your HTML
  • You optimize your site so that scripts run at the end of the page

When an user loads a page that meets these conditions, they briefly see a version of your site that doesn't look correct, as if it hasn't been fully loaded. Styles will be applied, but the UI will look incomplete.

Why?

Let's think about what's happening when you load a site that uses a rich JavaScript front-end (assuming best practice CSS and JavaScript patterns):

  1. The HTML page is requested and loaded (which includes any static HTML in your page)
  2. The external stylesheets referenced by your page are downloaded and the styles are applied to your static HTML
  3. The external JavaScript files referenced by your page are downloaded (this can take some time)
  4. The JavaScript code you've written to initialize your site and UI widgets (usually in a jQuery .ready() handler) is executed
  5. Finally, your site is fully rendered and ready to go!

The problem for users is that your site is "visible" before the initialization code runs to build your JavaScript UI. They see the styled static HTML before JavaScript has the chance to apply the needed transformations to your DOM.

To put this in context, I was having this problem in the Kendo UI Feed Reader demo. The problem was particularly pronounced on devices, like the iPad, where loading and execution of the site JavaScript is slower. Here's what users would see when loading the demo:

SNAGHTML3132a4a

Then, after the site initialization scripts ran and the Kendo UI widgets rendered, users would see the final (proper) site interface:

SNAGHTML314cb4a

Quite a difference! The uninitialized view is usually only visible for a split second (sometimes longer on slower device browsers), so you could easily dismiss this as an ignorable inconvenience. But we want to give our users a better experience. We want to eliminate the FOUJUI.

Solutions to FOUJUI

Solving the Flash of Uninitialized JavaScript UI can be done in a few different ways. The core problem is that the static HTML loaded on the initial request does not represent the final HTML as it will exist after JavaScript modifies the DOM. Solutions:

  1. Render All Initial HTML on the Server
    This is one of the benefits that server-side frameworks, like ASP.NET MVC or PHP, provide. They can render the "initial" HTML on the server and send a "completed" view to browser on the first request. The JavaScript UI initialization still happens and handles all subsequent UI actions, but the initial rendering is sent from the server, skipping the FOUJUI. (This technique can also have theoretical SEO benefits.)
  2. Use a JavaScript Loading Screen
    A loading screen? For the web?! It's not as crazy as it sounds as more of a web application moves to the client. As "web apps" become increasingly like their "native" counterparts, they inherit the challenges native apps have long faced with loading and initialization. Using some simple HTML, CSS, and JavaScript, a JavaScript loading screen can "hide" HTML that's waiting on JavaScript initialization, thus hiding the FOUJUI.

For the Feed Reader demo, everything is happening with static HTML and JavaScript, so option #1 (rendering the initial HTML on the server) is not an option. That means I'll pursue solution #2: a JavaScript loading screen.

Building a JavaScript Loading Screen

There are probably 1,001 ways to build a JavaScript loading screen, but for simplicity, I elected to use some simple HTML and CSS that would cover my entire application while the page is initializing.

HTML

<div id="preLoad">
    <div>
        <img src="styles/BlueOpal/loading-image.gif" alt="Loading Image" style="width:48px;" />
        <br />Loading...
    </div>
</div>

CSS

#preLoad{            
    width:100%;
    height:100%;
    background:#FFF;
    position:absolute;
    top:0;    
}        

#preLoad div{
    position:absolute;
    top: 50%;
    left: 50%;
    height:60px;
    margin-top: -30px;
    margin-left: -24px;
}

Now, when the Feed Reader app loads, rather than seeing the uninitialized HTML (or any of the app, for that matter), users will see my simple loading screen:

SNAGHTML3285fbc

Cool. That's better. Users understand loading screens, and it's a lot less jarring than seeing the FOUJUI effect.

But now I need to make the loading screen "go away" when the JavaScript UI is ready. Doing this requires two changes to my demo:

  1. I need to trigger a new event when the application initialization is done (so I know when to hide the loading screen)
  2. I need to handle the new event and write code to hide my loading screen when it is triggered

Simple enough. In the "init" event for my app (see the source), I add this single line of code that is executed after all initialization steps are complete (including the initialization of my Kendo UI widgets):

//Trigger event indicating init is complete
$(document).trigger("FEED_READER_APP_READY");

And then, to handle this event when it's triggered, I wire-up a binding in my main page that will hide my loading screen:

$(document).bind("FEED_READER_APP_READY",function(){ 
    $("#preLoad").fadeOut(); 
});

And that's that. Now users will always see the loading screen while my app is initializing, and when the UI is ready, the loading screen will fade out to reveal a ready-to-work application. No FOUJUI!

Improving the Effect with CSS3 Transitions

While the functional problem has been solved at this point, I quickly discovered that the jQuery "fadeOut" animation (which uses JavaScript) does not work well on all devices. The animation is choppy (at best) on mobile devices due to the weaker JavaScript processing.

We can improve this effect and make it buttery smooth on all devices by leveraging CSS3 Transitions. Browsers hardware accelerate CSS animations/transitions, giving CSS3 the power to speed-up any app (especially on mobile devices).

Browser support for CSS3 transitions is strong, but even browsers that don't support transitions will gracefully degrade to a functional, "direct" transition. So there's no reason not to use this technique.

Adding the Transition

The first step in this refactoring is to add the cross-browser CSS3 rules that define my transition. To achieve the same "fade out" effect, I will use the CSS opacity and visibility settings to hide my loading screen.

#preLoad{            
    width:100%;
    height:100%;
    background:#FFF;
    position:absolute;
    top:0;    
    
    -moz-transition: visibility 0s linear 1s, opacity 1s ease-in-out 0s;
    -webkit-transition: visibility 0s linear 1s, opacity 1s ease-in-out 0s;        
    -o-transition: visibility 0s linear 1s, opacity 1s ease-in-out 0s;
    transition: visibility 0s linear 1s, opacity 1s ease-in-out 0s;
}

This code basically says:

  • When "visibility" value is changed, change to the new value in 0s after a 1s delay
  • When "opacity" value is changed, change to the new value in 1s after a 0s delay

If opacity is used without visibility, then the entire app would remain "blocked" by the an invisible element after the loading screen fades out (opacity=0). By combining with visibility, the loading screen will fade out and be properly hidden. The delay ensures the opacity change animation will complete before the element is hidden.

Starting the Fade Out Transition

How do we trigger the CSS3 fade out transition? By simply changing the CSS opacity and visibility properties to their desired target values on our loading screen element:

$(document).bind("FEED_READER_APP_READY",function(){ 
    $("#preLoad").css("opacity","0").css("visibility","hidden"); 
});

When these values change, the browser will calculate the necessary animated transition to get from the original values to the new values, using the specified timing function ("ease-in-out") to shape the animation path.

The result: a fade out transition that looks smooth on desktop and mobile browsers.

The Final Result: No More FOUJUI

With these simple techniques applied, our user experience is now much better. When the application loads, users briefly see a loading screen, hiding the uninitialized HTML UI, and then a smooth, animated transition presents the app when it's ready.

You can try the updated Kendo UI Feed Reader demo for yourself to see this in action.

For those of you using a version of Internet Explorer less than 10 (the first from Microsoft to support CSS3 Transitions), here is a quick animated example showing what other browsers are seeing (in rough animated GIF format):

kendoui-feed-reader-foujui

The transition to JavaScript-driven applications will increasingly require developers to adopt "new" techniques to deliver premium user experiences. Eliminating the disruptive FOUJUI is one such problem that can easily be solved with minimal modification and code. Hopefully this post gives you some ideas for improving your own JavaScript application experiences, and hopefully you'll join me in eliminating FOUJUI!


About the Author

Todd Anglin

is an avid HTML5, CSS3, and JavaScript advocate, and geek about all things web development. He is an active speaker and author, helping developers around the world learn and adopt HTML5. Todd works for Telerik as VP of HTML5 Web & Mobile Tools, where his current technical focus is on Kendo UI. Todd is @toddanglin on Twitter

Related Posts

Comments

Comments are disabled in preview mode.