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.
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 (
). 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
More than a year ago,
I coined "FOUJUI"
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.
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:
- Show (via opacity) the final, initialized HTML UI
Why opacity? Why not use something like “display:none” or “visibility:hidden”? Two reasons:
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.”
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).
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.
We should do two things for this type of situation to provide the best loading experience:
- “Pre-build” more of our HTML.
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).
- Hide HTML that should be initially hidden.
The code required for these two techniques is quite simple:
<ul id="menu" data-role="menu">
<ul id="menu" data-role="menu"
class="k-widget k-reset k-header k-menu k-menu-horizontal"
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-->
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
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.
//Place this at the bottom of the page (after all other scripts)
(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
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:
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
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.