Themes and styling

Page Sections provides CSS defaults without requiring a utility framework. Set shared variables on an ancestor, or use PageShell to scope a typed theme across navigation and page content.

svelte
<script>
  import { PageShell, ContentPage, Section } from '@page-sections/svelte';
</script>

<PageShell
  mode="light"
  theme={{
    accent: '#286449',
    radius: '12px',
    fontFamily: 'Georgia, serif',
    narrowMax: '720px'
  }}
>
  <ContentPage page={{ title: 'Garden journal' }}>
    <Section
      section={{
        id: 'news',
        title: 'News',
        headline: 'A new season',
        background: { color: 'muted' }
      }}
    >
      <p>A theme follows the content wherever it is used.</p>
    </Section>
  </ContentPage>
</PageShell>

Complete PageTheme mapping

Every property is an optional CSS string, including units where needed.

PageTheme propertyCSS variable
background--ps-background
ink--ps-ink
body--ps-body
accent--ps-accent
standard--ps-section-standard
muted--ps-section-muted
radius--ps-radius
onAccent--ps-on-accent
narrowMax--ps-narrow-max
fontFamily--ps-font-family

PageShell applies these to its div; ContentPage.theme applies them to its main element. The themeStyle core helper performs the mapping and rejects unknown keys and values containing declaration delimiters. It is not a full CSS value validator. Variables outside this table, such as --ps-border, can be set in CSS.

Light and dark modes

PageShell accepts mode: 'light' | 'dark'. Dark mode changes the palette variables listed in the CSS reference. An explicit theme on the same element overrides that palette through inline CSS.

The host owns system-preference detection, persistence and initial server-side selection. Omitting mode does not automatically switch the palette. The stylesheet has no light-reset selector: nesting a light shell inside a dark shell inherits dark variables unless you explicitly supply a light palette. Image uses the nearest PageShell's mode context for srcDark; absent an explicit mode, its picture source uses the OS preference independently.

Integrate an existing design system

css
.site-theme {
  --ps-accent: var(--brand-link);
  --ps-ink: var(--text-primary);
  --ps-body: var(--text-secondary);
  --ps-section-standard: var(--surface);
  --ps-section-muted: var(--surface-muted);
  --ps-radius: 12px;
}

Place this class on an ancestor around the components and define the host variables. Shared styles also scope font, link and focus rules to .ps-shell, .ps-page and .ps-navigation; use a PageShell or equivalent class when composing low-level components independently.

Geometry is a shared contract: viewport thresholds, grid columns/gaps, catalog sizes and the 1536px content/menu cap come from layoutTokens. Per-size grid override inputs and PageTheme.contentMax were removed in 0.2. Use narrowMax with page.bodyLayout or section.layout for reading widths. Colors, font family and radius remain theme controls.

Section variant selects default grid typography, content headings or larger feature headings. Most high-level components do not forward arbitrary class/style props; use the documented theme and section fields or ancestor CSS. See the Svelte API for forwarding exceptions.

Related: Section Backgrounds and Surface Groups, CSS Variables and Layout Tokens.