SEO: How to eliminate render-blocking JS and CSS in above-the-fold content
Since Google recently (End of April 2015) started to penalize non-mobile friendly and non-responsive sites in their ranking, we evaluated some online SEO tools to test our website. The best tool to get insights in what Google thinks about your page is PageSpeed Insights by Google.
Road to 100 / 100 in PageSpeed Insights
PageSpeed Insights is a Google Tool which helps you to identify ways to make your site faster and more mobile-friendly. Google includes the page speed in its ranking calculation, so that fast, responsive pages are ranked higher than slow ones. Therefore PageSpeed Insights analyzes a single page of a site and scores it in three categories:
- Mobile: Speed
- Mobile: User Experience
- Desktop: Suggestions Summary
In this article we describe how we optimized our website www.illucit.com to reach the score of 100 / 100 in each category.
When we first evaluated the performance of our page, Google claimed „Eliminate render-blocking JavaScript and CSS in above-the-fold content“. Unfortunately this „Should Fix“ issue is the main cause for our page to be scored only 70 / 100 in mobile speed.
Google’s Recommendations
Remove Render-Blocking JavaScript
The official guidelines by Google suggest that you should load JavaScript asynchronously by including it like this (https://developers.google.com/speed/docs/insights/BlockingJS):
1 |
<script async src="my.js"> |
Optimize CSS Delivery
„The critical styles needed to style the above-the-fold content are inlined and applied to the document immediately. The full small.css is loaded after initial painting of the page. Its styles are applied to the page once it finishes loading, without blocking the initial render of the critical content.“ (https://developers.google.com/speed/docs/insights/OptimizeCSSDelivery)
First of all we now introduced a deferred loading of the fonts and main stylesheet for our website.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<html> <head> ... <body> ... <script> var cb = function() { var l = document.createElement('link'); l.rel = 'stylesheet'; l.href = '/stylesheets/illucit.min.css'; var h = document.getElementsByTagName('head')[0]; h.parentNode.insertBefore(l,h); }; var font = function() { var l = document.createElement('link'); l.rel = 'stylesheet'; l.href = 'https://fonts.googleapis.com/css?family=Open+Sans:400,300,700'; var h = document.getElementsByTagName('head')[0]; h.parentNode.insertBefore(l, h); }; var raf = requestAnimationFrame || mozRequestAnimationFrame || webkitRequestAnimationFrame || msRequestAnimationFrame; if (raf) { raf(cb); raf(font); } else { window.addEventListener('load', cb); window.addEventListener('load', font); } </script> </body> </html> |
Loading all stylesheets and fonts after the document is loaded, results in flash of unstyled content (FOUC), however. This means the page is displayed with the browser’s default styles before the actual stylesheets are loaded (very ugly).
Therefore we now have to dive into the first part of Googles advice and inline the „critical styles needed to style the above-the-fold content“.
Inline CSS for rendering the above-the-fold content
Above-the-fold content denotes all content which is visible without scrolling. Since potential customers might have a slow internet connection using their mobile device, it is best when the above-the-fold content can be rendered by only downloading necessary CSS instructions with as few requests as possible. Google therefore even advises to inline CSS instructions into the website for above-the-fold content, because downloading a separate CSS file would mean an additional HTTP request to the server.
By inlining Google means placing the CSS instructions for above-the-fold content directly into the header of the page (as you can see in the example below).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<!DOCTYPE html> <html> <head> ... <title>illucIT Software GmbH - Würzburg</title> ... <style type="text/css"> // inline css here header h2 { margin: 20px 0 0 100px; padding: 8px 32px; ... } ... </style> ... </head> <body> // content here </body> </html> |
I totally understand your objection… Hey this is how we have done it years ago and now we are going back to inlining all the CSS into our website??? How can this be maintained? How can we embed our CSS – or even generated CSS – into the webpage?
And partly you are right, but who are we to judge Googles mobile ranking 🙂 At least we found a solution that is maintainable, supports Less and gets you a perfect scoring for Google PageSpeed Insights.
Our first approach was trying to inline the whole CSS file directly into the webpage, but Google calculates the percentages of how many of the inline CSS instructions are actually needed to render only the above-the-fold content. If you embed too many unnecessary CSS instructions into the website itself, Google also penalizes this. So inlining the whole CSS file is no solution.
From this experiment we derived our further action plan.
Action Plan
- Split the main CSS file into two files illucit-atf.css (atf = above-the-fold) and illucit.css
- Inline the CSS instructions from illucit-atf.css in the HTML page
- Load CSS ( illucit.css ) and fonts via JavaScript as seen above
- Minify CSS (this should be done anyway)
At first the HTML page is then rendered with the inline CSS, so only the above-the-fold content is styled nicely. The rest of the page may as well remain unstyled. After the page is loaded the remaining CSS file and the fonts are loaded and added to the HTML page, so when the user scrolls down, the page is styled completely.
Now you probably ask yourself…. but how do I figure out what CSS instructions should be inlined and which ones should be loaded later on? This is a JavaScript which assists you in figuring exactly this out by Paul Kinlan (https://gist.github.com/PaulKinlan/6284142). If you depend on Less or Sass, you have to do a little manual work, however. But you can take Paul’s script to get some hints as well.
But don’t worry if you forget to include some of the CSS instructions needed for the above-the-fold content. Google kindly reminds you of that by claiming „Approximately 38% of the above-the-fold content on your page could be rendered without waiting for the following resources to load. Try to defer or asynchronously load blocking resources, or inline the critical portions of those resources directly in the HTML.“
We figured out that the percentages mentioned in the error message above equal the amount of „real estate“ on the first screen (above-the-fold content), which could not be rendered completely without additional requests to the server.
Our first assumption was that the message appears due to the images and fonts, which are still loaded with additional requests. So we included above-the-fold images and fonts in CSS files inline – base64 encoded (!!!). Fortunately this was not the reason for the message. Since base64-encoding images and fonts results in very large and ugly HTML files anyway, we went back to including images and fonts normally.
Our second assumption was that we just forgot to include some of the instructions needed for the above-the-fold content. So we entirely removed loading the full illucit.css to find out which CSS instructions are still missing to render the above-the-fold content.
After identifying which CSS instructions are needed for the above-the-fold content, they need to be put in a separate file like illucit-atf.css. All the instructions in there should also be removed from the main CSS file.
Automatically inlining Less using Play Framework
The next step is to automatically generate CSS from Less and inline the resulting CSS into the HTML page, so it is delivered together with the page itself as part of the HTML. In this case there is no additional HTTP request required to load the CSS, which is necessary to render the above-the-fold content.
Our site is implemented with the Play Framework 2.4. However this technique works with any kind of server side technology – JavaEE (Wildfly, Glassfish, …), .NET or even PHP. As an example our solution with the Play Framework is presented. So we introduced a CssController which can be used to inline CSS instructions while still relying on Less.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
object CssController extends Controller { def mincss: String = loadMinCss def loadMinCss: String = { val resourceName = resourceNameAt("/public", "/stylesheets/illucit-atf.min.css") get val assetInfo = resource(resourceName) get val stream = assetInfo.openStream() try { (Source fromInputStream stream).getLines mkString "\n" } finally { stream.close() } } ... } |
The methods resourceNameAt and resource were copied from controllers.Assets . Using these methods enables us to access the CSS file which is generated from the Less file by the assets pipeline of the Play Framework. Using the assets pipeline even allows us to use the minified CSS file – depending on the pipeline configuration. So we can stick to Less and don’t need to fall back to plain CSS. The CssController is then called from the HTML page like this:
1 2 3 4 5 6 7 |
<head> ... <style type="text/css"> @play.twirl.api.Html(CssController.mincss) </style> ... </head> |
The call for play.twirl.api.HTML is needed because otherwise Scala would escape entities like quotes.
Conclusion
We used Google PageSpeed Insights to evaluate and improve the performance of our page and hence its ranking value. Currently the most significant issue is eliminating render-blocking JavaScript and CSS in above-the-fold content. In this post we managed to divide our CSS (or Less) files into two files – one for the above-the-fold content and one for the remainder of the page. Then we included the first file inline in the HTML page using the web server backend.
If you need any assistance in making YOUR website responsive and mobile friendly, do not hesitate and CONTACT US!