How to optimize above the fold load speed

Posted on by

Above the fold is the first thing users see when they visit your website. It the most important part of a web page. You should load it as fast as possible, especially when there are 52.7% mobile internet users worldwide. This post is about front-end optimization tactics which will help you improve your visitors’ experience.

Too Long; Don’t Read

A simple solution:

1. Minify and concatenate CSS and JS files;
2. Use the HTML <style> element to define internal CSS;
3. Use the HTML <script> element to define internal JS and place it at the end of a <body> element.
4. Minify HTML.

That works great with small websites, e.g. landing pages, but I want to dive a little bit deeper in this post.

As an example, I will use the landing page of my website Digital Flask.

Introduction

A lot of websites still have problems with blocking page rendering and above the fold loading. As a solution for this, I will optimize the following:

1. CSS delivery;
2. Asynchronous image loading;
3. Non-blocking JavaScript loading.

1. CSS delivery

At Digital Flask I’m using internal CSS to reduce the number of HTTP requests. I recommend taking a look at the Jade – template engine. It is pretty handy for that purpose. It helps you use internal CSS and JS files and make an output as minified HTML.

There is an example of including the internal CSS and JavaScript.


head
  ...
  style
    include ../css/main.css
body
  ...
  script
    include ../js/main.js

I’m using “gulp-jade” module for GulpJS to compile my Jade templates into HTML code.


/**
 * Compile Jade into PHP
 * @usage gulp jade
 */
gulp.task('jade', () => {
  gulp.src('templates/layouts/index.jade')
    .pipe(jade({
      'pretty': false
    }))
    .pipe(rename('index.php'))
    .pipe(gulp.dest('dist'));
});

Internal CSS is a good practice and works great, but if you have a long page with a lot of styles, a browser will parse them all even if we don’t need everything to display the above the fold content. As we know, users need to see the above the fold content as soon as possible. How can we achieve that? For instance, we don’t need our footer styles to prepare above the fold content and here is a solution.

Define the required styles for your above the fold content and load them internally. Unnecessary styles should be stored in the local CSS file and loaded asynchronously.

First of all, let’s check which elements of our page are above the fold. You can either check that in a browser or, for instance, via Google’s PageSpeed Insights.

Above the fold | digital flask - digital marketing and ux agency, finland

In my case, there are the header, navigation bar, image, hero text, and a call-to-action button. These styles are the most important, also, don’t forget about the “reset” and other base styles, but the rest aren’t. Now we can split our styles into two chunks. I’m using a modular CSS approach via Sass preprocessor, so it’s very easy to divide the main CSS file. If you’re not using Sass or any other CSS preprocessor, I recommend checking Sass language and Sass guidelines.

At this point, we have two CSS files. The first is used internally in the <style> element. How do we load the second asynchronously? There are three solutions which I think are the easiest.

1. Link CSS at the end of a <body> element as the scripts.


<body>
  <link rel="stylesheet" href="main.css">
</body>

2. Use javascript on load event to switch the media property from none to all.


<head>
  <link rel="stylesheet" href="main.css" media="none" onload="if(media!='all')media='all'">
</head>

The trick is, that browser will still download the stylesheet with media = none, but won’t wait for the content to be available before rendering the page. Once the stylesheet finished downloading, it will change the media property and will be applied to the document.

3. The alternative non-javascript solution is to wrap link element in a <nonscript> tag.


@font-face {
  font-family: "Lato";
  font-family: normal;
  font-weight: 400;
  src: url("data:application/x-font-woff;charset=utf-8;base64,...");
}

The missing font won’t stop your page from rendering. It will use the first matching fallback font, and when your’s will be ready, it will repaint the elements.

2. Asynchronous image loading

On the Digital Flask page, we have a huge background image. The browser needs a lot of time to load and display it

There are plenty of solutions to improve this experience.For example, Medium uses a small blurry image, while original image is loading asynchronously and displays it when it’s ready.

Screenshot from Medium - blurry image on top and original below

I will use simpler way. I’m going to use default background color. Then I will load my image asynchronously and change the background when it’s ready. I will pick up #252b33 as my default color because I have its transparent version as an overlay on my image. Let’s add it our stylesheet.


header {
  background-color: #252b33;
  background-image: none;
  background-size: cover;
  background-position: center bottom;
  background-repeat: no-repeat;
}

Let’s create a function, which will create a new image object, download an image file and set it as a background-image when it’s ready.


let backgroundImage = new Image();
backgroundImage.src = "img/header.jpg";
document.getElementById("header").style["background-image"]=`url(${backgroundImage.src})`;

That’s it! Our image will be displayed when it’s ready. Users can comfortably browse the web page even with a poor internet connection.

Screenshot from Digital Flask - no background  color on top, background image below

3. Non-blocking JavaScript loading

I’m using javascript internally in the bottom of the page. For large files, it might be a good idea to use them externally. It will have a small impact on an SEO as well because it will increase text to HTML ratio.

Google’s recommendation on that is to use async attribute in our script tags.

What’s the difference between <script>, <script async> and <script defer>?

First will pause the parsing while the script is executing. Second won’t delay the page load first and run external javascript file when it’s available. Third will run javascript only when the DOM is ready.

Check this post for additional information: asynchronous and deferred javascript execution explained

It there a difference between putting your javascript in the bottom of the page and using async attribute? Not really.

But… You need to pay attention when using async attribute. Avoid using it if above the fold content requires javascript. For instance, I’m loading and displaying the background image via javascript. I was getting an error from Google that above the fold content isn’t ready, even when browser finishes parsing the whole HTML document.

The advanced solution is to split the JavaScript file. For instance, I will use my image loading function internally in the head of the document. Another script will be loaded externally with the async attribute. This approach will reduce the size of the HTML document, increase text to HTML ratio and allows the browser to deliver a faster time to first render.

I’ve run small tests in a browser. Google Chrome. Regular 3G (100ms, 750kb/s, 250kb/s).

JavaScript used internally in the bottom of the page.
DOM loaded ~1.78s, Finish 13.29s.

Image loading script used internally in the head of the document. Using script tags with async attributes for the other javascript.
DOM loaded ~1.08s, Finish ~12.82s.

non-blocking javascript test results in google chrome

Note that asynchronous scripts are not guaranteed to execute in specified order. Hope you bundle your scripts into one file.

Conclusion

I would like to remind one more time, above the fold section is the most important and should be displayed as soon as possible.

Now you know how to optimize the above the fold section load by removing render blocking stylesheets, images, and javascript files. These techniques will increase the loading speed and improve the user experience.

Hope you will find this useful. Think about your users and create better websites!