A minimal, classless CSS framework that conveys structure through typography and spacing alone. fogtype.tngl.io/css/
0

Configure Feed

Select the types of activity you want to include in your feed.

create project

Kohei Watanabe (Jun 16, 2026, 1:11 AM +0900) de4f618d f79f599a

+1269
+157
README.ja.md
··· 1 + # @fogtype/css 2 + 3 + [English](README.md) | **日本語** 4 + 5 + タイポグラフィと余白だけで構造を伝える、ミニマルなクラスレスCSSフレームワーク。 6 + 7 + セマンティックなHTML(`<h1>` / `<p>` / `<table>` / `<form>` …)がそのまま整ったレイアウトになります。CJKと欧文の混植を前提とした CJK向けの設計で、`text-autospace` による CJK・欧文間スペースの自動挿入、`rlh`(root line-height)基準の余白リズム、影を使わないフラットな表現を採用しています。 8 + 9 + ## Overview 10 + 11 + - **読みやすさ** - 本文幅を `ric`(文字幅基準)で制限してブレークポイントなしで全幅に適応、影を使わないフラットな表現 12 + - **クラスレス** - 素のHTMLがそのまま整う。スタイルは `:root` のCSS変数を上書きするだけで差し替え可能(1ファイル・依存関係ゼロ) 13 + - **CJK対応** - `text-autospace` でCJK・欧文間スペースを、`text-spacing-trim` で約物の余白を自動調整 14 + 15 + 実際の表示は [`preview.ja.html`](./preview.ja.html) をブラウザで開くと確認できます。 16 + 17 + ## Usage 18 + 19 + ### HTML(CDN) 20 + 21 + `<head>` に1行追加するだけです。 22 + 23 + ```html 24 + <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fogtype/css" /> 25 + ``` 26 + 27 + あとはセマンティックなHTMLを記述します。 28 + 29 + ```html 30 + <!doctype html> 31 + <html lang="ja" dir="ltr"> 32 + <head> 33 + <meta charset="utf-8" /> 34 + <meta name="viewport" content="width=device-width" /> 35 + <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fogtype/css" /> 36 + </head> 37 + <body> 38 + <h1>見出し</h1> 39 + <p>本文はクラスなしで整います。日本語とEnglishの混植も自動調整されます。</p> 40 + </body> 41 + </html> 42 + ``` 43 + 44 + ### NPM 45 + 46 + ```sh 47 + npm install @fogtype/css 48 + ``` 49 + 50 + バンドラ経由で取り込む場合: 51 + 52 + ```css 53 + @import "@fogtype/css"; 54 + ``` 55 + 56 + ```js 57 + import "@fogtype/css"; 58 + ``` 59 + 60 + ローカルにコピーして使う場合は [`index.css`](./index.css) をそのまま配置します。依存関係はありません。 61 + 62 + ## Themes 63 + 64 + テーマはすべて **`:root` の CSS 変数(カスタムプロパティ)として宣言** されています。色・タイポグラフィ・余白・角丸はこの変数群を起点にしており、変数を上書きするだけでテーマ全体を差し替えられます。 65 + 66 + 変数は次の4つのグループに分かれます。 67 + 68 + | グループ | プレフィックス | 役割 | 69 + | ---------- | ----------------------------- | --------------------------------------------------- | 70 + | Color | `--color-*` | ブランド / 意味 / ニュートラルの全色 | 71 + | Typography | `--text-*` / `--leading-*` | 文字サイズと行間 | 72 + | Spacing | `--space-*` / `--line-length` | block(`rlh`)・inline(`rem`)の余白リズムと本文幅 | 73 + | Shape | `--radius` | 操作要素の角丸 | 74 + 75 + 各変数の既定値は後述の [Legend - default theme (`:root`)](#legend-default-theme-root) を参照してください。 76 + 77 + ## Customizing 78 + 79 + 独自の CSS で `:root`(または任意のスコープ)の変数を上書きします。フレームワーク本体(`index.css`)を読み込んだ **後** に置くのがポイントです。 80 + 81 + <!-- prettier-ignore-start --> 82 + ```html 83 + <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fogtype/css" /> 84 + <style> 85 + :root { 86 + --color-primary: oklch(54% 0.247 293); /* ブランドカラー差し替え */ 87 + --color-primary-dark: oklch(40% 0.247 293); /* ホバー時 */ 88 + --radius: 0; /* 角張らせる */ 89 + --line-length: 50; /* 本文幅を 50ric に広げる */ 90 + } 91 + </style> 92 + ``` 93 + <!-- prettier-ignore-end --> 94 + 95 + ページの一部だけテーマを変えたい場合は、任意の要素にスコープして変数を再宣言できます。 96 + 97 + ```css 98 + .brand-section { 99 + --color-primary: oklch(52% 0.14 148); 100 + --color-background: oklch(96% 0.006 148); 101 + } 102 + ``` 103 + 104 + ## Legend - default theme (`:root`) 105 + 106 + `index.css` の `:root` で宣言されている既定テーマの全トークンです。 107 + 108 + ### Color 109 + 110 + | 変数 | 既定値 | 用途 | 111 + | ------------------------ | ---------------------- | -------------------------------------- | 112 + | `--color-primary` | `oklch(52% 0.165 255)` | ブランドカラー、リンク | 113 + | `--color-primary-dark` | `oklch(44% 0.168 255)` | ホバー・プレス時のプライマリー | 114 + | `--color-primary-light` | `oklch(88% 0.045 255)` | 選択行・淡いハイライト(`mark` 等) | 115 + | `--color-danger` | `oklch(55% 0.16 25)` | エラー・削除・危険な操作 | 116 + | `--color-warning` | `oklch(55% 0.117 75)` | 警告・注意喚起 | 117 + | `--color-success` | `oklch(52% 0.14 148)` | 成功・完了 | 118 + | `--color-text` | `oklch(32% 0.025 255)` | 本文テキスト(青みのある濃いスレート) | 119 + | `--color-text-secondary` | `oklch(50% 0.03 255)` | 補足テキスト・ラベル・日付 | 120 + | `--color-text-disabled` | `oklch(64% 0.025 255)` | 無効状態のテキスト | 121 + | `--color-border` | `oklch(78% 0.023 255)` | 区切り線・枠・テーブル罫線 | 122 + | `--color-background` | `oklch(94% 0.006 255)` | ページ背景 | 123 + | `--color-surface` | `oklch(92% 0.015 255)` | カード・コード・テーブルセル | 124 + 125 + ### Typography 126 + 127 + | 変数 | 既定値 | 用途 | 128 + | ------------------- | ----------------- | ----------------------- | 129 + | `--text-huge` | `1.6rem`(32px) | H1 | 130 + | `--text-large` | `1.2rem`(24px) | H2 | 131 + | `--text-default` | `1rem`(20px) | H3 / 本文 | 132 + | `--text-small` | `0.75rem`(15px) | Caption・注釈・フッター | 133 + | `--leading-default` | `1.6` | 本文の行間 | 134 + | `--leading-small` | `1.2` | 見出し(h1 / h2)の行間 | 135 + 136 + ### Spacing 137 + 138 + block 方向は `rlh`(root line-height = 1.6 × 20px = **32px**)、inline 方向は `rem`(**20px**)が基準です。論理プロパティ(`margin-block` / `padding-inline` 等)と語彙を揃えており、縦書き(`writing-mode: vertical-rl` 等)でも軸が文書の流れに追従します。 139 + 140 + | 変数 | 既定値 | 用途 | 141 + | ------------------------ | ----------------- | -------------------------------- | 142 + | `--space-block-tiny` | `0.125rlh`(4px) | H3以上見出しの直後・リスト項目間 | 143 + | `--space-block-small` | `0.5rlh`(16px) | コード・セル内パディング | 144 + | `--space-block-default` | `1rlh`(32px) | 見出し間・段落間 | 145 + | `--space-inline-default` | `1rem`(20px) | 標準アキ | 146 + | `--space-inline-large` | `2rem`(40px) | インデント・引用・リスト | 147 + | `--line-length` | `40` | 本文幅(`40ric` ≒ 800px @20px) | 148 + 149 + ### Shape 150 + 151 + | 変数 | 既定値 | 用途 | 152 + | ---------- | ------------------------- | ------------------------------ | 153 + | `--radius` | `var(--space-block-tiny)` | ボタン・入力欄・fieldsetの角丸 | 154 + 155 + ## License 156 + 157 + MIT © 2026 [Kohei Watanabe](https://fogtype.com/@nebel)
+160
README.md
··· 1 + # @fogtype/css 2 + 3 + **English** | [日本語](README.ja.md) 4 + 5 + A minimal, classless CSS framework that conveys structure through typography and spacing alone. 6 + 7 + 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. 8 + 9 + ## Overview 10 + 11 + - **Readability** - The body width is constrained with `ric` (character-width based) to adapt to full width without breakpoints, with a flat, shadow-free aesthetic 12 + - **Classless** - Plain HTML is styled as-is. Themes can be swapped simply by overriding the CSS variables on `:root` (single file, zero dependencies) 13 + - **CJK support** - `text-autospace` adjusts spacing between CJK and Latin characters, and `text-spacing-trim` handles the spacing around punctuation automatically 14 + 15 + To see it in action, open [`preview.html`](./preview.html) in your browser. 16 + 17 + ## Usage 18 + 19 + ### HTML (CDN) 20 + 21 + Just add one line to your `<head>`. 22 + 23 + ```html 24 + <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fogtype/css" /> 25 + ``` 26 + 27 + Then write semantic HTML. 28 + 29 + ```html 30 + <!doctype html> 31 + <html lang="en" dir="ltr"> 32 + <head> 33 + <meta charset="utf-8" /> 34 + <meta name="viewport" content="width=device-width" /> 35 + <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fogtype/css" /> 36 + </head> 37 + <body> 38 + <h1>Heading</h1> 39 + <p> 40 + Body text is styled without any classes. Mixed 日本語 and English is 41 + auto-adjusted too. 42 + </p> 43 + </body> 44 + </html> 45 + ``` 46 + 47 + ### NPM 48 + 49 + ```sh 50 + npm install @fogtype/css 51 + ``` 52 + 53 + To pull it in through a bundler: 54 + 55 + ```css 56 + @import "@fogtype/css"; 57 + ``` 58 + 59 + ```js 60 + import "@fogtype/css"; 61 + ``` 62 + 63 + To use a local copy, just drop in [`index.css`](./index.css) as-is. It has no dependencies. 64 + 65 + ## Themes 66 + 67 + 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. 68 + 69 + The variables fall into four groups. 70 + 71 + | Group | Prefix | Role | 72 + | ---------- | ----------------------------- | ----------------------------------------------------------- | 73 + | Color | `--color-*` | All brand / semantic / neutral colors | 74 + | Typography | `--text-*` / `--leading-*` | Font sizes and line heights | 75 + | Spacing | `--space-*` / `--line-length` | block (`rlh`) / inline (`rem`) margin rhythm and body width | 76 + | Shape | `--radius` | Corner radius of interactive elements | 77 + 78 + For the default values of each variable, see [Legend - default theme (`:root`)](#legend-default-theme-root) below. 79 + 80 + ## Customizing 81 + 82 + 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`). 83 + 84 + <!-- prettier-ignore-start --> 85 + ```html 86 + <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fogtype/css" /> 87 + <style> 88 + :root { 89 + --color-primary: oklch(54% 0.247 293); /* swap the brand color */ 90 + --color-primary-dark: oklch(40% 0.247 293); /* on hover */ 91 + --radius: 0; /* sharpen the corners */ 92 + --line-length: 50; /* widen the body to 50ric */ 93 + } 94 + </style> 95 + ``` 96 + <!-- prettier-ignore-end --> 97 + 98 + To theme only part of a page, scope the variables to any element and re-declare them. 99 + 100 + ```css 101 + .brand-section { 102 + --color-primary: oklch(52% 0.14 148); 103 + --color-background: oklch(96% 0.006 148); 104 + } 105 + ``` 106 + 107 + ## Legend - default theme (`:root`) 108 + 109 + All tokens of the default theme declared on `:root` in `index.css`. 110 + 111 + ### Color 112 + 113 + | Variable | Default | Purpose | 114 + | ------------------------ | ---------------------- | ---------------------------------------------- | 115 + | `--color-primary` | `oklch(52% 0.165 255)` | Brand color, links | 116 + | `--color-primary-dark` | `oklch(44% 0.168 255)` | Primary on hover / press | 117 + | `--color-primary-light` | `oklch(88% 0.045 255)` | Selected rows, subtle highlights (`mark` etc.) | 118 + | `--color-danger` | `oklch(55% 0.16 25)` | Errors, deletion, dangerous actions | 119 + | `--color-warning` | `oklch(55% 0.117 75)` | Warnings, cautions | 120 + | `--color-success` | `oklch(52% 0.14 148)` | Success, completion | 121 + | `--color-text` | `oklch(32% 0.025 255)` | Body text (deep, bluish slate) | 122 + | `--color-text-secondary` | `oklch(50% 0.03 255)` | Supplementary text, labels, dates | 123 + | `--color-text-disabled` | `oklch(64% 0.025 255)` | Text in the disabled state | 124 + | `--color-border` | `oklch(78% 0.023 255)` | Dividers, frames, table rules | 125 + | `--color-background` | `oklch(94% 0.006 255)` | Page background | 126 + | `--color-surface` | `oklch(92% 0.015 255)` | Cards, code, table cells | 127 + 128 + ### Typography 129 + 130 + | Variable | Default | Purpose | 131 + | ------------------- | ---------------- | --------------------------------- | 132 + | `--text-huge` | `1.6rem` (32px) | H1 | 133 + | `--text-large` | `1.2rem` (24px) | H2 | 134 + | `--text-default` | `1rem` (20px) | H3 / body | 135 + | `--text-small` | `0.75rem` (15px) | Caption, notes, footer | 136 + | `--leading-default` | `1.6` | Line height of body text | 137 + | `--leading-small` | `1.2` | Line height of headings (h1 / h2) | 138 + 139 + ### Spacing 140 + 141 + 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.). 142 + 143 + | Variable | Default | Purpose | 144 + | ------------------------ | ---------------- | -------------------------------------------- | 145 + | `--space-block-tiny` | `0.125rlh` (4px) | Right after H3+ headings, between list items | 146 + | `--space-block-small` | `0.5rlh` (16px) | Padding inside code / cells | 147 + | `--space-block-default` | `1rlh` (32px) | Between headings, between paragraphs | 148 + | `--space-inline-default` | `1rem` (20px) | Standard gap | 149 + | `--space-inline-large` | `2rem` (40px) | Indents, blockquotes, lists | 150 + | `--line-length` | `40` | Body width (`40ric` ≈ 800px @20px) | 151 + 152 + ### Shape 153 + 154 + | Variable | Default | Purpose | 155 + | ---------- | ------------------------- | ------------------------------------------- | 156 + | `--radius` | `var(--space-block-tiny)` | Corner radius of buttons, inputs, fieldsets | 157 + 158 + ## License 159 + 160 + MIT © 2026 [Kohei Watanabe](https://fogtype.com/@nebel)
+273
index.css
··· 1 + :root { 2 + --color-primary: oklch(52% 0.165 255); 3 + --color-primary-dark: oklch(44% 0.168 255); 4 + --color-primary-light: oklch(88% 0.045 255); 5 + --color-danger: oklch(55% 0.16 25); 6 + --color-warning: oklch(55% 0.117 75); 7 + --color-success: oklch(52% 0.14 148); 8 + --color-text: oklch(32% 0.025 255); 9 + --color-text-secondary: oklch(50% 0.03 255); 10 + --color-text-disabled: oklch(64% 0.025 255); 11 + --color-border: oklch(78% 0.023 255); 12 + --color-background: oklch(94% 0.006 255); 13 + --color-surface: oklch(92% 0.015 255); 14 + --text-huge: 1.6rem; 15 + --text-large: 1.2rem; 16 + --text-default: 1rem; 17 + --text-small: 0.75rem; 18 + --leading-default: 1.6; 19 + --leading-small: 1.2; 20 + --space-block-tiny: 0.125rlh; 21 + --space-block-small: 0.5rlh; 22 + --space-block-default: 1rlh; 23 + --space-inline-default: 1rem; 24 + --space-inline-large: 2rem; 25 + --line-length: 40; 26 + --radius: var(--space-block-tiny); 27 + } 28 + *, 29 + *::before, 30 + *::after { 31 + box-sizing: border-box; 32 + } 33 + html { 34 + font-family: sans-serif; 35 + font-size: max(20px, 100%); 36 + line-height: var(--leading-default); 37 + color: var(--color-text); 38 + background: var(--color-background); 39 + text-autospace: normal; 40 + text-spacing-trim: trim-start; 41 + -webkit-text-size-adjust: 100%; 42 + } 43 + body { 44 + max-inline-size: calc(var(--line-length) * 1ric); 45 + padding-inline: 5lvi; 46 + margin-block: 5svb; 47 + margin-inline: auto; 48 + } 49 + h1, 50 + h2, 51 + h3, 52 + h4, 53 + h5, 54 + h6 { 55 + font-weight: normal; 56 + } 57 + h1 { 58 + margin-block: var(--space-block-default); 59 + font-size: var(--text-huge); 60 + line-height: var(--leading-small); 61 + } 62 + h2 { 63 + margin-block: var(--space-block-default); 64 + font-size: var(--text-large); 65 + line-height: var(--leading-small); 66 + } 67 + h3 { 68 + margin-block: var(--space-block-default) var(--space-block-tiny); 69 + font-size: var(--text-default); 70 + } 71 + p { 72 + margin-block: var(--space-block-default); 73 + } 74 + hr { 75 + margin-block: var(--space-block-default); 76 + border: none; 77 + border-block-start: 1px solid var(--color-border); 78 + } 79 + pre { 80 + padding-block: var(--space-block-small); 81 + padding-inline: var(--space-inline-default); 82 + margin-block: var(--space-block-default); 83 + overflow-x: auto; 84 + overflow-inline: auto; 85 + background: var(--color-surface); 86 + } 87 + pre code { 88 + padding: 0; 89 + } 90 + blockquote { 91 + padding-inline-start: var(--space-inline-default); 92 + margin-block: var(--space-block-default); 93 + margin-inline: 0; 94 + color: var(--color-text-secondary); 95 + border-inline-start: 2px solid var(--color-border); 96 + } 97 + ul, 98 + ol { 99 + padding-inline-start: var(--space-inline-large); 100 + margin-block: var(--space-block-default); 101 + } 102 + li { 103 + margin-block: var(--space-block-tiny); 104 + } 105 + li > ul, 106 + li > ol { 107 + margin-block: var(--space-block-tiny); 108 + } 109 + dl { 110 + margin-block: var(--space-block-default); 111 + } 112 + dt { 113 + font-weight: bold; 114 + } 115 + dd { 116 + margin-inline-start: var(--space-inline-large); 117 + } 118 + figure { 119 + margin-block: var(--space-block-default); 120 + margin-inline: 0; 121 + } 122 + figcaption { 123 + margin-block-start: var(--space-block-tiny); 124 + font-size: var(--text-small); 125 + color: var(--color-text-secondary); 126 + } 127 + a { 128 + color: var(--color-primary); 129 + text-decoration-color: color-mix(in oklch, currentcolor, white); 130 + text-underline-offset: 0.15em; 131 + } 132 + a:hover { 133 + color: var(--color-primary-dark); 134 + } 135 + em { 136 + font-style: normal; 137 + font-weight: bold; 138 + } 139 + code, 140 + pre, 141 + kbd, 142 + samp, 143 + time { 144 + font-family: monospace; 145 + font-size: inherit; 146 + text-autospace: no-autospace; 147 + text-spacing-trim: space-all; 148 + } 149 + mark { 150 + color: inherit; 151 + background: var(--color-primary-light); 152 + } 153 + img { 154 + max-inline-size: 100%; 155 + block-size: auto; 156 + } 157 + table { 158 + inline-size: 100%; 159 + margin-block: var(--space-block-default); 160 + border-collapse: collapse; 161 + } 162 + th, 163 + td { 164 + padding-block: var(--space-block-small); 165 + padding-inline: var(--space-inline-default); 166 + vertical-align: top; 167 + text-align: start; 168 + background: var(--color-surface); 169 + border-bottom: 1px solid var(--color-border); 170 + } 171 + thead th { 172 + border-bottom: 2px solid var(--color-border); 173 + } 174 + caption { 175 + margin-block-end: var(--space-block-tiny); 176 + font-size: var(--text-small); 177 + color: var(--color-text-secondary); 178 + text-align: start; 179 + } 180 + label { 181 + display: inline-block; 182 + margin-block-end: var(--space-block-tiny); 183 + } 184 + input, 185 + textarea, 186 + select { 187 + inline-size: 100%; 188 + max-inline-size: 100%; 189 + min-block-size: calc(var(--text-default) * 3); 190 + padding-block: calc(var(--space-block-tiny) * 2); 191 + padding-inline: var(--space-inline-default); 192 + font: inherit; 193 + color: var(--color-text); 194 + background: white; 195 + border: 1px solid var(--color-border); 196 + border-radius: var(--radius); 197 + } 198 + textarea { 199 + min-block-size: calc(var(--text-default) * 6); 200 + resize: vertical; 201 + resize: block; 202 + } 203 + input:focus, 204 + textarea:focus, 205 + select:focus { 206 + outline: 2px solid var(--color-primary); 207 + outline-offset: -2px; 208 + border-color: var(--color-primary); 209 + } 210 + input::placeholder, 211 + textarea::placeholder { 212 + color: var(--color-text-disabled); 213 + } 214 + input:disabled, 215 + textarea:disabled, 216 + select:disabled { 217 + color: var(--color-text-disabled); 218 + background: var(--color-background); 219 + } 220 + input[type="checkbox"], 221 + input[type="radio"] { 222 + inline-size: auto; 223 + min-block-size: 0; 224 + accent-color: var(--color-primary); 225 + } 226 + button, 227 + [type="button"], 228 + [type="submit"] { 229 + min-block-size: var(--space-block-default); 230 + padding-block: var(--space-block-small); 231 + padding-inline: var(--space-inline-default); 232 + font: inherit; 233 + font-weight: bold; 234 + cursor: pointer; 235 + border-radius: var(--radius); 236 + } 237 + [type="submit"] { 238 + color: white; 239 + background: var(--color-primary); 240 + border: none; 241 + } 242 + [type="submit"]:not(:disabled):hover { 243 + background: var(--color-primary-dark); 244 + } 245 + button, 246 + [type="button"] { 247 + color: var(--color-primary); 248 + background: transparent; 249 + border: 1px solid var(--color-border); 250 + } 251 + button:not(:disabled):hover, 252 + [type="button"]:not(:disabled):hover { 253 + background: var(--color-surface); 254 + } 255 + button:focus-visible { 256 + outline: 2px solid var(--color-primary-dark); 257 + outline-offset: 2px; 258 + } 259 + button:disabled { 260 + color: var(--color-background); 261 + cursor: not-allowed; 262 + background: var(--color-text-disabled); 263 + } 264 + fieldset { 265 + padding-block: var(--space-block-small); 266 + padding-inline: var(--space-inline-default); 267 + margin-block: var(--space-block-default); 268 + border: 1px solid var(--color-border); 269 + border-radius: var(--radius); 270 + } 271 + legend { 272 + padding-inline: var(--space-inline-default); 273 + }
+17
index.html
··· 1 + <!doctype html> 2 + <html lang="en" dir="ltr"> 3 + <meta charset="utf-8" /> 4 + <meta name="viewport" content="width=device-width" /> 5 + <title>@fogtype/css</title> 6 + <link rel="stylesheet" href="index.css" /> 7 + <body> 8 + <main> 9 + <h1>@fogtype/css</h1> 10 + <p>A minimal, classless CSS framework.</p> 11 + <ul> 12 + <li><a href="preview.html">Preview</a></li> 13 + <li><a href="preview.ja.html">プレビュー (日本語)</a></li> 14 + </ul> 15 + </main> 16 + </body> 17 + </html>
+15
package.json
··· 1 + { 2 + "name": "@fogtype/css", 3 + "version": "1.0.0", 4 + "description": "A classless CSS framework", 5 + "keywords": [ 6 + "css" 7 + ], 8 + "license": "MIT", 9 + "author": "Kohei Watanabe <nebel@fogtype.com>", 10 + "repository": { 11 + "type": "git", 12 + "url": "https://git.fogtype.com/nebel/css.git" 13 + }, 14 + "main": "index.css" 15 + }
+325
preview.html
··· 1 + <!doctype html> 2 + <html lang="en" dir="ltr"> 3 + <meta charset="utf-8" /> 4 + <meta name="viewport" content="width=device-width" /> 5 + <title>@fogtype/css</title> 6 + <link rel="stylesheet" href="index.css" /> 7 + <style> 8 + .palette { 9 + list-style: none; 10 + display: grid; 11 + grid-template-columns: repeat(auto-fill, minmax(8em, 1fr)); 12 + gap: var(--space-block-small); 13 + padding: 0; 14 + margin-block: var(--space-block-default); 15 + } 16 + .palette li { 17 + margin: 0; 18 + } 19 + .swatch { 20 + display: block; 21 + block-size: 4rlh; 22 + border: 1px solid var(--color-border); 23 + } 24 + .palette code { 25 + background: none; 26 + padding: 0; 27 + color: var(--color-text-secondary); 28 + } 29 + .palette b { 30 + display: block; 31 + } 32 + .palette small { 33 + display: block; 34 + } 35 + .alert { 36 + margin-block: var(--space-block-small); 37 + padding-block: var(--space-block-small); 38 + padding-inline: var(--space-inline-default); 39 + border-inline-start: 4px solid var(--color-text-secondary); 40 + } 41 + .alert.is-danger { 42 + border-color: var(--color-danger); 43 + } 44 + .alert.is-warning { 45 + border-color: var(--color-warning); 46 + } 47 + .alert.is-success { 48 + border-color: var(--color-success); 49 + } 50 + .alert b.is-danger { 51 + color: var(--color-danger); 52 + } 53 + .alert b.is-warning { 54 + color: var(--color-warning); 55 + } 56 + .alert b.is-success { 57 + color: var(--color-success); 58 + } 59 + .btn-row { 60 + display: flex; 61 + flex-wrap: wrap; 62 + gap: var(--space-inline-default); 63 + align-items: center; 64 + } 65 + </style> 66 + 67 + <header> 68 + <h1>@fogtype/css</h1> 69 + <p> 70 + A minimal, classless CSS framework that conveys structure through 71 + typography and spacing alone. 72 + </p> 73 + </header> 74 + 75 + <hr /> 76 + 77 + <h2>Color Palette</h2> 78 + <ul class="palette"> 79 + <li> 80 + <span class="swatch" style="background: var(--color-primary)"></span> 81 + <b>Primary</b><code>--color-primary</code> 82 + </li> 83 + <li> 84 + <span class="swatch" style="background: var(--color-primary-dark)"></span> 85 + <b>Primary Dark</b><code>--color-primary-dark</code> 86 + </li> 87 + <li> 88 + <span 89 + class="swatch" 90 + style="background: var(--color-primary-light)" 91 + ></span> 92 + <b>Primary Light</b><code>--color-primary-light</code> 93 + </li> 94 + <li> 95 + <span class="swatch" style="background: var(--color-danger)"></span> 96 + <b>Danger</b><code>--color-danger</code> 97 + </li> 98 + <li> 99 + <span class="swatch" style="background: var(--color-warning)"></span> 100 + <b>Warning</b><code>--color-warning</code> 101 + </li> 102 + <li> 103 + <span class="swatch" style="background: var(--color-success)"></span> 104 + <b>Success</b><code>--color-success</code> 105 + </li> 106 + <li> 107 + <span class="swatch" style="background: var(--color-text)"></span> 108 + <b>Text</b><code>--color-text</code> 109 + </li> 110 + <li> 111 + <span 112 + class="swatch" 113 + style="background: var(--color-text-secondary)" 114 + ></span> 115 + <b>Text Secondary</b><code>--color-text-secondary</code> 116 + </li> 117 + <li> 118 + <span 119 + class="swatch" 120 + style="background: var(--color-text-disabled)" 121 + ></span> 122 + <b>Text Disabled</b><code>--color-text-disabled</code> 123 + </li> 124 + <li> 125 + <span class="swatch" style="background: var(--color-border)"></span> 126 + <b>Border</b><code>--color-border</code> 127 + </li> 128 + <li> 129 + <span class="swatch" style="background: var(--color-surface)"></span> 130 + <b>Surface</b><code>--color-surface</code> 131 + </li> 132 + <li> 133 + <span class="swatch" style="background: var(--color-background)"></span> 134 + <b>Background</b><code>--color-background</code> 135 + </li> 136 + </ul> 137 + 138 + <h2>Typography</h2> 139 + 140 + <h1>Heading 1 - 32px</h1> 141 + <h2>Heading 2 - 24px</h2> 142 + <h3>Heading 3 / Body - 20px</h3> 143 + 144 + <p> 145 + Body text is based on 20px with a line height of 1.6. When mixing 日本語 and 146 + English, 147 + <code>text-autospace: normal</code> 148 + automatically inserts a 1/4 em space between CJK and Latin characters. Even 149 + in a sentence like "use Claude Opus 4.8 in 2026年", the spacing around 150 + punctuation is adjusted by 151 + <code>text-spacing-trim</code>. 152 + </p> 153 + 154 + <p> 155 + Use <em>bold (em)</em> for emphasis and <strong>strong</strong> for stronger 156 + meaning. Links appear <a href="#">like this</a> in an underline color. Keys 157 + are shown as <kbd>Ctrl</kbd>+<kbd>K</kbd>, notes are attached 158 + <small>like this with small</small>. Highlights are 159 + <mark>expressed with mark</mark>. 160 + </p> 161 + 162 + <h2>Lists</h2> 163 + 164 + <h3>Unordered list</h3> 165 + <ul> 166 + <li>Calm, clean, readability first</li> 167 + <li> 168 + Flat design 169 + <ul> 170 + <li>Nested items keep the rhythm too</li> 171 + <li>Indent is <code>--space-inline-large</code> (40px)</li> 172 + </ul> 173 + </li> 174 + <li>Layout for print media and long-form reading</li> 175 + </ul> 176 + 177 + <h3>Ordered list</h3> 178 + <ol> 179 + <li>Pin the root font-size to a minimum of 20px</li> 180 + <li>Align margins to the rlh (32px) rhythm</li> 181 + </ol> 182 + 183 + <h3>Definition list</h3> 184 + <dl> 185 + <dt>rlh</dt> 186 + <dd> 187 + root line-height = 1.6 × 20px = 32px. The base unit for all block-axis 188 + margins. 189 + </dd> 190 + <dt>ic</dt> 191 + <dd>The advance width of one full-width character</dd> 192 + </dl> 193 + 194 + <h2>Code</h2> 195 + <p> 196 + Inline code blends into the body as in 197 + <code>--space-block-small</code>. Blocks scroll horizontally: 198 + </p> 199 + 200 + <pre><code>:root { 201 + --color-primary: oklch(54% 0.247 293); /* swap the brand color */ 202 + --color-primary-dark: oklch(40% 0.247 293); /* on hover */ 203 + --radius: 0; /* sharpen the corners */ 204 + --line-length: 50; /* widen the body to 50ric */ 205 + }</code></pre> 206 + 207 + <h2>Table</h2> 208 + <p> 209 + Tables are flat, with no shadows or rounded corners. Cell backgrounds use 210 + <code>--color-surface</code>, and row dividers use 211 + <code>1px solid var(--color-border)</code>. 212 + </p> 213 + 214 + <table> 215 + <caption> 216 + Type Scale 217 + </caption> 218 + <thead> 219 + <tr> 220 + <th>Role</th> 221 + <th>Token</th> 222 + <th>Size</th> 223 + <th>Line Height</th> 224 + </tr> 225 + </thead> 226 + <tbody> 227 + <tr> 228 + <td>Heading 1</td> 229 + <td><code>--text-huge</code></td> 230 + <td>32px</td> 231 + <td>1.2</td> 232 + </tr> 233 + <tr> 234 + <td>Heading 2</td> 235 + <td><code>--text-large</code></td> 236 + <td>24px</td> 237 + <td>1.2</td> 238 + </tr> 239 + <tr> 240 + <td>Heading 3 / Body</td> 241 + <td><code>--text-default</code></td> 242 + <td>20px</td> 243 + <td>1.6</td> 244 + </tr> 245 + <tr> 246 + <td>Caption / Small</td> 247 + <td><code>--text-small</code></td> 248 + <td>15px</td> 249 + <td>1.6</td> 250 + </tr> 251 + </tbody> 252 + </table> 253 + 254 + <h2>Semantic Colors</h2> 255 + 256 + <div class="alert is-danger"> 257 + <b class="is-danger">Error</b>: The value you entered is not valid. Uses 258 + <code>--color-danger</code>. 259 + </div> 260 + <div class="alert is-warning"> 261 + <b class="is-warning">Warning</b>: This action cannot be undone. Uses 262 + <code>--color-warning</code>. 263 + </div> 264 + <div class="alert is-success"> 265 + <b class="is-success">Done</b>: Your changes have been saved. Uses 266 + <code>--color-success</code>. 267 + </div> 268 + 269 + <h2>Buttons</h2> 270 + <p> 271 + Corners have a subtle radius (<code>border-radius: var(--radius)</code>). 272 + The height meets the minimum touch-target size. 273 + </p> 274 + <p class="btn-row"> 275 + <button type="submit">Primary</button> 276 + <button type="reset">Secondary</button> 277 + <button type="button" disabled>Disabled</button> 278 + </p> 279 + 280 + <h2>Forms</h2> 281 + <form onsubmit="return false;"> 282 + <p> 283 + <label for="name">Name</label> 284 + <input id="name" type="text" placeholder="Jane Doe" /> 285 + </p> 286 + <p> 287 + <label for="email">Email address</label> 288 + <input id="email" type="email" placeholder="name@example.com" /> 289 + </p> 290 + <p> 291 + <label for="theme">Theme</label> 292 + <select id="theme"> 293 + <option>Light</option> 294 + <option>Dark</option> 295 + <option>Auto</option> 296 + </select> 297 + </p> 298 + <p> 299 + <label for="message">Message</label> 300 + <textarea id="message" placeholder="Write freely"></textarea> 301 + </p> 302 + 303 + <fieldset> 304 + <legend>Display settings</legend> 305 + <p> 306 + <label><input type="checkbox" checked /> Show ruby</label> 307 + </p> 308 + <p> 309 + <label><input type="radio" name="lh" checked /> Relaxed</label> 310 + <label><input type="radio" name="lh" /> Cozy</label> 311 + </p> 312 + </fieldset> 313 + 314 + <p class="btn-row"> 315 + <button type="submit">Submit</button> 316 + <button type="reset">Reset</button> 317 + </p> 318 + </form> 319 + 320 + <hr /> 321 + 322 + <footer> 323 + <small>@fogtype/css - A classless CSS framework. MIT License.</small> 324 + </footer> 325 + </html>
+322
preview.ja.html
··· 1 + <!doctype html> 2 + <html lang="ja" dir="ltr"> 3 + <meta charset="utf-8" /> 4 + <meta name="viewport" content="width=device-width" /> 5 + <title>@fogtype/css</title> 6 + <link rel="stylesheet" href="index.css" /> 7 + <style> 8 + .palette { 9 + list-style: none; 10 + display: grid; 11 + grid-template-columns: repeat(auto-fill, minmax(8em, 1fr)); 12 + gap: var(--space-block-small); 13 + padding: 0; 14 + margin-block: var(--space-block-default); 15 + } 16 + .palette li { 17 + margin: 0; 18 + } 19 + .swatch { 20 + display: block; 21 + block-size: 4rlh; 22 + border: 1px solid var(--color-border); 23 + } 24 + .palette code { 25 + background: none; 26 + padding: 0; 27 + color: var(--color-text-secondary); 28 + } 29 + .palette b { 30 + display: block; 31 + } 32 + .palette small { 33 + display: block; 34 + } 35 + .alert { 36 + margin-block: var(--space-block-small); 37 + padding-block: var(--space-block-small); 38 + padding-inline: var(--space-inline-default); 39 + border-inline-start: 4px solid var(--color-text-secondary); 40 + } 41 + .alert.is-danger { 42 + border-color: var(--color-danger); 43 + } 44 + .alert.is-warning { 45 + border-color: var(--color-warning); 46 + } 47 + .alert.is-success { 48 + border-color: var(--color-success); 49 + } 50 + .alert b.is-danger { 51 + color: var(--color-danger); 52 + } 53 + .alert b.is-warning { 54 + color: var(--color-warning); 55 + } 56 + .alert b.is-success { 57 + color: var(--color-success); 58 + } 59 + .btn-row { 60 + display: flex; 61 + flex-wrap: wrap; 62 + gap: var(--space-inline-default); 63 + align-items: center; 64 + } 65 + </style> 66 + 67 + <header> 68 + <h1>@fogtype/css</h1> 69 + <p> 70 + タイポグラフィと余白だけで構造を伝える、ミニマルなクラスレスCSSフレームワーク。 71 + </p> 72 + </header> 73 + 74 + <hr /> 75 + 76 + <h2>Color Palette</h2> 77 + <ul class="palette"> 78 + <li> 79 + <span class="swatch" style="background: var(--color-primary)"></span> 80 + <b>Primary</b><code>--color-primary</code> 81 + </li> 82 + <li> 83 + <span class="swatch" style="background: var(--color-primary-dark)"></span> 84 + <b>Primary Dark</b><code>--color-primary-dark</code> 85 + </li> 86 + <li> 87 + <span 88 + class="swatch" 89 + style="background: var(--color-primary-light)" 90 + ></span> 91 + <b>Primary Light</b><code>--color-primary-light</code> 92 + </li> 93 + <li> 94 + <span class="swatch" style="background: var(--color-danger)"></span> 95 + <b>Danger</b><code>--color-danger</code> 96 + </li> 97 + <li> 98 + <span class="swatch" style="background: var(--color-warning)"></span> 99 + <b>Warning</b><code>--color-warning</code> 100 + </li> 101 + <li> 102 + <span class="swatch" style="background: var(--color-success)"></span> 103 + <b>Success</b><code>--color-success</code> 104 + </li> 105 + <li> 106 + <span class="swatch" style="background: var(--color-text)"></span> 107 + <b>Text</b><code>--color-text</code> 108 + </li> 109 + <li> 110 + <span 111 + class="swatch" 112 + style="background: var(--color-text-secondary)" 113 + ></span> 114 + <b>Text Secondary</b><code>--color-text-secondary</code> 115 + </li> 116 + <li> 117 + <span 118 + class="swatch" 119 + style="background: var(--color-text-disabled)" 120 + ></span> 121 + <b>Text Disabled</b><code>--color-text-disabled</code> 122 + </li> 123 + <li> 124 + <span class="swatch" style="background: var(--color-border)"></span> 125 + <b>Border</b><code>--color-border</code> 126 + </li> 127 + <li> 128 + <span class="swatch" style="background: var(--color-surface)"></span> 129 + <b>Surface</b><code>--color-surface</code> 130 + </li> 131 + <li> 132 + <span class="swatch" style="background: var(--color-background)"></span> 133 + <b>Background</b><code>--color-background</code> 134 + </li> 135 + </ul> 136 + 137 + <h2>Typography</h2> 138 + 139 + <h1>Heading 1 - 32px</h1> 140 + <h2>Heading 2 - 24px</h2> 141 + <h3>Heading 3 / Body - 20px</h3> 142 + 143 + <p> 144 + 本文は20px・行間1.6を基準とします。日本語とEnglishの混植では 145 + <code>text-autospace: normal</code> 146 + によって和欧間に1/4emのスペースが自動挿入されます。たとえば「Claude Opus 147 + 4.8を2026年に使う」のような文でも、約物アキは 148 + <code>text-spacing-trim</code> 149 + で調整されます。 150 + </p> 151 + 152 + <p> 153 + 強調には 154 + <em>太字(bold)</em>を、より強い意味には<strong>strong</strong>を使います。 155 + リンクは<a href="#">この通り</a>下線色で表現します。 156 + キーは<kbd>Ctrl</kbd>+<kbd>K</kbd>、 157 + 注釈は<small>このようにsmallで</small>添えます。 158 + ハイライトは<mark>markで表現します</mark>。 159 + </p> 160 + 161 + <h2>Lists</h2> 162 + 163 + <h3>順序なしリスト</h3> 164 + <ul> 165 + <li>静謐・クリーン・可読性最優先</li> 166 + <li> 167 + フラット設計 168 + <ul> 169 + <li>ネストした項目もリズムを維持</li> 170 + <li>インデントは <code>--space-inline-large</code>(40px)</li> 171 + </ul> 172 + </li> 173 + <li>活字メディア・読み物向けレイアウト</li> 174 + </ul> 175 + 176 + <h3>順序付きリスト</h3> 177 + <ol> 178 + <li>ルートfont-sizeを最低20pxに固定</li> 179 + <li>余白をrlh(32px)のリズムに揃える</li> 180 + </ol> 181 + 182 + <h3>定義リスト</h3> 183 + <dl> 184 + <dt>rlh</dt> 185 + <dd>root line-height = 1.6 × 20px = 32px。block方向の全余白の基準単位。</dd> 186 + <dt>ic</dt> 187 + <dd>全角1文字の送り幅</dd> 188 + </dl> 189 + 190 + <h2>Code</h2> 191 + <p> 192 + インラインコードは 193 + <code>--space-block-small</code> 194 + のような形で本文に溶け込みます。ブロックは横スクロールします: 195 + </p> 196 + 197 + <pre><code>:root { 198 + --color-primary: oklch(54% 0.247 293); /* ブランドカラー差し替え */ 199 + --color-primary-dark: oklch(40% 0.247 293); /* ホバー時 */ 200 + --radius: 0; /* 角張らせる */ 201 + --line-length: 50; /* 本文幅を 50ric に広げる */ 202 + }</code></pre> 203 + 204 + <h2>Table</h2> 205 + <p> 206 + テーブルはフラット、影・角丸なし。セル背景は 207 + <code>--color-surface</code>、行区切りは 208 + <code>1px solid var(--color-border)</code>。 209 + </p> 210 + 211 + <table> 212 + <caption> 213 + Type Scale 214 + </caption> 215 + <thead> 216 + <tr> 217 + <th>Role</th> 218 + <th>Token</th> 219 + <th>Size</th> 220 + <th>Line Height</th> 221 + </tr> 222 + </thead> 223 + <tbody> 224 + <tr> 225 + <td>Heading 1</td> 226 + <td><code>--text-huge</code></td> 227 + <td>32px</td> 228 + <td>1.2</td> 229 + </tr> 230 + <tr> 231 + <td>Heading 2</td> 232 + <td><code>--text-large</code></td> 233 + <td>24px</td> 234 + <td>1.2</td> 235 + </tr> 236 + <tr> 237 + <td>Heading 3 / Body</td> 238 + <td><code>--text-default</code></td> 239 + <td>20px</td> 240 + <td>1.6</td> 241 + </tr> 242 + <tr> 243 + <td>Caption / Small</td> 244 + <td><code>--text-small</code></td> 245 + <td>15px</td> 246 + <td>1.6</td> 247 + </tr> 248 + </tbody> 249 + </table> 250 + 251 + <h2>Semantic Colors</h2> 252 + 253 + <div class="alert is-danger"> 254 + <b class="is-danger">エラー</b>: 255 + 入力された値が正しくありません。<code>--color-danger</code>を使用します。 256 + </div> 257 + <div class="alert is-warning"> 258 + <b class="is-warning">警告</b>: 259 + この操作は取り消せません。<code>--color-warning</code>を使用します。 260 + </div> 261 + <div class="alert is-success"> 262 + <b class="is-success">完了</b>: 263 + 変更を保存しました。<code>--color-success</code>を使用します。 264 + </div> 265 + 266 + <h2>Buttons</h2> 267 + <p> 268 + 角は控えめな角丸(<code>border-radius: var(--radius)</code>)。 269 + 高さはタッチターゲットの最小サイズ基準に適合。 270 + </p> 271 + <p class="btn-row"> 272 + <button type="submit">Primary</button> 273 + <button type="reset">Secondary</button> 274 + <button type="button" disabled>Disabled</button> 275 + </p> 276 + 277 + <h2>Forms</h2> 278 + <form onsubmit="return false;"> 279 + <p> 280 + <label for="name">お名前</label> 281 + <input id="name" type="text" placeholder="山田 太朗" /> 282 + </p> 283 + <p> 284 + <label for="email">メールアドレス</label> 285 + <input id="email" type="email" placeholder="name@example.com" /> 286 + </p> 287 + <p> 288 + <label for="theme">テーマ</label> 289 + <select id="theme"> 290 + <option>ライト</option> 291 + <option>ダーク</option> 292 + <option>自動</option> 293 + </select> 294 + </p> 295 + <p> 296 + <label for="message">メッセージ</label> 297 + <textarea id="message" placeholder="ご自由にお書きください"></textarea> 298 + </p> 299 + 300 + <fieldset> 301 + <legend>表示設定</legend> 302 + <p> 303 + <label><input type="checkbox" checked /> ルビを表示</label> 304 + </p> 305 + <p> 306 + <label><input type="radio" name="lh" checked /> ゆったり</label> 307 + <label><input type="radio" name="lh" /> まったり</label> 308 + </p> 309 + </fieldset> 310 + 311 + <p class="btn-row"> 312 + <button type="submit">送信する</button> 313 + <button type="reset">リセット</button> 314 + </p> 315 + </form> 316 + 317 + <hr /> 318 + 319 + <footer> 320 + <small>@fogtype/css - A classless CSS framework. MIT License.</small> 321 + </footer> 322 + </html>