Netlify and Astro 1.4.x: Styles not imported the same way as on local machine

Hi everybody,

I have built a new site with Astro 1.4.x.

I deploy the site with “npm run build” which runs “astro build”.

I have a Astro component which defines some scoped styling for only this specific component. But this style does not get loaded properly after a deployment to Netlify. If I execute a local Astro build with “npm run build” and then “npm run preview” to check it out locally, then it works, the style ordering is correctly done in the html file. But on Netlify somehow the html is not built the same way and has a wrong order of loading the styles.

My current assumption:

  • The Netlify build somehow does not use the latest Astro version defined in my package.json and therefore it does not build the site correctly with the fixes given in Astro 1.4 (see Astro 1.4.0 Release | Astro).

I have also already tried to execute a deployment with “clearing the build cache”, but did not help.

I also assume that the CDN invalidation works as expected, because if I change for example some content in this index html, the changes are deployed properly but not the loading of the styles.

So currently I’m a bit confused, because locally it works, but not on Netlify.

Do you have any idea why this “style loading order” issue happens?

I have a current test branch here: https://netlify-astro-style-order-issue-test--comvation-website.netlify.app/

The latest log copy:

12:54:41 PM: Build ready to start
12:54:44 PM: build-image version: 9289b698a503f132b265bd089ab40ce1d6f9e65e (focal)
12:54:44 PM: build-image tag: v4.12.0
12:54:44 PM: buildbot version: 8004afba0d79c2913deefb1ea0ee8f3ed710b828
12:54:44 PM: Building without cache
12:54:44 PM: Starting to prepare the repo for build
12:54:44 PM: No cached dependencies found. Cloning fresh repo
12:54:44 PM: git clone git@bitbucket.org:comvation/comvation.com-website
12:55:01 PM: Preparing Git Reference refs/heads/netlify-astro-style-order-issue-test
12:55:04 PM: Parsing package.json dependencies
12:55:05 PM: Different publish path detected, going to use the one specified in the Netlify configuration file: 'frontend/dist' versus 'dist' in the Netlify UI
12:55:05 PM: Starting build script
12:55:05 PM: Installing dependencies
12:55:05 PM: Python version set to 2.7
12:55:05 PM: Attempting node version 'lts/*' from .nvmrc
12:55:05 PM: v16.17.1 is already installed.
12:55:05 PM: Now using node v16.17.1 (npm v8.15.0)
12:55:05 PM: Started restoring cached build plugins
12:55:05 PM: Finished restoring cached build plugins
12:55:06 PM: Attempting ruby version 2.7.2, read from environment
12:55:06 PM: Using ruby version 2.7.2
12:55:06 PM: Using PHP version 8.0
12:55:07 PM: No npm workspaces detected
12:55:07 PM: Started restoring cached node modules
12:55:07 PM: Finished restoring cached node modules
12:55:07 PM: Installing NPM modules using NPM version 8.15.0
12:55:07 PM: npm WARN config tmp This setting is no longer used.  npm stores temporary files in a special
12:55:07 PM: npm WARN config location in the cache, and they are managed by
12:55:07 PM: npm WARN config     [`cacache`](http://npm.im/cacache).
12:55:07 PM: npm WARN config tmp This setting is no longer used.  npm stores temporary files in a special
12:55:07 PM: npm WARN config location in the cache, and they are managed by
12:55:07 PM: npm WARN config     [`cacache`](http://npm.im/cacache).
12:55:12 PM: added 519 packages, and audited 520 packages in 5s
12:55:12 PM: 209 packages are looking for funding
12:55:12 PM:   run `npm fund` for details
12:55:12 PM: found 0 vulnerabilities
12:55:12 PM: NPM modules installed
12:55:12 PM: npm WARN config tmp This setting is no longer used.  npm stores temporary files in a special
12:55:12 PM: npm WARN config location in the cache, and they are managed by
12:55:12 PM: npm WARN config     [`cacache`](http://npm.im/cacache).
12:55:12 PM: Started restoring cached go cache
12:55:12 PM: Finished restoring cached go cache
12:55:12 PM: Installing Go version 1.16.5 (requested 1.16.5)
12:55:16 PM: unset GOOS;
12:55:16 PM: unset GOARCH;
12:55:16 PM: export GOROOT='/opt/buildhome/.gimme/versions/go1.16.5.linux.amd64';
12:55:16 PM: export PATH="/opt/buildhome/.gimme/versions/go1.16.5.linux.amd64/bin:${PATH}";
12:55:16 PM: go version >&2;
12:55:16 PM: export GIMME_ENV="/opt/buildhome/.gimme/env/go1.16.5.linux.amd64.env"
12:55:16 PM: go version go1.16.5 linux/amd64
12:55:16 PM: Installing missing commands
12:55:16 PM: Verify run directory
12:55:17 PM: ​
12:55:17 PM: ────────────────────────────────────────────────────────────────
12:55:17 PM:   Netlify Build                                                 
12:55:17 PM: ────────────────────────────────────────────────────────────────
12:55:17 PM: ​
12:55:17 PM: ❯ Version
12:55:17 PM:   @netlify/build 27.20.1
12:55:17 PM: ​
12:55:17 PM: ❯ Flags
12:55:17 PM:   baseRelDir: true
12:55:17 PM:   buildId: 63400571924b813fab5b83f8
12:55:17 PM:   deployId: 63400571924b813fab5b83fa
12:55:17 PM: ​
12:55:17 PM: ❯ Current directory
12:55:17 PM:   /opt/build/repo/frontend
12:55:17 PM: ​
12:55:17 PM: ❯ Config file
12:55:17 PM:   /opt/build/repo/frontend/netlify.toml
12:55:17 PM: ​
12:55:17 PM: ❯ Context
12:55:17 PM:   branch-deploy
12:55:17 PM: ​
12:55:17 PM: ────────────────────────────────────────────────────────────────
12:55:17 PM:   1. build.command from netlify.toml                            
12:55:17 PM: ────────────────────────────────────────────────────────────────
12:55:17 PM: ​
12:55:17 PM: $ npm run build
12:55:17 PM: npm WARN config tmp This setting is no longer used.  npm stores temporary files in a special
12:55:17 PM: npm WARN config location in the cache, and they are managed by
12:55:17 PM: npm WARN config     [`cacache`](http://npm.im/cacache).
12:55:17 PM: > @comvation/website-frontend@0.1.0 build
12:55:17 PM: > astro build
12:55:19 PM: 10:55:19 AM [build] output target: static
12:55:19 PM: 10:55:19 AM [build] Collecting build info...
12:55:19 PM: 10:55:19 AM [build] Completed in 374ms.
12:55:19 PM: 10:55:19 AM [build] Building static entrypoints...
12:55:25 PM: 10:55:25 AM [build] Completed in 5.78s.
12:55:25 PM: 
12:55:25 PM:  building client 
12:55:26 PM: Completed in 1.87s.
12:55:26 PM: 
12:55:26 PM: 
12:55:26 PM:  generating static routes 
12:55:26 PM: ▶ src/pages/index.astro
12:55:26 PM:   └─ /index.html (+17ms)
...
12:55:27 PM: Completed in 296ms.
12:55:27 PM: 
12:55:27 PM: @astrojs/sitemap: `sitemap-index.xml` is created.
12:55:27 PM: 10:55:27 AM [build] 45 page(s) built in 8.34s
12:55:27 PM: 10:55:27 AM [build] Complete!
12:55:27 PM: ​
12:55:27 PM: (build.command completed in 9.7s)
12:55:27 PM: ​
12:55:27 PM: ────────────────────────────────────────────────────────────────
12:55:27 PM:   2. Deploy site                                                
12:55:27 PM: ────────────────────────────────────────────────────────────────
12:55:27 PM: ​
12:55:27 PM: Starting to deploy site from 'frontend/dist'
12:55:27 PM: Creating deploy tree 
12:55:27 PM: Creating deploy upload records
12:55:27 PM: 1 new files to upload
12:55:27 PM: 0 new functions to upload
12:55:27 PM: Site deploy was successfully initiated
12:55:27 PM: ​
12:55:27 PM: (Deploy site completed in 482ms)
12:55:27 PM: ​
12:55:27 PM: ────────────────────────────────────────────────────────────────
12:55:27 PM:   Netlify Build Complete                                        
12:55:27 PM: ────────────────────────────────────────────────────────────────
12:55:27 PM: ​
12:55:27 PM: (Netlify Build completed in 10.2s)
12:55:27 PM: Starting post processing
12:55:28 PM: Caching artifacts
12:55:28 PM: Started saving node modules
12:55:28 PM: Finished saving node modules
12:55:28 PM: Started saving build plugins
12:55:28 PM: Finished saving build plugins
12:55:28 PM: Started saving pip cache
12:55:28 PM: Finished saving pip cache
12:55:28 PM: Started saving emacs cask dependencies
12:55:28 PM: Post processing - HTML
12:55:28 PM: Finished saving emacs cask dependencies
12:55:28 PM: Started saving maven dependencies
12:55:28 PM: Finished saving maven dependencies
12:55:28 PM: Started saving boot dependencies
12:55:28 PM: Finished saving boot dependencies
12:55:28 PM: Started saving rust rustup cache
12:55:28 PM: Finished saving rust rustup cache
12:55:28 PM: Started saving go dependencies
12:55:28 PM: Finished saving go dependencies
12:55:28 PM: Processing form - contact-form
12:55:28 PM: Detected form fields: - firstname-lastname - customer-need - myextra-field - email - phone - estimated-budget - message
12:55:28 PM: Post processing - header rules
12:55:28 PM: Post processing - redirect rules
12:55:28 PM: Post processing done
12:55:29 PM: Build script success
12:55:30 PM: Uploading Cache of size 341.2MB
12:55:32 PM: Site is live ✨
12:55:32 PM: Finished processing build request in 48.893387198s

Hi @olim, I have navigated your website and your styles seem to be working well from my end.

I’m assuming what you mean by style loading order is what style will take precedence if two rules have the same specificity.

From the Official Astro Documentation it states that…

If two rules have the same specificity, then the order of appearance is evaluated, and the last rule’s value will take precedence

You can learn more about the above in the Official Astro Documentation at the link below.

If that’s not the case can you explain further in details what you mean by style loading order.

You can also create an issue regarding your question on the Astro Official GitHub Page

Hope this helps.
Nice website by the way.

Thanks.

Hi @clarnx

thanks for your reply!

Exactly this is what I meant, what style will take precedence if two rules have the same specificity.

It is actually only about the h2 title “Unsere Kund:innen”, which has another style definition as when I do a local Astro build. So on the Netlify website the font size is smaller that actually defined and it works correctly on the local machine if I do a local “npm run build” and “npm run preview” build.

As I understand the Astro docs and the new Astro 1.4 blog, the component styles come after the global styles: “… In 1.4.0, styles you write in Astro components will come after global styles imported…”.

So the title " Unsere Kund:innen" (an h2 element) in https://netlify-astro-style-order-issue-test--comvation-website.netlify.app/ should have a bigger font size according to our component code:

HTML code:

  ... <h2 class="m-0 p-0 pt-7">{title}</h2> ...

Style:

h2 {
  font-size: 3.1rem;
  ...
}

and in the global.scss file we have a style def like this:

h2 {
  font-size: 2rem; 
  ...
}

So according to my understanding the global style import should come before the component styles so therefore the bigger font size will take then precendence. On a local build this behaviour is correct, but after deploying to Netlify somehow this style order is not present.

Our current workaround is, that we still add some additional css class “.section-title” which the has a higher precedence because of the higher specificity.

So in our component code we have:

  .section-title {
    h2 {
      font-size: 3.1rem;
      ...
    }
  }

which results to proper styling according to our requirements, can be viewed here: https://www.comvation.com/

That’s why I think it is most probably a Netlify issue, because the local Astro build handles it correctly as far as I see.

I hope it is a bit more clear now :slight_smile:

Hi @olim,

Thank you for the clear explanation. I can see the problem happening. As soon as I change your scoped style’s order to be after the global style’s one in the dev tools, it works.

However, I cannot say much as to why it’s happening. Could you share your repo?

Hi @hrishikesh,

thanks for checking and support!

I have created a separate test repo here: GitHub - olimination/netlify-astro-style-test

and you can check the current Netlify deployment here: https://illustrious-hotteok-b7f9af.netlify.app/ (I have created a new Site deploy for testing purposes, I thought maybe it has some CDN caching issues and with a new site deploy it would work…but nope :)).

There you see that the h2 element “Kund:innen” has the wrong font size style.

If you build the project locally with “npm run build” and check it locally on localhost:3000 after “npm run preview” you can see the correct h2 element styling.

While Hrishikesh may be able to tell what is going on with your repo, our usual debugging guidance is to help you debug.

Something I would suggest you try before he is back (this is his weekend as he works Weds-Sun), is this portion of our site build debugging support guide:

In it, I talk about how to ensure that Netlify is using the same versions of all of the software that you are, since it is frequently the case that a different version of node, npm, yarn, etc can create vastly (or subtly) different build output that can be pretty hard to debug.

Could you run through those steps for us in the meantime, to ensure that our versions match what you use locally to create a correct build?

Thanks a lot @fool for this Debugging guide.

I currently have checked the build tool versions Node, npm, etc. this looks good so far, we use a .nvmrc which gets read from Netlify’s build.

The local debugging/running a Netlify build using your containers is still a todo on my list.

1 Like

While I agree, the behaviour is strange, I also think this is a problem with how Astro is handling scoped CSS. For example, they say this:

When conflicting CSS rules apply to the same element, browsers first use specificity and then order of appearance to determine which value to show.

and that’s true. However, for some reason, Astro uses :where() selector for scoped styles. According to MDN:

The specificity-adjustment pseudo-class :where() always has its specificity replaced with zero, 0-0-0 . It enables making CSS selectors very specific in what element is targeted without any increase to specificity.

So, not sure why Astro chose to go with :where().

For example, Vue uses attribute selector as scoped styles, which automatically gets higher preference.

If Astro had used a similar approach, the order of CSS file would not have mattered. I’m sure they have their reasons (as it’s being developed by much better devs than me - that is, if at all I decide to self-proclaim myself as a dev).

In any case, I can confirm this is not a Netlify problem. I tried to build this site on macOS first, and it worked fine. However, when I built this site on an Ubuntu machine, I faced the same issue that you’re seeing on Netlify. This would indicate that, Astro is creating this problem when the OS used to build this site is Ubuntu - which is what Netlify uses too, and thus the problem.

I think you should open a bug report for Astro to fix this.

Thanks a lot @hrishikesh for your findings! Makes very sense. I still could not yet test it out, but I still have it on my todo list :). But thank you very much for your analysis. I will check this further and will probably open an issue for the Astro project. Me myself I use Manjaro Linux, that’s why probably I could not reproduce the issue on my local machine.