Telerik blogs

One of the cool things we released along with the Kendo UI Winter Release last week is the brand new Kendo UI Music Store demo . It’s a complete, end-to-end demo designed to show many of the pieces from Kendo UI Web, DataViz, (and soon Mobile) working together in the context of a “real app,” along with the necessary server code to expose JSON web services and load and persist data in a database. It is based on a Microsoft demo originally created for ASP.NET MVC, but the concepts are universal. Our plan is to eventually provide alternate implementations of the server code in Java and PHP so you can view the demo in the language you prefer most.

The complete source for the demo is available on GitHub .

This demo also happens to be one the top requested features (more than 480 votes!) on the official Kendo UI UserVoice feedback portal ( feedback.kendoui.com ). We’re stoked that this demo delivers on one the major things you guys (our customers and community) have been demanding for a while.

So, we’re happy with the demo, but in the initial release it had a problem. It had FOUJUI .

Music Store “Flash of Uninitialized JavaScript UI”

More than a year ago, I coined "FOUJUI" to described a problem common to applications that rely heavily JavaScript UI. In short, FOUJUI occurs when you rely on JavaScript to build part of your UI (render HTML/apply CSS) after your page loads. Since JavaScript takes time to download and run, users potentially see a version of your page "pre-JavaScript UI" and then suddenly (after your scripts run) they see the "correct" layout.

The problem is easy to ignore since it doesn't impact the function of an app or site, but it's ugly, distracting, and not the kind of first impression you want to give your users.

The first release of the Kendo UI Music Store demo did exactly this. Because Kendo UI Web widgets were used with a mix of server-side HTML rendering, there was a brief flash of the uninitialized HTML (as rendered on the server) before the JavaScript ran and the final layout kicked-in. You can see the effect in the GIF below:

KendoMusicStore-FOUJUI

This is a perfect chance to fix FOUJUI and show one technique for solving the problem in your own apps.

Fixing FOUJUI with Opacity Animation

I’m a big fan of fixing FOUJUI with opacity animations. The technique is simple and the effect looks very nice. In general, the idea behind this solution is:

  1. Hide (via opacity) the HTML that must be initialized by JavaScript
  2. Run your JavaScript to initialize the UI (such as your Kendo UI widget JavaScript)
  3. Show (via opacity) the final, initialized HTML UI

Why opacity? Why not use something like “display:none” or “visibility:hidden”? Two reasons:

  1. By working with opacity, we’re not triggering layout changes when we toggle between “invisible” and “visible” UI. Changing an element to “display:none” actually removes it from the document layout , which we don’t need (or want) to do. That’s extra work for a browser, and it potentially introduces new undesired UI reflows as elements are shown with “display:block.”
  2. Meanwhile, “visibility:hidden” can be used to hide/show elements without removing them from the layout, but there is no way to animate the “visibility” CSS property. It’s binary: hidden or visible. Opacity gives us the ability to animate (if we want to) the visibility of an element from 0 to 1. As a bonus, if we use CSS transitions, the opacity animation can also be hardware accelerated (in supported browsers).

The first step to fixing the problem in our Music Store demo, then, is hiding all portions of the UI that need to be initialized by JavaScript. You can, of course, hide ALL of your page UI (similar to a loading screen), but that’s a bit heavy handed for the web. I’d prefer to just hide the areas that need initialization. Done well, odds are many users won’t even notice the loading effect, which is a good thing!

Referring to the GIF above, we can see one of the worst FOUJUI offenders is the Menu. In the Music Store (as in many apps), the menu HTML is rendered dynamically server-side making the sub-menu items appear as visible un-styled links until Kendo UI is initialized.

MusicStore-FOUJUI-Menu

We should do two things for this type of situation to provide the best loading experience:

  1. “Pre-build” more of our HTML. While dynamic JavaScript UI can handle the task of taking very simple HTML and rendering all necessary styles and HTML, for fixing FOUJUI, sometimes it’s better to “pre-build” more of the HTML- particularly CSS styles and classes- by hand. This ensures the HTML is styled correctly as soon as it’s seen by the user (assuming our stylesheets are properly loaded).
  2. Hide HTML that should be initially hidden. Most of the menu items we see should not be visible, even after the JavaScript UI is initialized. We can “help” during page load by manually hiding these items instead of waiting on our JavaScript to do the work for us.

The code required for these two techniques is quite simple:

<!--BEFORE-->
<ul id="menu" data-role="menu">

<!--AFTER-->
<ul id="menu" data-role="menu" 
class="k-widget k-reset k-header k-menu k-menu-horizontal" 
style="opacity:0;">


It’s a little more work, but it is worth it when you’re optimizing for FOUJUI. If you’re not sure how to build the HTML by hand, just inspect elements using browser dev tools to see what JavaScript normally does to build the final widget HTML and CSS.

For the rest of the elements on the Music Store homepage, I apply more of a catch-all FOUJUI opacity setting:

<div id="body" style="opacity:0;">
<!--Server-side view engine code-->
@RenderBody()
</div>


Next, I need to setup my CSS transition so that the eventual opacity change will be animated by the browser. Adjusting the length of this animation will determine how subtle or “obvious” the loading animation appears.

/*  Global CSS Transitions
------------------------------------- */

* { 
-webkit-transition:opacity 1s;
-moz-transition:opacity 1s;
transition:opacity 1s;
}


I’ve used the universal selector to apply the transition to all opacity changes in my app. It has no perf implications ( as I discussed previously ), and it’s more convenient than explicitly targeting all CSS selectors where I want this transition to happen. Only one word of caution: if you are using opacity to do other things in your app, the universal selector approach could cause some unintended transitions.

Finally, I just need to run some JavaScript to change the opacity of these now hidden elements from 0 to 1 once I know the necessary JavaScript UI initialization is complete. The animation will happen “for free” thanks to CSS transitions. To keep things simple, I can just put this line at the bottom of my page, after all other JavaScript has run, implicitly ensuring the opacity change happens after my JavaScript UI is ready:

<script>
//Place this at the bottom of the page (after all other scripts)
$("#body").css("opacity", 1);
</script>


Ideally, you want to run this code as soon after JavaScript widgets are initialized to minimize the time it takes for users to see your UI. In the case of the Music Store, I use the “bottom of the page” technique for most elements, except UI widgets in the page header (like the Menu). For the menu and search box, I run very similar code in the JavaScript module that initializes those Kendo UI widgets.

(If you want to see all of my changes, exactly as I applied them to the Music Store demo, here is the git commit showing exactly what I did .)

No More FOUJUI

After these simple change are applied, our FOUJUI is gone! Now, thanks to some extra hand-coded HTML and precise opacity settings, users see most of the UI when the page loads, and the pieces that need initialization are pleasantly displayed when they’re ready. The final effect can be viewed live on the demo site , or you can see the result in the GIF below:

KendoMusicStore-FOUJUI-Fix

 

Don’t Ignore FOUJUI

I said it once in this post, but I’ll say it again. Don’t ignore FOUJUI!

It’s easy to do. If nothing else, the Music Store demo proves even teams with awareness of the problem and solution can overlook this obvious detail. The problem is easily solvable if you take the time to polish your final result.

As more UI moves to the client (instead of being rendered on the server), apply techniques like this so the web remains a beautiful place and not a frustrating mess of “now you see it, now you don’t” HTML. Got it? Good.


ToddAnglin_164
About the Author

Todd Anglin

Todd Anglin is Vice President of Product at Progress. Todd is responsible for leading the teams at Progress focused on NativeScript, a modern cross-platform solution for building native mobile apps with JavaScript. Todd is an author and frequent speaker on web and mobile app development. Follow Todd @toddanglin for his latest writings and industry insights.

Comments

Comments are disabled in preview mode.