🎨 Using global class selectors in CSS ModulesMay 14, 2021TIL 201 words

This site is written in Gatsby, and uses CSS Modules. If you were to inspect element on this site, you’d find CSS like PostContent-module--markdown-body--adE4E. This is the magic of CSS Modules. It adds arbitrary class names during build to avoid style collisions between components in a page.

CSS Modules are simply CSS files with a *.module.css extension.

// PostContent.module.css
.markdown-body a {
	color: var(--color-link);
	text-decoration: none;
}
.markdown-body a:hover {
	text-decoration: underline;
}
.markdown-body a.footnote-ref{
	background-color: lighten(#61afef, 25%);
	border-radius: 3px;
}	

And to use it in a Component, we import it like any other JS module.

import React from 'react';
import { markdownBody } from './PostContent.module.scss';import './Prism.css';
const PostContent = ({ post }) => {
	return (
		<article className={markdownBody}>
			<section dangerouslySetInnerHTML={{ __html: post }} itemProp='articleBody' />
		</article>
	);
};

export default PostContent;

Now the issue was, the Markdown classes were handled by gatsby-transformer-remark. I had to target a specific class, .footnote-ref to add a background to it. Initial code was, .markdown-body a.footnote-ref. But when I inspected the footnote element, because the CSS was declared in a module file, the class name ended up becoming .PostContent-module--markdown-body--adE4E a.PostContent-module--footnote-ref--1To04. This CSS was not able to target the element, because the element had a classname of .footnote-ref.

Took me a while, but I found the solution in CSS Loader README.

// Original CSS
:local(.className) {
  background: red;
}
:local .className {
  color: green;
}
:local(.className .subClass) {
  color: green;
}
:local .className .subClass :global(.global-class-name) {  color: blue;
}

By using :global() selector, we can keep the CSS class as it is, hence the name global selector.

// Compiled CSS
._23_aKvs-b8bW2Vg3fwHozO {
  background: red;
}
._23_aKvs-b8bW2Vg3fwHozO {
  color: green;
}
._23_aKvs-b8bW2Vg3fwHozO ._13LGdX8RMStbBE9w-t0gZ1 {
  color: green;
}
._23_aKvs-b8bW2Vg3fwHozO ._13LGdX8RMStbBE9w-t0gZ1 .global-class-name {  color: blue;
}

This is exactly what I wanted. So now to change my css,

// PostContent.module.css
.markdown-body a {
	color: var(--color-link);
	text-decoration: none;
}
.markdown-body a:hover {
	text-decoration: underline;
}
.markdown-body a:global(.footnote-ref){	background-color: lighten(#61afef, 25%);
	border-radius: 3px;
}	

And et voilà, the CSS is .PostContent-module--markdown-body--adE4E a.footnote-ref. You can checkout the Footnote Element style here.

So TIL, about :global() and :local() selectors in CSS Modules.

Until next time! ✌🏽