- HTML 74.7%
- CSS 25.3%
|
|
||
|---|---|---|
| .forgejo/workflows | ||
| .github/workflows | ||
| index.css | ||
| index.html | ||
| package.json | ||
| preview.html | ||
| preview.ja.html | ||
| README.ja.md | ||
| README.md | ||
@fogtype/css
English | 日本語
A minimal, classless CSS framework that conveys structure through typography and spacing alone.
Semantic HTML (<h1> / <p> / <table> / <form> …) turns into a polished layout as-is. Designed for CJK with mixed CJK and Latin text in mind, it uses text-autospace to automatically insert spacing between CJK and Latin characters, a margin rhythm based on rlh (root line-height), and a flat, shadow-free aesthetic.
Overview
- Readability - The body width is constrained with
ric(character-width based) to adapt to full width without breakpoints, with a flat, shadow-free aesthetic - Classless - Plain HTML is styled as-is. Themes can be swapped simply by overriding the CSS variables on
:root(single file, zero dependencies) - CJK support -
text-autospaceadjusts spacing between CJK and Latin characters, andtext-spacing-trimhandles the spacing around punctuation automatically
To see it in action, view the preview.
Usage
HTML (CDN)
Just add one line to your <head>.
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fogtype/css" />
Then write semantic HTML.
<!doctype html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fogtype/css" />
</head>
<body>
<h1>Heading</h1>
<p>
Body text is styled without any classes. Mixed 日本語 and English is
auto-adjusted too.
</p>
</body>
</html>
NPM
npm install @fogtype/css
To pull it in through a bundler:
@import "@fogtype/css";
import "@fogtype/css";
To use a local copy, just drop in index.css as-is. It has no dependencies.
Themes
Every theme is declared as CSS variables (custom properties) on :root. Color, typography, spacing, and corner radius all derive from this set of variables, so the entire theme can be swapped just by overriding them.
The variables fall into four groups.
| Group | Prefix | Role |
|---|---|---|
| Color | --color-* |
All brand / semantic / neutral colors |
| Typography | --text-* / --leading-* |
Font sizes and line heights |
| Spacing | --space-* / --line-length |
block (rlh) / inline (rem) margin rhythm and body width |
| Shape | --radius |
Corner radius of interactive elements |
For the default values of each variable, see Legend - default theme (:root) below.
Customizing
Override the variables on :root (or any scope) with your own CSS. The key is to place it after loading the framework itself (index.css).
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fogtype/css" />
<style>
:root {
--color-primary: oklch(54% 0.247 293); /* swap the brand color */
--color-primary-dark: oklch(40% 0.247 293); /* on hover */
--radius: 0; /* sharpen the corners */
--line-length: 50; /* widen the body to 50ric */
}
</style>
To theme only part of a page, scope the variables to any element and re-declare them.
.brand-section {
--color-primary: oklch(52% 0.14 148);
--color-background: oklch(96% 0.006 148);
}
Legend - default theme (:root)
All tokens of the default theme declared on :root in index.css.
Color
| Variable | Default | Purpose |
|---|---|---|
--color-primary |
oklch(52% 0.165 255) |
Brand color, links |
--color-primary-dark |
oklch(44% 0.168 255) |
Primary on hover / press |
--color-primary-light |
oklch(88% 0.045 255) |
Selected rows, subtle highlights (mark etc.) |
--color-danger |
oklch(55% 0.16 25) |
Errors, deletion, dangerous actions |
--color-warning |
oklch(55% 0.117 75) |
Warnings, cautions |
--color-success |
oklch(52% 0.14 148) |
Success, completion |
--color-text |
oklch(32% 0.025 255) |
Body text (deep, bluish slate) |
--color-text-secondary |
oklch(50% 0.03 255) |
Supplementary text, labels, dates |
--color-text-disabled |
oklch(64% 0.025 255) |
Text in the disabled state |
--color-border |
oklch(78% 0.023 255) |
Dividers, frames, table rules |
--color-background |
oklch(94% 0.006 255) |
Page background |
--color-surface |
oklch(92% 0.015 255) |
Cards, code, table cells |
Typography
| Variable | Default | Purpose |
|---|---|---|
--text-huge |
1.6rem (32px) |
H1 |
--text-large |
1.2rem (24px) |
H2 |
--text-default |
1rem (20px) |
H3 / body |
--text-small |
0.75rem (15px) |
Caption, notes, footer |
--leading-default |
1.6 |
Line height of body text |
--leading-small |
1.2 |
Line height of headings (h1 / h2) |
Spacing
The block axis is based on rlh (root line-height = 1.6 × 20px = 32px) and the inline axis on rem (20px). The vocabulary is aligned with logical properties (margin-block / padding-inline etc.), so the axes follow the document flow even in vertical writing (writing-mode: vertical-rl etc.).
| Variable | Default | Purpose |
|---|---|---|
--space-block-tiny |
0.125rlh (4px) |
Right after H3+ headings, between list items |
--space-block-small |
0.5rlh (16px) |
Padding inside code / cells |
--space-block-default |
1rlh (32px) |
Between headings, between paragraphs |
--space-inline-default |
1rem (20px) |
Standard gap |
--space-inline-large |
2rem (40px) |
Indents, blockquotes, lists |
--line-length |
40 |
Body width (40ric ≈ 800px @20px) |
Shape
| Variable | Default | Purpose |
|---|---|---|
--radius |
var(--space-block-tiny) |
Corner radius of buttons, inputs, fieldsets |
License
MIT © 2026 Kohei Watanabe