Go to main content

Textpattern CMS support forum

You are not logged in. Register | Login | Help

#1 2015-04-10 08:43:26

Bloke
Developer
From: Leeds, UK
Registered: 2006-01-29
Posts: 11,271
Website GitHub

Pagespeed and render-blocking CSS

As part of satisfying our Google overlords and their impending mobile-only search results in a week or two, I took a bit of time trawling and trying to fix highlighted Webmaster issues on a site. A 97% user experience was good enough for me until I get round to sorting out the spacing between tap targets, but the speed was lagging at 75%.

Google give the usual optimisation hints such as minifying and compressing, which I’ve done (though last time I asked, this particular host bizarrely didn’t support gzipped content for “performance reasons”! Go figure). But what I’m struggling with is:

Eliminate render-blocking JavaScript and CSS in above-the-fold content

I’ve added defer to all my <script> tags which has improved things somewhat and stopped it whining to some degree, but it’s still complaining about one thing. It says I need to optimise CSS delivery of http://fonts.googleapis.com/.... How do I do that for a <link> tag? I can use jQuery to load regular CSS with <noscript> fallback. Is that technique applicable to google fonts too, or is there another method I should use? I don’t really want “flash of web-safe font” issues to crop up by loading things asynchronously.

The hints go on about inlining CSS, but I can’t see how fetching fonts from a third party can be inlined. Is the PageSpeed tool being stupid and telling me to fix something I can do nothing about? Or is there a decent way to satisfy it without adding (more) scripts to the page weight?

Thanks in advance for any insight.


The smd plugin menagerie — for when you need one more gribble of power from Textpattern. Bleeding-edge code available on GitHub.

Txp Builders – finely-crafted code, design and Txp

Offline

#2 2015-04-10 10:00:57

geoff777
Plugin Author
From: Benarrabá Andalucía Spain
Registered: 2008-02-19
Posts: 282
Website

Re: Pagespeed and render-blocking CSS

Hi Stef,

I’ve messed around with this trying to get as close to 100% …

Export the fonts from Google upload them to Font Squirrel web generator
select Expert settings and tick: Base64 CSS.

If your fonts are ‘popular’ a lot of people may have them cached.
But do you need the whole family?

I gave up and just link to them. I need them.

Last edited by geoff777 (2015-04-10 10:01:22)


There are 10 types of people in the world: those who understand binary, and those who don’t.

Offline

#3 2015-04-10 10:17:38

philwareham
Core designer
From: Haslemere, Surrey, UK
Registered: 2009-06-11
Posts: 3,564
Website GitHub Mastodon

Re: Pagespeed and render-blocking CSS

I’ve done a lot of performance work over the last couple of months.

Leave the fonts on Google, seriously. Check the performance in a real test suite and the fonts are served much quicker on Google CDN than anything you could serve yourself. The Google Pagespeed score is a bit stupid sometimes – for example the whole thing collapses on img srcset and drops you score (as of April 2015).

The same can be argued for above-the-fold CSS. It’s debatable whether there are any performance gains on a dynamic page by inlining important CSS versus single external (and easily cached) file. What you should do is load your CSS as close to the top of the page code as you possibly can. But before that, if you have something such as an image sprite in your CSS make sure you prefetch that so it’s also loaded as soon as possible. Here’s my company site’s head code…

<!DOCTYPE html>
<html lang="en-gb">
<head>
    <meta charset="utf-8">
    <title>Graphic designers Farnham, Guildford, Surrey: Design Hive Ltd</title>
    <link rel="prefetch" href="http://static2.designhive.com/assets/img/sprite.svg">
    <link rel="stylesheet" href="/assets/css/main.1428658486860.css">
    <link rel="dns-prefetch" href="https://ajax.googleapis.com">
   ... rest of code ...

Basically, don’t sweat the perfect score, it’s a fair barometer for doing good practices but it’s not the be-all.

Use these tools for a better idea of real-world performance than Google Pagespeed:

Offline

#4 2015-04-10 10:25:58

philwareham
Core designer
From: Haslemere, Surrey, UK
Registered: 2009-06-11
Posts: 3,564
Website GitHub Mastodon

Re: Pagespeed and render-blocking CSS

Oh, and you are using WOFF2 format on any self-hosted fonts right, not anything else (apart from a fallback WOFF for older browsers and Comic Sans for IE8)? Of course you are.

Offline

#5 2015-04-10 10:33:18

Bloke
Developer
From: Leeds, UK
Registered: 2006-01-29
Posts: 11,271
Website GitHub

Re: Pagespeed and render-blocking CSS

Thanks for the thoughts guys. I’m coming round to the notion that PageSpeed is flawed. And from my tinkering, here’s why:

Firstly, I can confirm that loading fonts using the jQuery approach outlined in my OP does indeed work… sort of.

The main problem is one of timing. If I do this (gross simplification) just before my closing <body>:

<script defer src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script defer>
jQuery(function($) {
	// Load stylesheets asynchronously. gFontsLink variable is a URL set up in page head.
	if ($('body').size() > 0) {
		if (document.createStyleSheet) {
			document.createStyleSheet('<txp:variable name="gFontsLink" />');
		} else {
			$('head').append($('<link rel="stylesheet" href="<txp:variable name="gFontsLink" />" type="text/css" />'));
		}
	}

	// Prepend menu icon
	$('nav').prepend('<div id="menu-icon">Menu</div>');

	// Toggle nav
	$("#menu-icon").on("click", function(){
		$(".section_list").slideToggle('fast');
		$(this).toggleClass("active");
	});

	// ... blah blah more code here
});
</script>

then, when browsing, more often than not I get no style loaded at all (bleurgh!) and no responsive menu because the script bails with ReferenceError: jQuery is not defined. And a host of other site issues that rely on jQuery being available to set them up. BTW, I’ve omitted the stylesheet loading in the above code, just showing the google fonts portion for readability: the full thing’s more involved (conditionals to load sheets based on the section being viewed, and under error conditions, etc).

It seems that the browser is not honouring defer on inline scripts and executing the content of the second script before jQuery has loaded, which understandably fails. Using async is the same. Maybe I’ve misunderstood how defer is supposed to work: I thought it guaranteed load order to that defined in the document.

Anyway, resorting to removing defer from the jquery.min.js script (as I had it when I had a 75% PageSpeed score) fixes things visually… but PageSpeed then goes back to complaining about jQuery being a blocking resource and the score is actually lower than before at around 60%, because the CSS and Google fonts are dependent on jQuery being loaded.

There are a number of “solutions”. Number one is to just not use jQuery at all and resort to raw JavaScript (nooooooooooooooooo!) for setting above-the-fold things up:

document.addEventListener('DOMContentLoaded', function() {
    //.. do stuff ..
});

But that means re-learning all the good stuff that I take for granted in jQuery, like event hooks.

Another approach is to defer running the inline <script> until full page load (not just DOMReady) and either put up with the naked page until that point when the stylesheets are then loaded, or employ some kind of ‘cover page’ with a loading icon to hide the fact the page isn’t ready and use jQuery to toggle the overlay off when the styles are in. I can see that being a big problem, given the browser has already fired the OnLoad event and I’m then telling it to fetch the Stylesheets after that event occurs. So I have no hook to say when it’s done, so no way to know when to remove the overlay class.

None of the latter options seem to be particularly endearing from an end-user perspective so, despite Google’s noble recommendations, I think I concur that a slower initial rendering time is a far better user experience than being a purist and trying to get the page speed numbers up.

Willing to be proved wrong if someone has any further tips, thanks.


The smd plugin menagerie — for when you need one more gribble of power from Textpattern. Bleeding-edge code available on GitHub.

Txp Builders – finely-crafted code, design and Txp

Offline

#6 2015-04-10 10:36:06

Bloke
Developer
From: Leeds, UK
Registered: 2006-01-29
Posts: 11,271
Website GitHub

Re: Pagespeed and render-blocking CSS

philwareham wrote #289859:

Oh, and you are using WOFF2 format on any self-hosted fonts right

I’m not using any self-hosted fonts right now, just a pair from Google Fonts. But if I was then yes, I’d use WOFF2.

Comic Sans for IE8

<splutter> What?!? ;-)


The smd plugin menagerie — for when you need one more gribble of power from Textpattern. Bleeding-edge code available on GitHub.

Txp Builders – finely-crafted code, design and Txp

Offline

#7 2015-04-10 10:53:34

philwareham
Core designer
From: Haslemere, Surrey, UK
Registered: 2009-06-11
Posts: 3,564
Website GitHub Mastodon

Re: Pagespeed and render-blocking CSS

Google Fonts serves WOFF2 nowadays I believe so that’s as good a reason as any to stay with them.

Please don’t use JavaScript (or even worse, jQuery) to load CSS or fonts. Let the browser do what it was designed to do. Other things that are of much better uses of your time for performance gains:

  1. Make all JPEG images progressive, at the correct pixel size, and not above 55% quality setting in Photoshop.
  2. Use mod_pagespeed to automatically generate WebP images of your JPEGs and serve them to compatible browsers.
  3. Get rid of Google Analytics.
  4. Make sure no cookies are on the site domain, i.e. see number 3 above.
  5. Serve assets (images/JS) from a couple of static subdomains in addition to your main domain, but leave the CSS file on main domain.
  6. DNS Prefetch any external domains needed, as close to top of head as possible (but under your CSS file).
  7. Cache the shit out of your site.
  8. Use CloudFlare with their CDN and performance settings turned on.
  9. Reduce SQL lookups to an absolute minimum, reduce your TXP tags to the necessities, reduce your dynamic content to the bare necessiites (e.g. if you know the site domain already then you don’t need to use <txp:site_url />, how much of your text really needs to be dynamic? Hard code any text/content/images that it’s doubtful you’ll be changing frequently or ever, etc.).
  10. Remove any CSS you don’t actually use. i.e. if you use Normalize.css, just keep the rules you need instead of just lazily slapping Normalize stylesheet into a project verbatim. Yeah, we all need that essential audio:not([controls]) rule don’t we?

Offline

#8 2015-04-10 10:58:59

philwareham
Core designer
From: Haslemere, Surrey, UK
Registered: 2009-06-11
Posts: 3,564
Website GitHub Mastodon

Re: Pagespeed and render-blocking CSS

Also, don’t use Drupal. For anything. That’s probably my first performance tip.

Offline

#9 2015-04-10 11:01:28

Gocom
Developer Emeritus
From: Helsinki, Finland
Registered: 2006-07-14
Posts: 4,533
Website

Re: Pagespeed and render-blocking CSS

If you want to use asynchronous JavaScript delivery, use an AMD library, e.g. Require.js, or concat the bitch. This forum uses Require.js too, with each component (jQuery plugin, library etc), and jQuery, loaded as a separate module on demand.

Bloke wrote #289860:

But that means re-learning all the good stuff that I take for granted in jQuery, like event hooks.

What? What does that even mean? How you load the library doesn’t change anything about how you use it…

Offline

#10 2015-04-10 11:02:02

Bloke
Developer
From: Leeds, UK
Registered: 2006-01-29
Posts: 11,271
Website GitHub

Re: Pagespeed and render-blocking CSS

Sage advice Phil, thank you. I follow bits of it but I’m guilty of not optimising images, using the entirety of normalize.css, not always using cache/cookieless subdomains, and I won’t pay for CloudFlare.

I’ll try and improve in the above regards.

Your faithful Padawan.


The smd plugin menagerie — for when you need one more gribble of power from Textpattern. Bleeding-edge code available on GitHub.

Txp Builders – finely-crafted code, design and Txp

Offline

#11 2015-04-10 11:03:49

philwareham
Core designer
From: Haslemere, Surrey, UK
Registered: 2009-06-11
Posts: 3,564
Website GitHub Mastodon

Re: Pagespeed and render-blocking CSS

CloudFlare is free.

Offline

#12 2015-04-10 11:07:35

Bloke
Developer
From: Leeds, UK
Registered: 2006-01-29
Posts: 11,271
Website GitHub

Re: Pagespeed and render-blocking CSS

Gocom wrote #289865:

How you load the library doesn’t change anything about how you use it

I meant for anything that’s critical to do on DomReady, one way is to just not use jQuery methods for it if there’s a chance it’s not loaded in time. i.e. set jQuery downloading asynchronously for later use (non-essential stuff that can be set up after full page load), but use JavaScript methods for stuff on DOMReady that needs to happen faster earlier.

I just wouldn’t relish having to remember how to set up cross-browser event hooks, create DOM elements by hand, and the like.

/me lazy and used to the convenience of jQuery’s methods.


The smd plugin menagerie — for when you need one more gribble of power from Textpattern. Bleeding-edge code available on GitHub.

Txp Builders – finely-crafted code, design and Txp

Offline

Board footer

Powered by FluxBB