react-helmet icon indicating copy to clipboard operation
react-helmet copied to clipboard

Order of stylesheets changing

Open Anahkiasen opened this issue 8 years ago • 4 comments

I'm passing two dynamic links to stylesheets to react-helmet like this:

const links = [
    {
        rel: "stylesheet",
        href: `/dist/stylesheets/themes/${someVariable}.css`
    },
    {
        rel: "stylesheet",
        href: "/dist/stylesheets/core.css"
    }
];

<Helmet links={links} />

On first and subsequent renders everything is correct:

<link rel="stylesheet" href="/dist/stylesheets/themes/dark.css" data-react-helmet="true">
<link rel="stylesheet" href="/dist/stylesheets/core.css" data-react-helmet="true">

However as soon as someVariable changes, and the head tags are recomputed, the order changes to this:

<link rel="stylesheet" href="/dist/stylesheets/core.css" data-react-helmet="true">
<link rel="stylesheet" href="/dist/stylesheets/themes/light.css" data-react-helmet="true">

Throwing the whole design away. Is there a way to enforce the order of link tags?

Anahkiasen avatar May 29 '16 13:05 Anahkiasen

@Anahkiasen Thanks for your interest in Helmet. You can set the order of the tags in your Helmet, but because of some checks we do for FOUC, the order will change as you've noticed. The checks we have in place make sure that only the required DOM changes are made and nothing more. So, in your case core.css will remain untouched, while the new light.css is added to the end of the document head.

We can look into the possibility of maintaining the order of the tags, but in the meantime, could you write the css in a way that let's the second file swap out to change the theme?

cwelch5 avatar Jun 01 '16 21:06 cwelch5

You can trick Helmet into thinking that the DOM has changed when it actually hasn't but adding a querystring that updates when you update someVariable. This way both link tags will be re-rendered.

    {
        rel: "stylesheet",
        href: `/dist/stylesheets/core.css?theme=${someVariable}`
    }

Wexcode avatar Feb 10 '20 21:02 Wexcode

<Helmet 
-  links={links} 
+  link={links}
/>

props link work, links does not!.

kopax avatar Nov 29 '20 19:11 kopax

I have tried the following approach and the order is maintained (using typescript here)

import { Helmet } from "react-helmet"
/**
 * Used to dynamically add custom client specific css
 */
export const buildClientCssHelmet = (baseUrl: string, resourceBasePath: string, clientCss?: Array<string>, commonResourceBasePath?: string, commonCss?: Array<string>) => {

    const mapCommonStyles = buildStyleMap(baseUrl, commonResourceBasePath, commonCss)
    const mapClientStyles = buildStyleMap(baseUrl, resourceBasePath, clientCss)

    /*NOTE: going with the idea of making changes in client specific css which should override the common css, here in the array the last element will have highest priority */
    const mergeStyles = [...mapCommonStyles, ...mapClientStyles]
    return <Helmet link={mergeStyles} />
}

const buildStyleMap = (baseUrl:string, path?:string, css ?: Array<string>) =>{
    if(css==undefined || path==undefined) return []
    return css.map(item => {
        return {
            rel: "stylesheet",
            type: "text/css",
            href: baseUrl.concat(path, item)
        }
    })
}

Usage:

Inside react component

{buildClientCssHelmet("http://localhost:3000", "/client1", ["client1.css"], "/common", ["common.css"])}

abitgen avatar Apr 16 '21 05:04 abitgen