TIL about CSS Modules
POSTED ON:
TAGS: css modules javascript
One of the challenges with CSS is that the cascading features of CSS can make it tricky to manage.
One strategy to avoid it is to use CSS Modules, where you define your markup in a JS file instead. It's not a official spec or anything; it's a build strategy.
This approach is designed to fix the problem of the global scope in CSS. With CSS Modules, a build tool changes class names and selectors to be locally scoped (i.e. kinda like namespaced).
Vanilla CSS:
<style>
.title {
background-color: red;
}
</style>
<h1 class="title">An example heading</h1>
CSS Modules:
// the file's name is `index.js`
import styles from "./styles.css";
element.innerHTML =
`<h1 class="${styles.title}">
An example heading
</h1>`;
Then, using a compiler like Webpack, the following steps would happen:
-
The compiler would search through that styles.css file that we’ve imported,
-
Look through the JavaScript we’ve written and make the .title class accessible via styles.title.
-
Create new, separate HTML and CSS files, with a new string of characters replacing both the HTML class and the CSS selector class.
// index.js becomes two files:
// index.css
._styles__title_309571057 {
background-color: red;
}
// index.html
<h1 class="_styles__title_309571057">
An example heading
</h1>
The classes are dynamically generated, unique, and mapped to the correct styles.
JS Frameworks #
Using CSS Modules in React:
via https://glenmaddern.com/articles/css-modules
/* components/submit-button.jsx */
import { Component } from 'react';
import styles from './submit-button.css';
export default class SubmitButton extends Component {
render() {
let className, text = "Submit"
if (this.props.store.submissionInProgress) {
className = styles.inProgress
text = "Processing..."
} else if (this.props.store.errorOccurred) {
className = styles.error
} else if (!this.props.form.valid) {
className = styles.disabled
} else {
className = styles.normal
}
return <button className={className}>{text}</button>
}
}
Using CSS Modules in Vue:
via https://vuejs.org/api/sfc-css-features.html#css-modules
<template>
<p :class="$style.red">This should be red</p>
</template>
<style module>
.red {
color: red;
}
</style>
It's not the same as Scoped CSS, but the outcome is pretty similar.
https://vuejs.org/api/sfc-css-features.html#scoped-css
<style scoped>
.example {
color: red;
}
</style>
<template>
<div class="example">hi</div>
</template>
The composes
keyword #
.serif-font {
font-family: Georgia, serif;
}
.display {
composes: serif-font; // this
font-size: 30px;
line-height: 35px;
}
The CSS Module:
import type from "./type.css";
element.innerHTML =
`<h1 class="${type.display}">
This is a heading
</h1>`;
The result:
<h1 class="_type__display_0980340 _type__serif_404840">
Heading title
</h1>
via CSS Modules
Related TILs
Tagged: css