Solved

Deferring CSS (Theme Stylesheet)

madia
Excursionist
17 0 3

So I noticed this issue or question gets mentioned A LOT, but no one really has been able to resolve the issue. 

 

For Example:

Hi, looking to defer/ preload my main style sheet, as per google recommendations for deferring 

Defer non-critical CSS - https://web.dev/defer-non-critical-css/

 

Being trying this.. so far.. no luck.. kills my site or random flashes of css rules popup before page fully load.

 

 

<link title="theme" rel="preload" href="{{ 'theme.css' | asset_url | stylesheet_tag }}" as="style">
<noscript><link rel="stylesheet" href="{{ 'theme.css' | asset_url | stylesheet_tag }}"></noscript>

 

 

or

 

 

<link rel="preload" href="//cdn.shopify.com/s/files/1/0219/6550/4612/t/10/assets/theme.css?v=6116588842272161559" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="//cdn.shopify.com/s/files/1/0219/6550/4612/t/10/assets/theme.css?v=6116588842272161559"></noscript>

 

 

 

The default way our theme developer has brought in the stylesheet..

 

 

{{ 'theme.css' | asset_url | stylesheet_tag }}
{% if settings.use_rtl %}{{ 'style-rtl.css' | asset_url | stylesheet_tag }}{% endif %}

 

 

 

How can I defer or preload the CSS without other elements popping up quickly while page loads or blocking the first paint of of the website? Please tell if I am doing something wrong here. Thanks in advance!

Accepted Solutions (2)

jameskosh
Shopify Partner
10 4 17

This is an accepted solution.

I would assume your theme.css is critical (as in it affects the critical rendering path). If so, you should not be deferring it since that only further delays the render of your page. Instead, you should make sure it's prioritized by either inlining it in the HTML (turn it into a Liquid snippet and render it) or at the very least, add a preload hint at the very top of the HTML so the browser sees it immediately as the HTML is streamed to it.

One drawback to note regarding inlining is that if your CSS file is pretty large, the browser will have to re-download it each time if its inlined, which will be a worse UX compared to having the browser cache the file and load it from cache on subsequent requests. You can either conditionally inline the CSS depending if the browser has already downloaded it (difficult to do, but I've done it before) or just preload the CSS as early as possible as I mentioned in the previous paragraph.

If the CSS is not critical, then you should asynchronously load it like this:

<link rel="alternate stylesheet" href="slow.css" title="styles" as="style" onload="this.title='';this.rel='stylesheet'">

 

View solution in original post

jameskosh
Shopify Partner
10 4 17

This is an accepted solution.

You won't need a preload hint if you're inlining the CSS. Also, I would recommend replacing `include` with `render` since `include` is deprecated.

View solution in original post

Replies 8 (8)

jameskosh
Shopify Partner
10 4 17

This is an accepted solution.

I would assume your theme.css is critical (as in it affects the critical rendering path). If so, you should not be deferring it since that only further delays the render of your page. Instead, you should make sure it's prioritized by either inlining it in the HTML (turn it into a Liquid snippet and render it) or at the very least, add a preload hint at the very top of the HTML so the browser sees it immediately as the HTML is streamed to it.

One drawback to note regarding inlining is that if your CSS file is pretty large, the browser will have to re-download it each time if its inlined, which will be a worse UX compared to having the browser cache the file and load it from cache on subsequent requests. You can either conditionally inline the CSS depending if the browser has already downloaded it (difficult to do, but I've done it before) or just preload the CSS as early as possible as I mentioned in the previous paragraph.

If the CSS is not critical, then you should asynchronously load it like this:

<link rel="alternate stylesheet" href="slow.css" title="styles" as="style" onload="this.title='';this.rel='stylesheet'">

 

madia
Excursionist
17 0 3

Got it. So yes, the theme.css is critical css that has been placed in a liquid snippet in the main HTML sheet.

{%- include "include_css" -%}

With that being said, what preload hint should be added to this?

jameskosh
Shopify Partner
10 4 17

This is an accepted solution.

You won't need a preload hint if you're inlining the CSS. Also, I would recommend replacing `include` with `render` since `include` is deprecated.

madia
Excursionist
17 0 3

Awesome. This has been EXTREMELY insightful. My site is loading A LOT faster now. Thanks so much for the help.

jameskosh
Shopify Partner
10 4 17

No problem! Glad I could help!

Eddie-Hosseini
Visitor
1 0 0

Dear James,

I tried to understand what you were trying to say, but I really have no clue how to improve my site speed. Could you please help me?

My site is: https://www.widorf.com/

Thanks

jameskosh
Shopify Partner
10 4 17

Hi @Eddie-Hosseini, in this thread I'm explaining how to do a specific web performance optimization, but it's not necessarily the best for your site. I'd be happy to help with your site, but since it might not be relevant for others in this thread, I would recommend messaging me directly or email me via jamesk (at) devisedlabs.com.

alexflorisca
New Member
7 0 0

Hi,

Just chipping in with something that might be useful. I've had to do this recently while developing a theme and found it quite frustrating having to manually generate the critical-css and upload it to the theme files. I also noticed my css was widely different between some pages (product page vs home page). So I built an app to solve these problems. 

Check it out here.

It will generate all the critical css for every type of page on your store (home page, product pages, collections, pages, blogs, etc. You still need to click the button every time your theme's css changes, but I'm thinking about a webhook to do it automatically in the future.

Hope this is useful.

Alex.