During the course of the year 2020, Google has announced that Core Web Vitals will be come a ranking factors. Google makes, such announcement when the company wants webmasters to prepare their website for the changes to come.
Core Web Vitals is a selection of metrics that help characterize the user experience on a page: how fast does it render? how fast is it interactive? Does the content of the page jump around when new element are loaded?
In technical terms thats gives:
Largest Contentful Paint (LCP): measures loading performance. To provide a good user experience, LCP should occur within 2.5 seconds of when the page first starts loading.
First Input Delay (FID): measures interactivity. To provide a good user experience, pages should have a FID of less than 100 milliseconds.
Cumulative Layout Shift (CLS): measures visual stability. To provide a good user experience, pages should maintain a CLS of less than 0.1.
https://web.dev/vitals/
You can find the Core Web Vitals for a page by using tools such as https://developers.google.com/speed/pagespeed/insights/ but they are also available in Google Search Console and other Google products.
As the opportunities for improvement will vary greatly from one website to another. I will develop here the one I encounter during my own optimization process, and hopefuly it will be useful to others. Let’s analyze some opportunities:
Preload keys requests:
Preloading a font to be loaded ahead of time so that when it is needed, it is already available.
https://web.dev/codelab-preload-web-fonts/
https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content
Preloading content is also useful to help prevent blocking resource.
When preloading the font, Google Page Speed returns an error message that the font is not used:
Warnings: A preload <link> was found for “https://www.example.com/templates/horme_3/fonts/glyphicons-halflings-regular.woff” but was not used by the browser. Check that you are using the `crossorigin` attribute properly.
https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content#Cross-origin_fetches
So preloading a font will look like:
<link rel="preload" href="https://fonts.googleapis.com/css?family=Michroma|Roboto" as="font" crossorigin >
<link rel="preload" href="/some/script.js" as = "script" />
<link rel="preload" type="text/css" href="/some/style.css" as="style" />
In the same vein, you can also preconnect to external resource to gain on loading time:
<link rel="preconnect" href="https://stackpath.bootstrapcdn.com" >
Cumulative Layout Shift (CLS)
The most common causes of a poor CLS are:
- Images without dimensions
- Ads, embeds, and iframes without dimensions
- Dynamically injected content
- Web Fonts causing FOIT/FOUT
- Actions waiting for a network response before updating DOM
The first suggestion apply to my case as I don’t declare any width and height in the picture element. I got used to the flexibility of responsive image (calculated according the size of the screen) and didn’t move on to the srcset method where the different image size available are listed with specification regading the screen size it should be displayed at. This method requires to carefully plan break and the various size available to fit the different screen size. Example:
< i mg srcset="elva-fairy-480w.jpg 480w, elva-fairy-800w.jpg 800w" sizes="(max-width: 600px) 480px, 800px" src="elva-fairy-800w.jpg" alt="Elva dressed as a fairy"> The code above did not work as desired (the image loaded on mobile screen size was still the largest one. The following code works as intended:<picture>
<source media="(max-width: 799px)" srcset="elva-480w-close-portrait.jpg">
<source media="(min-width: 800px)" srcset="elva-800w.jpg">
<img src="elva-800w.jpg" alt="Chris standing up holding his daughter Elva">
</picture>
In the article about optimizing cls cited earlier, it is specified that you need to give the image aspect ratio (actually width and height) so that the browser can calculate the size on the screen as soon at it received the css relative width, for example:
width:100%
implementing min-height for the images class solved the issue of layout shifting. The text still overlay pictures that have a height larger than the min-height but it’s due to a javascript (matchHeight.js) in my template which role is to set all div from a row to the same height. This needs to be replaced with css that performs the same action.
Avoid displaying empty font:
adding
font-display:swap;
to the @font-face in the bootstrap css glyphicon font delaration solved the issue. It tells the browser to use a build-in font to render the text while the proper font is loaded.
https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display
Display pictures at the proper size
To display picture properly on high-dpi screen I use to display compressed jpeg at half their actual width. This rendered well on iPhone screen even though the quality was a bit lower on desktop compared to the same compression but at the actual size.
The issue with this method is that it requires that the browser resize the picture to the screen size and it might consume more badwidth than serving the picture at the actual screen size, although with this method you can serve picture twice the size but lighter than the actual size one because they are more compressed.
There might be an alternative that would save the computer the calulation cost and that would be to use picture at 100% their screen size but saved with higher dpi so that they look good on high-dpi screen as well.
We need to control that high-dpi picture are looking good on retina display and the like, but also that the CMS, when generating thumbnails, will also create high-dpi thumbnails.
Security
Link with target="_blank"
are unsecured without rel="noopener"
or rel="noreferrer"
. Read more:
https://web.dev/external-anchors-use-rel-noopener/
And on wether or not you should use target="_blank"
at all :
Best practice:
Links do not have a discernible name
if your link doesn’t have text or a picture with an alt-tag, you can use arial-label=”link description” for people using assistive technology.
Next step: remove unused CSS and javascript!