FCSS 2:读起来像 CSS 的实用类 CSS
FCSS 2: Utility CSS that reads like CSS

原始链接: https://github.com/meerita/FCSS2

FCSS 是一个实用型 CSS 库,其类名直接对应 CSS 声明:`padding--24` 等于 `padding:24px`,`background-color--blue` 等于 `background-color:blue`。悬停、ARIA 和响应式变体都是类名的一部分,因此无需速查表。它可用于任何框架或纯 HTML,并输出无运行时的纯 CSS。`@functionalcss/core` 包含所有类(约 28 MB);清除步骤或框架集成会扫描源文件,仅保留用到的类,通常可将输出缩减到几 KB。支持的集成包括 Vite、Next.js、Astro、Angular 和 PostCSS,还可通过 CDN 用于原型开发。它需要 Node 20.19+ 或 Bun 以及包管理器。扫描器会读取 HTML、JS/TS、JSX/TSX、Angular 模板和 `.astro` 文件;尚不扫描 Vue 和 Svelte。动态类名需要加入安全列表。CLI 命令包括 `init`、`purge`、`audit`、`explain`、`list`、`build`、`doctor` 和 `migrate`。项目专属的多声明规则使用 `c-` 前缀。采用 MIT 许可。

相关文章

原文

FCSS is a utility CSS library where every class name is a CSS property and a value. If you know CSS, you already know FCSS. It works with any framework, or none.

<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>

One class is one declaration: padding--24 is padding: 24px and nothing else. Names are the real CSS names, so it's background-color--blue, not bg-blue, and there is no cheat sheet to keep open. Hover, ARIA and breakpoint variants are part of the name (color--red:hover, display--block:aria-expanded:true, md-display--none). There is no runtime: the browser gets plain CSS, and your build removes the classes you don't use.

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

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.

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.

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.

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.

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.

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" />
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.

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.

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', 'display--block'],
});

Multi-declaration, project-specific rules use the c- prefix and live in your own CSS:

.c-card {
  display: flex;
  flex-direction: column;
  border-radius: 8px;
  padding: 16px;
}
npm install -D @functionalcss/cli   # or: bun add -d @functionalcss/cli
Command Description
fcss init [-f <framework>] Create fcss.config.ts and add the CSS import
fcss purge -i <in.css> -o <out.css> Keep only the classes found in your content globs
fcss audit Flag dynamic class fragments and deprecated classes
fcss explain <class> Show what a class compiles to
fcss list [-p <property>] List classes for a property or category
fcss build Generate custom CSS (colors, data states) from your config
fcss doctor Check your installation
fcss migrate Migrate from legacy TFCSSF class names

All published on npm under @functionalcss. Editor support (VS Code and Zed extensions, LSP server) lives in this repo and is not published yet.

Installation · Syntax · Responsive · States · Purging · Custom CSS · Reference · Migration · Philosophy

See CONTRIBUTING.md for setup, architecture, and contribution guidelines.

MIT © Diego Lafuente

联系我们 contact @ memedata.com