展示
Heading 标题
一个标题,元素和字号是两个各自独立的决定。
用法
什么时候用它
import { Heading } from '@misoto22/design'说明
一个标题,元素和字号分开决定。
每一个只收一个数字的标题组件都会在这里搞错,而且只有两种错法:要么为了拿到一个字号把大纲掰弯(页面中间冒出一个 <h1>,只因为设计想要大字),要么为了守住大纲把字号掰弯(一个区块标题被压到 20px,只因为它排在第四级)。两种都只差一个 prop 就对了,所以这里给了两个。
level 是文档,size 是页面。默认值经由这套系统的字号阶把两者绑在一起,所以只写 level 就是对的——而一旦它们真的要分开,调用处会把这件事说出来。
和这套系统里每一个标题一样,用书刊衬线体、字重 400。它还带着 scroll-margin-top,所以一个有 id、被目录链过来的标题会停在顶栏下面,而不是被顶栏盖住。
结构
| 部件 | 说明 |
|---|---|
| Element必填 | level, 1 to 6, rendered as the matching <h1>–<h6>. This is the document outline — what a screen reader navigates by — so it follows the section the heading opens, never the size it wants to be. |
| Step必填 | size, one of title, lead, heading, sub, item and label. Defaults from level through the system ladder, so writing only level is correct. |
| Anchor offset必填 | scroll-margin-top: var(--scroll-offset), carried by every heading, so one given an id and linked from a table of contents comes to rest below the masthead instead of under it. |
实践建议
推荐
- Write level alone unless the outline and the design genuinely disagree. The default ladder is 1→title, 2→heading, 3→sub, 4→item, 5 and 6→label — the same map article.css applies to rendered Markdown, which is what makes a post and a component page read as one publication.
- Notice that the default ladder SKIPS lead between levels 1 and 2, and skip a step yourself when you set size by hand: --fs-lead over --fs-heading is a ratio of 1.14 and reads as a rendering accident, where --fs-title over --fs-heading is 1.86 and reads as a hierarchy.
- Give a heading an id when anything links to it. The component already carries the scroll offset the anchor needs; nothing else on the page does.
避免
- Do not raise level to get a bigger heading. Two <h1>s on a page make its outline unnavigable, and size is one prop away.
- Do not reach past size="title". The ladder ends there because a page has exactly one thing larger than its own records; a bigger heading is className territory and it is the moment the page stopped being in the system.
- size="label" is the mono kicker at 11px and --ink-3-aa, not a small serif heading — it is what levels 5 and 6 should look like, and setting it on an <h2> makes the section title read as metadata.
示例
level and size
The two decisions, apart. level is the document outline — what a screen reader navigates by — and size is the page. The default binds them through the system ladder, which SKIPS a step between the first two: --fs-lead over --fs-heading is a ratio of 1.14 and reads as an accident, where --fs-title over --fs-heading is 1.86 and reads as a hierarchy. The mono eyebrow is the ladder's fifth rung, worn here by an h4 so this run does not skip a level in the outline; the last pair is a semantically-correct h3 that had to look like a page title.
The White Reset
A record title
A sub-head inside it
Metadata
Third level, page-title sized
The last one is an h3. Nothing about the outline moved.
anchored headings
Two headings a table of contents can link into. Every Heading carries scroll-margin-top: var(--scroll-offset), so one given an id comes to rest below the masthead rather than under it — nothing else on a page does that, which is why an anchor into a hand-rolled h2 lands with its own title hidden behind the bar. The id is the caller's, and it has to be stable: it is what every link to this section already says.
Installation
One package, and one stylesheet next to it.
Upgrading
Minor versions add exports; they never move one.
a fragment that starts at h2
A panel dropped into a page that already has its h1. The outline decides level — this opens a section, so it is an h2 and its sub-heads are h3s — and size decides how big it looks, which is the whole reason they are two props. Raising level to reach the larger step would give the page two first-level headings and an outline nobody can navigate, for a difference one prop already covers.
Publish 0.4.1
What ships
Five display components, and the examples that explain them.
What it breaks
Nothing — every export in 0.4.0 is still exported here.
类型
export type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6
export type HeadingSize = 'title' | 'lead' | 'heading' | 'sub' | 'item' | 'label'无障碍
- level 渲染的是真正的标题元素,所以这份大纲是能被导航的,而不只是看得见。
- 两个决定是两个 prop,正是这一点让一个语义上正确的 h3 可以长得像页面标题,而不必把大纲掰弯。
- 带 scroll-margin-top,所以锚点跳过去的标题不会被固定的顶栏盖住(实践中的 WCAG 2.4.7)。