What is the benefit of using :local in CSS files?

Viewed 141

I've been learning about using CSS in React and have come across the idea of CSS modules, as part of that I came across this article https://blog.fearcat.in/a?ID=00550-af5ece9b-eb49-4e13-8711-26e00c48c84e which discusses using :global and :local in CSS files but it mentions this at one point

:local(.className) , Which is equivalent to .className

So I understand from this article that using :global would put that CSS rule at the global level, but why use :local if it is equivalent to just having .className? there doesn't seem to be any functional difference.

2 Answers

By default, the CSS in CSS modules is local. But when you use :global qualifier/block, and inside that, if you want to switch back to local CSS, then you should it.

Imagine you are using global mode for CSS modules using css-loader options:

module: {
  rules: [
    {
      test: /\.css$/i,
      use: [
        MiniCssExtractPlugin.loader,
        {
          loader: 'css-loader',
          options: {
            // THIS IS IMPORTANT
            modules: 'global'
          }
        }
      ],
    }
  ]
}

For above configuration, consider following example:

.abc { color: red; }

:global(.abc) { color: green; }

:local .xyz { color: blue; }

:local(.xyz) .pqr { color: yellow; }

.abc :local .xyz .pqr { color: cyan; }

It would be compiled into following CSS.

/* Since it is global model for CSS modules, classname is not hashed */
.abc { color: red; }

/* .global(.abc) has no effect here */
.abc { color: green; }

/* :local .xyz means anything after :local will be hashed */
.dkzEiLgPjIar3vTOyiHv { color: blue; }

/* .local(.xyz) .pqr means only .xyz is hashed */
.dkzEiLgPjIar3vTOyiHv .pqr { color: yellow; }

/* Everything after the :local is hashed i.e. both .xyz and .pqr */
.abc .dkzEiLgPjIar3vTOyiHv .k3SKPTpkzRcircxhU4Dd { color: cyan; }

The difference between :local and :local(selector) is subtle. The former is aggressive (hashed selector after it) and latter is lenient. The same but inverse logic applies if I am using CSS Scope as local i.e. modules: true or modules: 'local'.

Now to your question, why would I use :local inside :global is when I have some component whose styles should be changed when it is inside some or top level component. Imagine, a .text should be 18px in size when it it is inside the .blogArticle. Otherwise this component should render by default as 14px:

:local .text { font-size: 14px; }
.blogArticle :local(.text) { font-size: 18px ;}

But in general, you are right. You would rarely need to put local inside global. The only reason you would be doing that is some legacy complex CSS that you are migrating to newer codebase and want to keep related blocks of CSS closer together for better readability. Last but not least, consider deep nested legacy CSS like this:

.abc :local .xyz .pqr :global(.def) {
  color: cyan;
}

I start global, then switch to :local and then again to :global(.def). But needing to do this is a good case of anti-pattern/code-smell.

There is a difference when you will have the same className in multiple components. For example you have the compoment A with <div className={classes.wrapper}> and then you have Component B with <div className={classes.wrapper}. With normal css the if the attributes in css file of those "wrapper" class will be different will overide the first one by the last one. Is like blocked scoped in your component and dont "lives" away from the component. And of course you can add every other attribute in global.css file that will occur in the whole project

.wrapper{                //component A
  display:flex;
  flex-direction:column;
}

.wrapper {              //component B
  display:flex;
  flex-direction:column;
  width:60%;
}

With normal css the last attributes will overide the first .wrapper so with modules is 100% not the same style in your div.

Related