CSS Modules
A CSS Module is a CSS file in which all class names and animation names are scoped locally by default.
The selector names are unique to avoid naming collision. They can then be imported as a JavaScript object.
Usage
CSS Modules can be enabled from the style editor menu.
Selectors added to the style editor (using any language e.g. CSS, SCSS, Less, etc.) are transformed to unique selectors. The transformed classes are then accessible in the script editor as a JSON object, and are injected into the HTML elements.
Example:
- Source CSS
- Compiled CSS
- JSON Object
- Source HTML
- Compiled HTML
:global .page {
padding: 20px;
}
.text {
color: black;
font-family: sans-serif;
}
.small-text {
composes: text;
font-size: 20px;
}
.large-text {
composes: text;
font-size: 40px;
}
.large-text:hover {
color: red;
}
.title {
composes: large-text;
color: green;
}
.page {
padding: 20px;
}
._text_1ygro_9 {
color: black;
font-family: sans-serif;
}
._small-text_1ygro_19 {
font-size: 20px;
}
._large-text_1ygro_29 {
font-size: 40px;
}
._large-text_1ygro_29:hover {
color: red;
}
._title_1ygro_47 {
color: green;
}
{
"text": "_text_1ygro_9",
"small-text": "_small-text_1ygro_19 _text_1ygro_9",
"large-text": "_large-text_1ygro_29 _text_1ygro_9",
"title": "_title_1ygro_47 _large-text_1ygro_29 _text_1ygro_9",
"smallText": "_small-text_1ygro_19 _text_1ygro_9",
"largeText": "_large-text_1ygro_29 _text_1ygro_9"
}
<div class="page">
<h1>Page Title</h1>
<p class="small-text">
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Dolore earum blanditiis quidem non
beatae ipsam autem maiores ut et delectus unde repudiandae, repellendus aut. Aspernatur
similique facere facilis minima tempora.
</p>
</div>
<div class="page">
<h1>Page Title</h1>
<p class="small-text _small-text_1ygro_19 _text_1ygro_9">
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Dolore earum blanditiis quidem non
beatae ipsam autem maiores ut et delectus unde repudiandae, repellendus aut. Aspernatur
similique facere facilis minima tempora.
</p>
</div>
In the script editor, the JSON object representing the transformed classes can be imported from the relative URLs './style.module.css'
or './styles.module.css'
.
Default, named and namespace imports are supported. Class names are also available in camelCase (e.g .large-text
becomes largeText
). This can be changed by setting localsConvention
in custom settings.
Example:
In script editor (using JS in this case):
import classes from './style.module.css';
import { smallText } from './styles.module.css';
import * as allClasses from './styles.module.css';
console.log(classes.title);
console.log(smallText);
console.log(allClasses.largeText);
console.log(allClasses['large-text']);
For full example, see example usage below.
CSS Modules has to be enabled (from style editor menu), to be able to import classes in the script editor.
Importing a URL that does not include .module
(e.g. ./style.css
) gets the processed CSS string as the module's default export.
The extension of the style editor language can also be used, in addition to .css
. For example, when using SCSS, importing from any of the following URLs is the same:
./style.module.css
./styles.module.css
./style.module.scss
./styles.module.scss
Language Info
Name
cssmodules
Type
Processor
Editor
style
Compiler
The CSS Modules processor is provided using postcss-modules as a PostCSS plugin.
Version
postcss-modules
: v6.0.0
Custom Settings
Custom settings added to the property cssmodules
are passed as a JSON object to the postcss-modules
plugin during compile. Please check the documentation for full reference.
In addition, the following settings are available:
addClassesToHTML
Type: boolean
. Default: true
.
The generated classes are injected into the HTML elements, so the styles are applied without having to assign them using JavaScript.
removeOriginalClasses
Type: boolean
. Default: false
.
When enabled, the original classes are removed from HTML, keeping only the generated classes. Only applies if addClassesToHTML
is enabled.
Please note that custom settings should be valid JSON (i.e. functions are not allowed).
Example:
{
"cssmodules": {
"exportGlobals": true,
"localsConvention": "camelCaseOnly",
"addClassesToHTML": false
}
}
Limitations
Currently, loading external sources in composes
is not supported.
.title {
composes: title from 'https://example.com/styles.css';
}
If you get this working, please create a pull request.
Example Usage
show code
import { createPlayground } from 'livecodes';
const options = {
"params": {
"activeEditor": "style",
"html": "<div class=\"page\">\n <h1>Page Title</h1>\n <p class=\"small-text\">Lorem, ipsum dolor sit amet consectetur adipisicing elit. Dolore earum blanditiis quidem non beatae ipsam autem maiores ut et delectus unde repudiandae, repellendus aut. Aspernatur similique facere facilis minima tempora.</p>\n</div>\n",
"css": ":global .page {\n padding: 20px;\n}\n\n.text {\n color: black;\n font-family: sans-serif;\n}\n\n.small-text {\n composes: text;\n font-size: 20px;\n}\n\n.large-text {\n composes: text;\n font-size: 40px;\n}\n\n.large-text:hover {\n color: red;\n}\n\n.title {\n composes: large-text;\n color: green;\n}\n",
"js": "import classes from './style.module.css';\n\ndocument.querySelector('h1').className = classes.title;\nconsole.log(classes);\n",
"processors": "cssmodules",
"compiled": "open"
}
};
createPlayground('#container', options);
import { createPlayground, type EmbedOptions } from 'livecodes';
const options: EmbedOptions = {
"params": {
"activeEditor": "style",
"html": "<div class=\"page\">\n <h1>Page Title</h1>\n <p class=\"small-text\">Lorem, ipsum dolor sit amet consectetur adipisicing elit. Dolore earum blanditiis quidem non beatae ipsam autem maiores ut et delectus unde repudiandae, repellendus aut. Aspernatur similique facere facilis minima tempora.</p>\n</div>\n",
"css": ":global .page {\n padding: 20px;\n}\n\n.text {\n color: black;\n font-family: sans-serif;\n}\n\n.small-text {\n composes: text;\n font-size: 20px;\n}\n\n.large-text {\n composes: text;\n font-size: 40px;\n}\n\n.large-text:hover {\n color: red;\n}\n\n.title {\n composes: large-text;\n color: green;\n}\n",
"js": "import classes from './style.module.css';\n\ndocument.querySelector('h1').className = classes.title;\nconsole.log(classes);\n",
"processors": "cssmodules",
"compiled": "open"
}
};
createPlayground('#container', options);
import LiveCodes from 'livecodes/react';
export default function App() {
const options = {
"params": {
"activeEditor": "style",
"html": "<div class=\"page\">\n <h1>Page Title</h1>\n <p class=\"small-text\">Lorem, ipsum dolor sit amet consectetur adipisicing elit. Dolore earum blanditiis quidem non beatae ipsam autem maiores ut et delectus unde repudiandae, repellendus aut. Aspernatur similique facere facilis minima tempora.</p>\n</div>\n",
"css": ":global .page {\n padding: 20px;\n}\n\n.text {\n color: black;\n font-family: sans-serif;\n}\n\n.small-text {\n composes: text;\n font-size: 20px;\n}\n\n.large-text {\n composes: text;\n font-size: 40px;\n}\n\n.large-text:hover {\n color: red;\n}\n\n.title {\n composes: large-text;\n color: green;\n}\n",
"js": "import classes from './style.module.css';\n\ndocument.querySelector('h1').className = classes.title;\nconsole.log(classes);\n",
"processors": "cssmodules",
"compiled": "open"
}
};
return (<LiveCodes {...options}></LiveCodes>);
}
<script setup>
import LiveCodes from "livecodes/vue";
const options = {
"params": {
"activeEditor": "style",
"html": "<div class=\"page\">\n <h1>Page Title</h1>\n <p class=\"small-text\">Lorem, ipsum dolor sit amet consectetur adipisicing elit. Dolore earum blanditiis quidem non beatae ipsam autem maiores ut et delectus unde repudiandae, repellendus aut. Aspernatur similique facere facilis minima tempora.</p>\n</div>\n",
"css": ":global .page {\n padding: 20px;\n}\n\n.text {\n color: black;\n font-family: sans-serif;\n}\n\n.small-text {\n composes: text;\n font-size: 20px;\n}\n\n.large-text {\n composes: text;\n font-size: 40px;\n}\n\n.large-text:hover {\n color: red;\n}\n\n.title {\n composes: large-text;\n color: green;\n}\n",
"js": "import classes from './style.module.css';\n\ndocument.querySelector('h1').className = classes.title;\nconsole.log(classes);\n",
"processors": "cssmodules",
"compiled": "open"
}
};
</script>
<template>
<LiveCodes v-bind="options" />
</template>
<script>
import { onMount } from 'svelte';
import { createPlayground } from 'livecodes';
let options = $state({
"params": {
"activeEditor": "style",
"html": "<div class=\"page\">\n <h1>Page Title</h1>\n <p class=\"small-text\">Lorem, ipsum dolor sit amet consectetur adipisicing elit. Dolore earum blanditiis quidem non beatae ipsam autem maiores ut et delectus unde repudiandae, repellendus aut. Aspernatur similique facere facilis minima tempora.</p>\n</div>\n",
"css": ":global .page {\n padding: 20px;\n}\n\n.text {\n color: black;\n font-family: sans-serif;\n}\n\n.small-text {\n composes: text;\n font-size: 20px;\n}\n\n.large-text {\n composes: text;\n font-size: 40px;\n}\n\n.large-text:hover {\n color: red;\n}\n\n.title {\n composes: large-text;\n color: green;\n}\n",
"js": "import classes from './style.module.css';\n\ndocument.querySelector('h1').className = classes.title;\nconsole.log(classes);\n",
"processors": "cssmodules",
"compiled": "open"
}
});
let container = $state(null);
onMount(() => {
createPlayground(container, options);
});
</script>
<div bind:this="{container}"></div>
Links