Web開発
FCSS 2: CSSのように読めるユーティリティCSS
FCSS 2: Utility CSS that reads like CSS (github.com)
要約
FCSS2は、クラス名がCSSプロパティと値に対応するユーティリティCSSライブラリです。CSSの知識があればそのまま利用でき、フレームワークの有無を問わず機能します。クラス名はCSSの命名規則に沿っており、ホバーやブレークポイントなどのバリアントもクラス名に含まれます。ビルド時に未使用のクラスが削除されるため、ランタイムのオーバーヘッドはありません。
全文翻訳
FCSS Utility CSS that reads like CSS.
Install · Usage · Docs · npm
FCSSは、すべてのクラス名がCSSプロパティと値であるユーティリティCSSライブラリです。CSSを知っていれば、FCSSもすぐに使いこなせます。どんなフレームワークでも、あるいはフレームワークなしでも機能します。
<div class="display--flex align-items--center gap--16 padding--24">
<p class="color--blue font-size--16 font-weight--bold">Hello, FCSS</p>
</div>
1つのクラスは1つの宣言です:padding--24 は padding: 24px であり、それ以上の意味はありません。名前は実際のCSS名に準拠しており、例えば bg-blue ではなく background-color--blue となります。そのため、参照用のチートシートを開いておく必要はありません。ホバー、ARIA、ブレークポイントのバリアントもクラス名の一部です(例: color--red:hover, display--block:aria-expanded:true, md-display--none)。ランタイムは存在せず、ブラウザにはプレーンなCSSが提供され、ビルド時に使用しないクラスは削除されます。
Contents
Requirements
Installation:
Vite · Next.js · Astro · Angular · Other bundlers (PostCSS) · Plain HTML / CDN
Usage
CLI
Packages
Documentation
Requirements
You need
Notes
Node.js 20.19+ or Bun
Tested on Node.js 24 and Bun 1.4. Your framework may require a newer Node.js.
A package manager: npm, pnpm, yarn or bun
All four work. Examples show npm and bun; see the equivalents.
A bundler or build step (recommended)
To purge unused classes. Without one you can still use the CDN.
Supported frameworks: Vite 5 – 8, Next.js 14 – 16, Astro 7, Angular 17 – 22.
FCSS finds the classes you use by scanning HTML, JS/TS, JSX/TSX, Angular templates and .astro files. Vue (.vue) and Svelte (.svelte) files are not scanned yet, so a class used only there gets purged. Support is on the list.
Package manager equivalents
npm
pnpm
yarn
bun
npm install <pkg>
pnpm add <pkg>
yarn add <pkg>
bun add <pkg>
npm install -D <pkg>
pnpm add -D <pkg>
yarn add -D <pkg>
bun add -d <pkg>
npx fcss <command>
pnpm exec fcss …
yarn fcss …
bunx fcss …
npm run build
pnpm build
yarn build
bun run build
Installation
Every setup has two parts. @functionalcss/core is the CSS itself: every class in every state and breakpoint, about 28 MB. Then a purge step, usually a framework integration, cuts that down to the classes your source actually uses, which is typically a few KB. You want both. Nobody should ship 28 MB of CSS, however good the gzip ratio looks.
Platform
Install
Vite (React, Preact, Solid, vanilla JS/TS)
npm install @functionalcss/core + npm install -D @functionalcss/vite
Next.js
npm install @functionalcss/core @functionalcss/next
Astro
npm install @functionalcss/core @functionalcss/astro
Angular
ng add @functionalcss/angular
Other bundlers (PostCSS)
npm install @functionalcss/core + npm install -D @functionalcss/postcss
Plain HTML / CDN
Nothing for a <link> tag; @functionalcss/cli to purge
Vite (React, Preact, Solid, vanilla JS)
npm install @functionalcss/core
npm install -D @functionalcss/vite
# or with bun
bun add @functionalcss/core
bun add -d @functionalcss/vite
// vite.config.ts
import { defineConfig } from 'vite';
import { fcss } from '@functionalcss/vite';
export default defineConfig({
plugins: [fcss()],
});
// src/main.ts (your entry point)
import '@functionalcss/core/full.css';
vite dev serves every class; vite build purges to what src/**/*.{html,js,jsx,ts,tsx} uses. Scan other paths with fcss({ config: { content: ['index.html', 'src/**/*.tsx'] } }) or an fcss.config.ts.
Guide: React · package README.
Next.js
npm install @functionalcss/core @functionalcss/next
# or bun add @functionalcss/core @functionalcss/next
// next.config.ts
import { withFcss } from '@functionalcss/next';
export default withFcss({
// your Next.js config
});
// app/layout.tsx (App Router), or pages/_app.tsx (Pages Router)
import '@functionalcss/core/full.css';
Next.js 16 builds with Turbopack by default; FCSS purges through webpack. Use "build": "next build --webpack" in package.json. next dev needs no flag. Next.js 14 and 15 need no changes.
Guide: Next.js · package README.
Astro
npm install @functionalcss/core @functionalcss/astro
# or bun add @functionalcss/core @functionalcss/astro
// astro.config.mjs
import { defineConfig } from 'astro/config';
import fcss from '@functionalcss/astro';
export default defineConfig({
integrations: [fcss()],
});
---
// src/layouts/Layout.astro
import '@functionalcss/core/full.css';
---
Works for static and server output; class="…" and static class:list entries are scanned.
Guide: Astro · package README.
Angular
ng add @functionalcss/angular
# in a bun workspace
bunx ng add @functionalcss/angular
The schematic installs the packages, adds the stylesheet to angular.json, and wires a purge step into your build script. Then:
ng serve # development, every class available
npm run build # production: purge first, then ng build (or: bun run build)
Always build through npm run build; ng build on its own skips the purge.
Guide: Angular · package README.
Other bundlers (PostCSS)
npm install @functionalcss/core
npm install -D @functionalcss/postcss
# or with bun
bun add @functionalcss/core
bun add -d @functionalcss/postcss
// postcss.config.mjs
import { createRequire } from 'node:module';
import fcss from '@functionalcss/postcss';
const require = createRequire(import.meta.url);
export default {
plugins: [
// The plugin purges on every run; this keeps the full set in development.
process.env.NODE_ENV === 'production' && fcss({
manifest: require.resolve('@functionalcss/core/manifest.json'),
content: ['src/**/*.{html,js,jsx,ts,tsx}'],
}),
].filter(Boolean),
};
Import @functionalcss/core/full.css from your entry point, and make sure your bundler runs PostCSS on CSS imported from node_modules. This path is used under the hood by the Vite, Next.js and Astro integrations; other bundlers have not been tested yet.
Options: package README.
Plain HTML / CDN
No build step? Link the full stylesheet:
<link rel="stylesheet" href="https://unpkg.com/@functionalcss/core/dist/full.css" />
This loads every class (about 28 MB), which is fine for prototypes but not for production. To ship only what you use, purge with the CLI:
npm install @functionalcss/core
npm install -D @functionalcss/cli
npx fcss init --framework none # creates fcss.config.ts; point `content` at your HTML
npx fcss purge -i node_modules/@functionalcss/core/dist/full.css -o public/fcss.css
# same with bun
bun add @functionalcss/core
bun add -d @functionalcss/cli
bunx fcss init --framework none
bunx fcss purge -i node_modules/@functionalcss/core/dist/full.css -o public/fcss.css
Run the purge again whenever your HTML changes.
<link rel="stylesheet" href="/fcss.css" />
Usage
Class syntax
Pattern
Example
CSS property--value
padding--24
padding: 24px
property--value:pseudo
color--red:hover
:hover { color: … }
property--value:aria-attr:value
display--block:aria-expanded:true
[aria-expanded='true'] { display: block }
breakpoint-property--value
md-display--none
@media (min-width: 768px) { display: none }
breakpoint-property--value:pseudo
md-color--red:hover
both combined
<button class="padding--16 background-color--blue color--white border-radius--8 color--red:hover"> Save </button>
<nav class="display--none md-display--flex justify-content--space-between">…</nav>
Breakpoints are mobile-first (min-width):
Prefix
sm
md
lg
xl
xxl
Min
576 px
768 px
992 px
1200 px
1400 px
Colors are custom properties (--fcss-color-blue, …) defined in root.css, so you can re-theme them.
Look up any class with npx fcss explain <class>, list them with npx fcss list, or see the reference.
Keep class names static
The purge step reads your source files; it cannot run your code. Write full class names:
// ✅ found by the scanner
<div className={isOpen ? 'display--block' : 'display--none'} />
// ❌ assembled at runtime, so it gets purged
<div className={`display--${isOpen ? 'block' : 'none'}`} />
Classes you can't write statically go in the safelist.
Configuration
Optional fcss.config.ts at your project root (npx fcss init creates one):
import { defineConfig } from '@functionalcss/cli';
export default defineConfig({
content: ['./src/**/*.{html,js,jsx,ts,tsx}'],
safelist: ['display--none', 'di