2021 was the year I decided I was going to rebuild my aging website using every speed optimization and accessibility technique that I had learned since the last time I redesigned my website. In the past few years, I had a large focus on speed and user accessibility which was part of the driving force in doing the redesign, so at the beginning of my planning stages, I had a few goals in mind:
- My new website had to be the epitome of a fast website, I wanted to prove that a WordPress website could get perfect speed scores!
- My new website had to be fully accessible by following WCAG guidelines
- My new website had to be fun, not only did I want the website to be engaging to site visitors, but I also wanted it to be fun to build, I wanted to play around with modern browser features that I was unable to use in previous projects such as switching between dark and light modes.
Welcome to part 1 of my Website Refresh series, In this article, I’ll share some insights into how I got perfect speed scores on both GTMetrix and Google PageSpeed Insights (mobile and desktop).
First things first, provide proof of a perfect speed score, I didn’t want to just write an article about how to obtain great load times, I also wanted to back it up with a proof of concept.
First up, GTmetrix results:
- GTmetrix Grade: A
- Performance: 100%
- Structure: 100%
- Largest Contentful Paint: 457ms
- Total Blocking Time: 0ms
- Cumulative Layout Shift: 0
There is one caveat with GTmetrix however, due to using the free Cloudflare service, I’m only able to get a perfect GTmetrix score in European countries, most likely because Europe accounts for most of my web traffic and Cloudflare is automatically adjusting speed preference to that area.
Next, Google PageSpeed Insights results:
- Score: 100
- First Contentful Paint: 1.1 s
- Speed Index: 1.6 s
- Largest Contentful Paint: 1.1 s
- Time to Interactive: 1.1 s
- Total Blocking Time: 0 ms
- Cumulative Layout Shift: 0
- Score: 100
- First Contentful Paint: 0.3 s
- Speed Index: 0.6 s
- Largest Contentful Paint: 0.3 s
- Time to Interactive: 0.4 s
- Total Blocking Time: 20 ms
- Cumulative Layout Shift: 0
Building the theme
Since I was updating my old site, I didn’t have to think too much about content, so the starting point for me was of course the theme, and in order for me to meet my goals, and get the exact look I wanted, I created my theme from the ground up, this would give me complete control over every aspect of the theme. I didn’t want to start completely from scratch, so I decided to build the theme using the BlankSlate starter theme By TidyThemes, this theme only had the basic, required files with no extras.
When it comes to building with speed in mind, you want to keep things simple, start with the basics, and keep things as minnimal as possible, once that is done, you can then add onto it. Every time I added something new to my website, I would test it to see how it would affect my sites speed scores.
Going into the development of my theme, I knew that I needed to keep the stylesheet as small as I could, I was only going to include exactly what was needed, nothing more. At this stage I decided to start with an empty stylesheet, I also decided that I was not going to include any CSS normalize or CSS Reset libraries, I felt that with IE11 finally going away on June 15th, 2022, we have come far enough along, that I was not going to be overly concerned if my sites line-height was a few pixels off from one browser to the next, after all, I’m a developer, not a designer, and honestly I probably wouldn’t even notice or care.
By excluding resets and normalize and by starting with an empty stylesheet and adding only what was needed, I was able to keep my stylesheet fairly light, currently, as of writing this article, the stylesheet was around 1200 lines and 70kb uncompressed, but after being minified and compressed, the file was only 22.5kb.
There are still some stylesheet improvements I would like to make, such as separating the home page styles from the secondary page styles to remove any unused CSS from the site load. I use WP Rocket which I will talk about further on in this article, but a future release is said to include a feature that removes unused CSS, so I’m excited to test that out as it would make the process of separating the stylesheets unnecessary.
Another improvement I would like to explore is the use of the new CSS property content-visibility which has some amazing speed saving potential, basically, it will not render anything “below the fold”. I’ve used
content-visibility: auto; in other projects with varying degrees of success, in some cases, it gave a tremendous speed boost to the load time, especially on sites with long, complex home pages, however, I have had some issues from time to time with negative effects on the Cumulative Layout Shift of the page, this can be corrected using
contain-intrinsic-size: 1000px; as explained in the article content-visibility: the new CSS property that boosts your rendering performance, but even with that, I’ve continued to have varying degrees of success. I would recommend trying it out and see what happens, in the worst-case scenario, it doesn’t help and you end up removing it. I’m going to give it a try on my home page and see if it improves my speed score at all, in some cases it may not do anything at all if the content you are not rendering already does little to affect your load time.
Unfortunately for me, I do have a few plugins that I’m reliant on for the moment which requires jQuery, however, with the aid of another plugin which I will talk about later, I was able to disable those plugins on the home page, thus removing the need for jQuery on that page. Once I was able to remove the need for jQuery on specific pages, I added some code in my functions file to de-register the jQuery library for those pages.
I have a love/hate relationship when it comes to images, I think they make websites look great, but they’re usually the biggest offenders for poor website performance. I decided to move away from today’s common web trend of including a large hero image or video background, and instead rely solely upon a hero section built with pure CSS. While it’s still possible to create a great-performing website with a large hero image, you always find yourself in a balancing act between optimizing your image for best performance and having a crisp-looking hero image.
While I opted to exclude a hero image on my website, there are things you can do to keep hero images from doing too much harm to web performance. Lazy loading is great for images “below the fold” but in the case of hero images, you want that to load as fast as possible, I found the article, The Humble <img> Element And Core Web Vitals, by Addy Osmani a great resource on this subject. The article mentions pre-loading your hero images by adding the following tag in the site header,
<link rel="preload" as="image" href="donut.webp" type="image/webp">.
Remember that when you add images to your website, they should first be run through an image compressor like OptimiZilla or CompressOrDie, you should also use modern image formats like webP with fallback support.
Speaking of modern image formats, there are two upcoming formats to be aware of that will be replacing webP, AVIF, and my personal favorite JPEG XL, one day (hopefully) soon, both AVIF and JPEG XL will be the two dominant image formats, but until then, webP with JPG and PNG fallbacks will just have to do.
On my site, you will notice that I have icons in my menu, these icons are not font icons, but inline SVGs.
Inline SVGs are amazing, you add the SVG code directly into your content and it does require any additional network requests. I try to use inline SVG’s instead of images whenever possible, I try to never use images for icons, logos’ or anything else that’s not a photograph, they help keep your site looking great with imagery while keeping your load time low. SVG’s are great because you can transition or even animate. When adding SVG’s always run them through an SVG compressor, I always use SVGOMG to compress my SVGs. One word of caution with SVG’s, try to avoid overly complex SVGs as they are made of many paths or nodes which will hurt your speed scores since, as mentioned above, the more complex your code is, the longer it takes to render.
Fonts are pretty amazing, they can add so much character to your website, and they can help make your content more legible, especially when adding differentiation between paragraphs and headers, with that said, I decided to stick with web-safe fonts to avoid adding additional network requests.
If you do plan on using fonts, make sure you load your fonts locally and add
font-display: swap; to font-face declaration, also try to avoid using large font families such as the Font Awesome library, you do not need every single font icon, and loading that library can slow down your website a lot. I was using font awesome locally on my website before the refresh and it had a very negative effect on my speed score (another reason for the rebuild).
It’s common knowledge these days that too many plugins can bog down a website, slowing things down a lot for you and or your site visitors, but this is not always the case, it is highly dependant upon the plugins you are using. If the plugin developer is really good and built their plugin with speed in mind, then you could find you will have no issues at all with speed, but sadly this is rarely the case.
Before getting further into plugins, I wanted to talk about the three types of plugins. First, you have backend plugins, these plugins only affect the admin side of the website, usually adding additional functions and features that the admin can use to enrich their website. Next, you have frontend plugins that are primarily used to add additional functions to the frontend of the site such as contact forms, carousels, and anything else that site visitors would interact with. The last type of plugin is a mix that can affect both the frontend and backend. Personally, I try to use as few plugins as possible as many will hurt site performance, being a developer I am able to create my own functionality that meets my needs without hurting my site performance. The biggest problem with 3rd party plugins is that they are usually set up to load their stylesheets and scripts on every page instead of just calling them when they are needed, because of this, you could end up with over a hundred site resources being pulled into your home page when in reality you only need less than half of those being pulled in.
When it comes to backend plugins, I stay away from plugins like Elementor, Divi, or Beaver Builder, I find them to be slow, restrictive, and they generate way too many elements on the frontend, I find that the default Gutenberg editor works perfectly well as the blocks generate a minimal amount of elements to create the page. This is also one of the reasons I use WordPress over something like Wix, Squarespace, or Weebly, their page builders generate too many nested elements which can hurt site performance by slowing down browser rendering.
With that said, here are some of the plugins I used to help with site performance:
- WP Rocket: This plugin is a must-have for me, I’ve tested several speed optimization plugins and this one gave the best results. Wp Rocket has all of the features you would need to speed up a website and produces incredible results even without all of the speed optimization tips above. WP Rocket also includes simple CDN integration options, I used the free Cloudflare account for my CDN which seems to do the trick… at least in Europe. The one downside is that WP Rocket is a premium-only plugin, so you do have to pay $50 a year for a single site license which for me was well worth it.
- Plugin Organizer: This plugin is the secret sauce to eliminating jQuery on at least a few pages, I use Plugin Organizer to disable other plugins on a page by page basis, no more unused plugin resources slowing down page load times, and more importantly no more unused jquery powered plugins running on my vanilla script home page.
- WebP Express: I use this plugin to change all of my images to webP images on supporting browsers
- Contact Form 7: Why in the world would I include Contact Form 7? Well before Contact Form 7 version 5.4, it wouldn’t have been included as a plugin that helps with speed, but as of version 5.4, Contact Form 7 no longer requires jQuery on the frontend of the website and has become, to the best of my knowledge, the ONLY form builder that doesn’t solely rely on jQuery. If you know of any good pure vanilla script form builders, please let me know in the comments below.
- All-In-One Image CAPTCHA Pro: Ok, time for a shameless plug, yes, I did build this plugin, and yes, I really do use it on my own website, but the All-in-one Image CAPTCHA pro plugin was built with speed in mind, it will only enqueue the needed resources on pages its actually being used on, and on top of that, those resources and the functionality itself are lazy-loaded so it will not affect your sites performance or load times.
- PWA for WP & AMP: I actually haven’t set this one up yet on my website, but I’ve used it in other projects and it works great at turning your website into a progressive web app so that your site could be used offline.
Because this was a pre-existing site, the database needed a bit of cleaning up, so after removing some un-needed plugins, I cleaned up my database by removing abandoned tables that are no longer being used by previously deleted plugins, I ran a database cleaner found in WP Rocket and I changed my MySQL storage engine from MyISAM to InnoDB.
This last point is what I wanted to talk about, changing the MySQL storage engine from MyISAM to InnoDB added more consistency to my speed scores. When I was using MyISAM, my speed score results from GTmetrix fluctuated between the high 90s and 100, once I changed to InnoDB, I was able to get 100 more consistently (From European locations).
A simple way to change your database to InnoDB is to install a plugin that does all the work for you, once you are done you can uninstall the plugin and enjoy the extra speed boost in your speed scores.
Now, to be honest, it’s not very hard for a website to obtain perfect speed scores, just make sure it’s very minimalistic like http://example.com/, but if you want to build something that’s more than a simple site, then these are the things to remember:
- Use InnoDB as your MYSQL engine
- Start small with minimal features and work your way up
- Remove jQuery from your site if possible
- If your a developer and if possible, build your own custom functionality instead of relying on ready-built plugins, if you need to install a plugin ask yourself if it’s really needed, gauge its potential impact on performance, make sure it has great support, and when in doubt, ask the developer about its performance.
- Use Plugin Organizer to disable plugins on specific pages if they are not used on said page
- Reduce CSS and HTML
- Avoid using images “above the fold” to reduce the number of resources being requested
- Use lazyload techniques for images and iframes “below the fold”
- Utilize site caching
- Utilize a CDN
- Use compressed, inline SVG’s over images when applicable
- Use lightweight local fonts or browser-safe fonts