⚠️ Notice: This project is not actively maintained. Reach out to @keenanpayne or @jaiheravi if you would like to chat about it ✌🏻
Concise CSS is a lightweight CSS framework and preprocessor. It gives you a solid foundation without the bloat. It has three parts, and you can use only the ones you need:
- The preprocessor: a CLI and a PostCSS plugin that compile
.pcssfiles. They add imports, a type scale, named breakpoints and inline media queries on top of modern CSS (nesting, range queries,rlhunits). - The styles:
core(base styles for HTML elements),ui(a small kit of components) andutils(helper classes). - Precompiled CSS for projects that don't need a build step.
Documentation: concisecss.com
npm install -D concise.css
Node.js 22.22 or newer is required.
Create a main.pcss file:
@import 'concise.css'; /* core + ui + utils */
/* Your styles */
.hero {
margin-bottom: 2rlh; /* two lines of the vertical rhythm (native CSS) */
font-size: 5; /* step 5 of the type scale */
padding: 1rlh ?if media (--medium);
}Compile it:
npx concise compile main.pcss main.css
Add -w (--watch) to recompile when the file, or any file it imports, changes. To run it from package.json:
"scripts": {
"css": "concise compile src/main.pcss dist/main.css",
"css:watch": "concise compile src/main.pcss dist/main.css -w"
}Import everything or only the parts you need:
@import 'concise.css'; /* everything */
@import 'concise.css/core'; /* base styles for HTML elements */
@import 'concise.css/ui'; /* components: see ui/README.md */
@import 'concise.css/utils'; /* helper classes: see utils/README.md */
@import 'concise.css/utils/margins-responsive'; /* opt-in responsive margin classes */
@import 'concise.css/core/settings.pcss'; /* a single file */Every part imports the settings it needs, and each file is only included once.
All settings are custom properties and custom media queries in core/settings.pcss: colors, fonts, spacing, the type ratio and the breakpoints. Override them after importing Concise:
@import 'concise.css';
@custom-media --medium (width >= 900px);
:root {
--color-base-primary: rebeccapurple;
--type-ratio: 1.25;
line-height: 1.6;
}Colors, fonts, spacing and the type ratio are regular custom properties, so they can also change at runtime, even per component. Only the breakpoints are resolved when compiling. Vertical rhythm uses the native rlh unit, so it follows the line-height of :root.
.pcss files are CSS with a few additions. Any valid CSS is valid .pcss, and native features such as nesting, media query ranges and the rlh unit are left as written.
| Feature | Write | Get |
|---|---|---|
| Imports | @import 'partials/header'; |
Inlines partials/header.pcss, _header.pcss, header.css or header/index.pcss. Bare names are looked up next to the file first, then in node_modules |
| Type scale | font-size: 4 |
calc(pow(var(--type-ratio), 2) * 1rem): step 2 is 1rem, and each step multiplies by --type-ratio |
| Named breakpoints | @media (--medium) {} |
@media (width >= 768px) {} |
| Inline queries | padding: 0 ?if media (--small); |
A @media block placed right after the rule |
| Query blocks | .a { ?if media (--small) { … } } |
Same, for several declarations |
Breakpoints defined in the settings: --extra-small, --small, --medium, --large, --extra-large, --only-small, --only-medium and --only-large.
Every release ships compiled stylesheets in dist/: concise.css, core.css, ui.css and utils.css, each with a .min.css version. They can be used from a CDN:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/concise.css@5/dist/concise.min.css">Concise is also a PostCSS plugin, so it works with any tool that runs PostCSS:
// postcss.config.js
import concise from 'concise.css'
export default { plugins: [concise()] }// postcss.config.cjs
module.exports = { plugins: [require('concise.css')()] }Options, all optional:
concise({
import: { /* postcss-import options */ }
})The compiled CSS targets current browsers and uses native nesting, media query range syntax, the rlh unit, pow() and, in the UI kit, relative color syntax. No vendor prefixes are added. To support older browsers, add plugins such as postcss-nested, postcss-media-minmax or autoprefixer after concise() in your own PostCSS config.
- Sass →
.pcss: rename your.scssfiles to.pcss, then replace Sass features:getColor(base, primary)→var(--color-base-primary)$spacing-m→var(--spacing-m)typeScale(3)→font-size: 3// comments→/* comments */- loops and mixins → plain CSS
&-suffix/&_suffixselector concatenation → full class names (native nesting can't build selectors from parts)
lhunit →rlh: Concise'slhunit was the root line height, which is nativerlh. Replace1.5lhwith1.5rlh. Nativelhis the element's own line height.- Removed options:
lh,typeScaleandautoprefixer. Add Autoprefixer to your own PostCSS config if you need it. - One package:
concise-ui,concise-utilsand@concisecss/coreare now part ofconcise.css. Importconcise.css/ui,concise.css/utilsandconcise.css/coreinstead. - The grid from v4 core is not part of v5. Use CSS grid or flexbox.
- Responsive margins are no longer controlled by
$responsive-margins. Importconcise.css/utils/margins-responsiveinstead.
npm install
npm test # fixtures, plugin, CLI and stylesheet snapshot tests
npm run test:update # accept stylesheet changes after reviewing the snapshot diff
npm run build # write dist/
To check the styles visually, run npm run build and open playground/core.html or playground/ui.html.
See CONTRIBUTING.md for how to contribute.
You can keep up to date with the changes on our releases page.
Code released under the MIT license. Documentation released under Creative Commons.