3 Ways to Deal with SFOUC in KnockoutJS

What is SFOUC?

A Sudden Flash Of Unstyled Content, or SFOUC, refers to that irritating few milliseconds between when your web page loads and when all of your dynamic content pops into place.

The reason for this annoying phenomenon is that your HTML is being rendered a split second before your CSS & JavaScript files have finished downloading and running.  The un-augmented HTML sits there just long enough to catch the eye of your user, and then is whisked away as soon as all the lovely dynamic content is ready to replace it.

I’ve found that this is particularly evident when working with KnockoutJS because generally the last line of your startup code is ko.applyBindings(viewModel), and until you bind the view model you always see the unstyled content.

So how can we stop this menace?

Option 1: The “Classic” Approach

KnockoutJS is just a library on top of JavaScript so there is no reason why we can’t use the same approach as is suggested for non-Knockout apps.

There are a few flavours to this, but as a general solution:

  1. Add a class to the body element (e.g. no-js)
  2. Add a class to the dynamic content (e.g. dynamic-content)
  3. Add a style that hides dynamic-content within no-js

    .no-js .dynamic-content { display: none; }
    
  4. Add some JavaScript to remove the no-js class from the body once everything is loaded

    document.body.className = 
        document.body.className.replace("no-js", "");
    

This will do the job quite nicely, but still relies on the CSS loading quickly enough to hide the dynamic content before anyone notices.

Option 2: The “Visible” Approach

If the idea is to reduce the amount of time the basic HTML is visible then the fastest place to put the “don’t show this” instruction is in the HTML itself – using a style="display:none" tag.

The problem with this approach is that you then have to to go through and remove all of those styles once your JavaScript is ready to run; this is where the visible binding can help us out.

Under the covers, the visible binding simply sets the display style to none or to "" (i.e. not set) so we can use this to automatically remove the style tags created above:

<div style="display:none" data-bind="visible: true"> </div>
<!-- or -->
<div style="display:none" data-bind="visible: $data"> </div>

The first of these examples will display the div as soon as Knockout is bound; the second will display as soon as the current context has a truthy value.

Option 3: The “Make-Everything-A-Template” Approach

Instead of trying to hide rendered HTML content until we’re ready, what if we just stopped rendering it all together?  If we put all of our dynamic content inside script tags (which obviously won’t be rendered by the browser) then we can use the template binding to render the content from inside the script tags in the context of a view model.

<div data-bind="template: 'dynamic-content'">
    <!-- will appear empty on page load -->
</div>

<script id="dynamic-content" type="text/html">
    <h1>This will be rendered by Knockout</h1>
</script>

This makes for slightly more verbose markup than the other approaches but we can improve on this by switching to the containerless syntax:

<!-- ko template: "dynamic-content" --><!-- /ko -->
<script id="dynamic-content" type="text/html">
    <h1>This will be rendered by Knockout</h1>
</script>

A Note about Progressive Enhancement

Obviously if you want to employ progressive enhancement then these approaches will not work for you – they work by hiding the content until it is ready to be rendered.  If you are using progressive enhancement then I’m going to assume that the original HTML renders nicely anyway and that you don’t care about the SFOUC problem!

Advertisements

3 thoughts on “3 Ways to Deal with SFOUC in KnockoutJS

  1. Great article as always. I think it might benefit from a better acronym, though. SFOUC sounds a little bit NSFW, IYSWIM!

    Perhaps “Sudden Exposure of Unstyled Content” – SEUC. You could retitle the article “Does your website SEUC?” heh heh

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s