Features
Material Design 3 tokens
Color, typography, shape and elevation tokens, with the whole color scheme generated from one source color.
Light and dark themes
Set theme="light" or theme="dark" on the root element, or use auto to follow the operating system.
Semantic HTML
The element is the component: an article is a card and a label wrapping a checkbox is a switch.
Accessible components
Interactive components manage focus, keyboard navigation and ARIA state for you.
No build step required
Link one stylesheet and one script, or import only the components you use from the ES module and Sass entries.
Charts included
Line, column, bar, pie, radar and heatmap charts, each with an accessible data table.
Code demo
This card, its filter chips and its switch are plain HTML. Switch the theme from the app bar to see the tokens change.
Trip settings
Weekend in the mountains
Every color here comes from theme tokens, so the card follows light and dark mode.
<article class="outlined">
<header>
<h4>Trip settings</h4>
<p class="subhead">Weekend in the mountains</p>
</header>
<p>Every color here comes from theme tokens, so the card follows light and dark mode.</p>
<p>
<input type="checkbox" class="chip-input" id="demo-hiking" checked>
<label class="chip" for="demo-hiking">
<span class="material-symbols" aria-hidden="true">check</span>
Hiking
</label>
<input type="checkbox" class="chip-input" id="demo-camping">
<label class="chip" for="demo-camping">
<span class="material-symbols" aria-hidden="true">check</span>
Camping
</label>
</p>
<label class="switch">
<input type="checkbox" checked>
Download offline maps
</label>
<div class="actions">
<button type="button" class="text">Cancel</button>
<button type="button" class="filled">Save</button>
</div>
</article>
Installation
Expressive comes in two forms. Pick the one that fits your
preference and experience.
The project is at version 0.16.0 and still growing, so the usual path is to build
from the repository.
Expressive
The standard version includes minified and unminified CSS and
JavaScript files.
Build the project, then copy the files from dist/. This option
needs little to no setup.
Use it if you are unfamiliar with Sass.
Sass
This version is the source SCSS in src/sass. It gives you more control over
which layers to include. It needs a Sass compiler.
From source
Clone the repository and build the compiled CSS and JavaScript:
npm install
npm run build
The compiled assets are written to dist/:
dist/
├── css/
│ ├── expressive.css
│ └── expressive.min.css
├── fonts/
├── js/
│ ├── expressive.cjs
│ ├── expressive.js
│ ├── expressive.min.js
│ ├── expressive.mjs
│ └── modular.mjs
└── types/
NPM
The package name is @expressivecss/expressive. It contains the source files and
the compiled CSS and JavaScript files.
npm install @expressivecss/expressive
Yarn
You can also add the package with yarn.
yarn add @expressivecss/expressive
Using a coding agent? AI agents covers the agent skills, the MCP server, and the plain-text docs.
Setup
Project structure
After building, copy the compiled files into your website's directory. It will look something like the tree below.
There are two sets of files. The
min files are compressed to reduce load times. Use the minified files
in production and the unminified files during development.
MyWebsite/
|--css/
| |--expressive.css
| |--expressive.min.css
|
|--fonts/
| |--material-symbols-outlined.woff2
|
|--js/
| |--expressive.js
| |--expressive.min.js
|
|--index.html
HTML setup
Next, link the files in your webpage, as in the example below. Load JavaScript files at the end of the body to reduce page load time.
<!DOCTYPE html>
<html lang="en" theme="light">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/expressive.min.css">
</head>
<body>
<script src="js/expressive.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', () => {
Expressive.AutoInit();
});
</script>
</body>
</html>
Initialize JavaScript
Call AutoInit() after the page has loaded so components such as navigation
rails, tooltips, and tabs start themselves. Importing the JavaScript does not call it for
you. The import does install shared document behaviors (forms, chips, cards, and a few
others). The browser bundle exposes the framework as the global Expressive
object.
AutoInit() scans document.body by default. Pass a container to limit
the scan, or add the
no-autoinit class to an element you want to initialize yourself.
Expressive.AutoInit();
Expressive.AutoInit(document.querySelector('#app'), {
Tooltip: { position: 'top' }
});
ES modules
Import the framework or individual components from the module build:
import { AutoInit, Tooltip } from './js/expressive.mjs';
AutoInit();
const element = document.querySelector('.custom-tooltip');
Tooltip.init(element, { position: 'top' });
Themes
Set the theme attribute on the root element.
light and dark lock the scheme.
auto, or no attribute at all, follows the OS.
<html lang="en" theme="auto">
document.documentElement.setAttribute('theme', 'dark');
Templates
Basic starter
Download this HTML file as index.html and put the framework's
dist/ directory beside it. It includes an app bar, responsive cards,
a tooltip, and a theme that follows your system settings. You do not need a bundler.
Download starter HTML Preview starter
From a built repository checkout, create a separate starter directory:
mkdir my-site
cp docs/public/starter.html my-site/index.html
cp -R dist my-site/dist
If you installed the npm package, copy its built assets instead:
cp -R node_modules/@expressivecss/expressive/dist my-site/dist
Keep the css/, js/, and fonts/ directories together.
my-site/
├── index.html
└── dist/
├── css/
├── js/
└── fonts/
Open my-site/index.html in your browser. Edit the title and content to start your project,
or copy the complete template below.
<!doctype html>
<html lang="en" theme="auto">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="A starter page for your ExpressiveCSS project.">
<title>My project</title>
<!-- Keep dist/fonts next to dist/css so the bundled fonts load. -->
<link rel="stylesheet" href="dist/css/expressive.min.css">
</head>
<body>
<header>
<nav aria-label="Main">
<h2>My project</h2>
<menu>
<li><a href="https://www.expressivecss.com/">Documentation</a></li>
</menu>
</nav>
</header>
<main class="container py-5">
<section aria-labelledby="welcome-title" class="mb-5">
<h1 id="welcome-title">Your project starts here</h1>
<p class="flow-text">Replace this content with your own. ExpressiveCSS handles the layout, typography, and theme.</p>
<a class="button filled tooltipped" href="https://www.expressivecss.com/"
data-tooltip="Read the setup guide and browse components.">Start building</a>
</section>
<!-- Full-width cards on phones, two columns from 600px. -->
<div class="row">
<div class="s12 m6">
<article class="outlined">
<h2>Your content</h2>
<p>Use this card for a feature, a project summary, or a next step.</p>
<div class="actions">
<a class="button outlined" href="https://www.expressivecss.com/grid.html">Explore layouts</a>
</div>
</article>
</div>
<div class="s12 m6">
<article class="outlined">
<h2>Make it yours</h2>
<p>The page follows your system theme. Set the root theme attribute to light or dark to choose a fixed scheme.</p>
<div class="actions">
<a class="button text" href="https://www.expressivecss.com/themes.html">Customize the theme</a>
</div>
</article>
</div>
</div>
</main>
<footer class="container py-3">
<p>My project</p>
</footer>
<script src="dist/js/expressive.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', () => {
Expressive.AutoInit();
});
</script>
</body>
</html>
Layout reference
These two pages show how Expressive structures content. You can copy the markup they use.
Grid
The 12-column CSS Grid, containers, offsets, and responsive layouts. Start here after you link the stylesheet.
Open GridHelpers
Alignment, visibility, spacing, truncation, and other single-purpose classes you will use on every page.
Open HelpersSmaller builds
Use the modular entry with a bundler to include selected JavaScript components. Initialize each component after its markup exists, and destroy instances when you remove the view.
import { Tabs } from '@expressivecss/expressive/modular';
const tabs = Tabs.init(document.querySelector('.tabs'));
This entry installs no document behaviors. Call each behavior your page needs once,
such as Forms.Init() or Dialogs.Init().
The root import keeps its existing initialization. AutoInit
is still available and includes the full component registry.
Select Sass partials with the custom entry. With Sass's Node package importer,
compile with sass --pkg-importer=node app.scss app.css.
@use "pkg:@expressivecss/expressive/scss/custom" with (
$components: ("icons-material-design", "tabs"),
$utilities: ()
);
Tokens and base styles stay included. Lists load in the order written.
null includes the full group, and () omits it.
Include supporting partials for the features you use. The default configuration
produces the same CSS as the full entry.
For FormSelect and Datepicker, select icons-material-design,
buttons, menu, forms, and
datepicker, in that order. Initialize both components explicitly.
To supply smaller icon fonts, set $expressive-include-fonts: false
and provide your own font faces, including text fonts. Your subset must include icons
from dynamic content and generated controls. Keep full fonts if icon names are unrestricted.
The README contains the initialization table, complete Sass recipes, and font declarations.
Sass setup
You only need this section if you chose the Sass sources.
Compiling Sass
Besides compiled CSS, the repository contains many .scss files with the
styles of individual layers
and components. Browsers cannot read Sass, so compile src/sass/expressive.scss
into a regular CSS file.
Then link the compiled file in your HTML page.
From the repository, the npm script does that for you:
npm run build:css
In another Sass project, use the framework's Sass entry point:
@use "@expressivecss/expressive/src/sass/expressive";
Inside this repository, the entry point is
src/sass/expressive.scss.
MyWebsite/
|--css/
| |--expressive.css <-- compiled from scss/expressive.scss
|
|--js/
| |--expressive.js
|
|--scss/
| |--expressive.scss
| |--abstracts/
| |--tokens/
| |--utilities/
| |--base/
| |--components/
|
|--index.html