Skip to content
RU
Scale
Density
Theme
Accent

Layout

Section

A named block inside a screen: a label, optional actions and contents. The label is quieter than the data it labels.

The component

The summary for the day

In work
7
In the queue
5
Fell
1
Markup
<div class="inst-section">
  <div class="inst-section-head">
    <h2 class="inst-section-title">The summary for the day</h2>
    <span class="inst-section-actions">
      <button class="inst-btn inst-btn--sm inst-btn--ghost" type="button">Period</button></span>
  </div>
  <div class="inst-grid inst-grid--tight">
    <div class="inst-metric"><div class="inst-metric-label">In work</div><div class="inst-metric-value">7</div></div>
    <div class="inst-metric"><div class="inst-metric-label">In the queue</div><div class="inst-metric-value">5</div></div>
    <div class="inst-metric"><div class="inst-metric-label">Fell</div><div class="inst-metric-value">1</div></div>
  </div>
</div>

Contract

What Required Why
A real heading of the wanted level yes inst-section-title styles but does not declare: navigation by headings does not work without it
A <section> or a <div> no The tag changes no role: a section draws nothing except rhythm
An inst-section-head no Wanted where there is a heading or there are actions
An inst-section-actions — for this block alone yes Actions at the level of a screen live in the page header

A section draws nothing except rhythm: it is a stack with a gap of --gap-row and a row of heading. A border around four metrics would turn one group into four objects.

What Why
The tag of the heading by level (<h2>, <h3>) The class gives the size rather than the level. A screen reader builds the table of contents from the tags
An inst-section-head as the wrapper Without it the heading and the actions become children of the column and line up one under another
A type="button" on the actions Otherwise inside a form they will submit it

Accessibility

The level of the heading Chosen by the structure of the document rather than by the look. It is not assigned automatically
The landmark If the block really is a self-standing division, put a <section> with an aria-labelledby on the heading; a <div> gives no landmark, and that is fine for grouping
Contrast The label is --text-muted, 4.5:1 in five themes. It is quieter than the data by colour, but not below the floor of reading
Type size The rung its rank asks for; --text-xs by default, a rung under the base of the document, so the label is smaller than the contents it labels
Order The actions stand after the heading in the markup and are traversed after it

Anatomy

Example

Active runs

7
worldgen · #4127
worldgen · #4126
Markup
<div class="inst-section">
  <div class="inst-section-head">
    <h2 class="inst-section-title">Active runs</h2>
    <span class="inst-badge inst-nav-count">7</span>
    <span class="inst-section-actions">
      <button class="inst-btn inst-btn--sm inst-btn--ghost" type="button">All</button></span>
  </div>
  <div class="inst-stack inst-stack--tight">
    <div class="inst-card"><div class="inst-card-title">worldgen · #4127</div></div>
    <div class="inst-card"><div class="inst-card-title">worldgen · #4126</div></div>
  </div>
</div>

inst-section-head aligns its children to the baseline: the heading, the counter and the button stand on one line of text rather than by the centres of their boxes. So anything at all can be put into the heading row without fitting heights to one another.

inst-section-actions is pushed to the far edge by margin-inline-start: auto — by the same device as inst-cluster-spacer and inst-page-actions. One axis — one mechanism.

The heading

inst-section-title is --weight-normal and --text-muted, and its size comes from rank: --text-xs by default, a rung up for lead, a rung down for support. The weight stays normal at every rank — weight is binary in this kit and already spent on labels, which is why size had to become sayable at all. That is, quieter than the contents: the label serves the data. There are no caps and no tracking here for the same reason as everywhere in the library, and a weight of 700 does not exist in the library at all.

The class sets the size but not the level. The level is chosen by the place in the structure of the document: under the <h1> of the page header it is usually an <h2>.

Composition

Several sections on a screen

<div class="inst-container inst-stack inst-stack--loose">
  <div class="inst-page-header">…</div>
  <div class="inst-section">…</div>
  <div class="inst-section">…</div>
</div>

The gap between sections is set by the outer stack rather than by the sections themselves: a gap is between neighbours rather than around each one.

A section with no actions

<div class="inst-section">
  <div class="inst-section-head">
    <h2 class="inst-section-title">The parameters of a run</h2>
  </div>
  <div class="inst-kv">…</div>
</div>

API

Classes
NameWhat it does
class
inst-sectionA column with a gap of --gap-row
inst-section-headThe row of the heading. Aligned to the baseline
inst-section-titleThe label of a section
inst-section-actionsThe tail of the heading row, pushed to the far edge
Attributes
NameValueWhat it does
attribute
data-rank—How much attention this section asks for: lead / default / support
Tokens
NameValueWhere from
token
--gap-rowvar(--space-3)base +14: density · scale
--gap-inlinevar(--space-4)base +14: density · scale
--region-title-sizevar(--region-title-default)base +3:
--region-title-inkvar(--text-primary)base +2:
--weight-normal400one across every cell
--text-mutedlight-dark(var(--n-8), var(--n-6))one across every cell

Why the kit works this way — the constitution · Open source under MIT, github.com/keshon/instrument