Sections and grids
Try it yourself
<script>
import { ContentGrid, ContentBlock } from '@page-sections/svelte';
</script>
<div style="max-width: 100%">
<ContentGrid>
<ContentBlock span={{"xs":4,"s":3,"m":5,"l":8}}>Main story</ContentBlock>
<ContentBlock span={{"xs":4,"s":3,"m":3,"l":4}}>Related thought</ContentBlock>
</ContentGrid>
</div> Section gives ordinary content a semantic region, anchor, spacing and optional background. ContentGrid and ContentBlock arrange explicit content inside it. Use them when a page needs an article/aside pair, feature columns or other layouts that vary with available width.
<script>
import {
ContentPage,
Section,
ContentGrid,
ContentBlock
} from '@page-sections/svelte';
</script>
<ContentPage page={{ title: 'Visit the garden' }}>
<Section
section={{
id: 'visit',
title: 'Visit',
headline: 'Make a day of it',
background: { color: 'muted' }
}}
>
<ContentGrid>
<ContentBlock span={{ xs: 4, s: 3, m: 5, l: 8 }}>
<h3>What to bring</h3>
<p>Comfortable shoes and a little curiosity.</p>
</ContentBlock>
<ContentBlock span={{ xs: 4, s: 3, m: 3, l: 4 }}>
<h3>Opening hours</h3>
<p>Saturdays, 10 am–2 pm.</p>
</ContentBlock>
</ContentGrid>
</Section>
</ContentPage> Section props
section: SectionDefinition is required. children?: Snippet supplies content. Section also accepts HTMLAttributes<HTMLElement> except id and the ordinary children attribute; its own class is combined with the library class.
Component-owned ID, accessibility and layout attributes are computed from section metadata. Do
not depend on overriding them through forwarded attributes.
Complete SectionDefinition
| Field | Type | Default / behavior |
|---|---|---|
id | string, required | Page-local anchor; registered IDs match ^[a-z][a-z0-9-]*$ |
title | string, required | Nonblank navigation/accessibility label |
headline | string | No visible heading unless supplied |
eyebrow | string | Optional text before heading |
introduction | string | Optional introductory paragraph |
headingLevel | HeadingLevel (1-6) | Inherited; standalone 2 |
headingSize | HeadingSize: m, l, xl | Independent of semantics; l by default, m for the content variant |
background | SectionBackground | Transparent, standard width |
layout | 'full', 'wide', 'narrow', 'inherit' | inherit |
spacing | 'none', 'tight', 'normal', 'loose', 'spacious' | normal; nested sections default to none |
divider | 'none', 'top', 'bottom', 'both' | none |
variant | 'default', 'content', 'feature' | Default grid headings, content headings or larger feature headings |
style | { width?: string; color?: string } | Optional CSS width/color overrides |
layout: 'narrow' caps at --ps-narrow-max (780px); wide caps at the
canonical 1536px. Inherit fills the parent. Inside ContentPage, full layout also respects
the page's content column and its 1536px limit, including asymmetric sidebar layouts. Use background.size: 'full' to paint a viewport-wide background independently of content width. Outside ContentPage, full
layout uses 100vw with centered negative margins. style.width normally
caps at the available width.
Vertical padding is 0, 0.5, 1, 2 or 4 times the active grid gap for
none/tight/normal/loose/spacious. Inset sections retain one horizontal gutter pair even with
spacing none. Dividers are 1px borders using --ps-border. Variants select
default grid headings, content headings or larger feature headings.
ContentGrid and ContentBlock props
| Component | Props |
|---|---|
| ContentGrid | Optional children: Snippet and standard div HTML attributes, including class/style |
| ContentBlock | The same, plus optional span: ContentSpan |
ContentSpan is number or Partial<Record<ContentGridSize, number>>, where ContentGridSize is xs, s, m, l. Missing spans fill a row.
An object inherits the last smaller configured span; before its first configured value, it
fills the row. Positive integers clamp to available columns; invalid numbers fill the row.
ContentBlock warns about invalid/clamped values in a client effect; these warnings are not
development-only.
Section establishes a named container before its inner padding. ContentGrid
adds no second outer padding. Standalone grids need a .ps-content-container ancestor
to respond to container width; without one, base XS rules apply. Grid rows use normal flow, not
dense backfilling, so DOM and keyboard order stay intact.
Section renders the inherited heading level (standalone h2, up to h6) when headline is set; otherwise the region uses title as its accessible label. Standalone sections work without a registry, while sections in ContentPage register and update automatically. Neither grid component introduces a heading or landmark. CSS layout works in the first SSR response.
Related: Responsive Layout and Breakpoints, Section Backgrounds and Surface Groups.
Nested sections and diagnostics
renderHeader defaults to true; disable it only when a specialized renderer
supplies the matching headline ID itself. inset defaults to true for top-level sections
and false for nested text/panels. Grid renderers set inset=true to establish their own single
gutter pair. Nested spacing defaults to none; top-level spacing defaults to normal. Spacing factors
none/tight/normal/loose/spacious are 0/0.5/1/2/4 times the active grid gap.
onDiagnostic?: (diagnostic: SectionBackgroundDiagnostic) => void receives normalization
diagnostics after hydration, once per requested color/size/context combination. It can update
host state. Page kind is inherited from SectionSurfaceGroup; normalization itself also applies
during SSR.