Sumi.css: Een minimalistisch, 'classless-first' CSS-framework
Het framework bestaat uit één enkel bestand en vereist geen build-stap. De geminificeerde en gegzipped versie is slechts 6,7 KB, bevat geen JavaScript en heeft geen afhankelijkheden.
Belangrijkste kenmerken:
- Standaard klasseloos: Koppen, formulieren, tabellen, kaarten, accordeons, modals en navigatie worden gestyled op basis van het HTML-element alleen.
- Lichte en donkere modus: Het volgt automatisch de systeeminstellingen van de bezoeker; via
data-themekan een specifieke modus worden afgedwongen. - Eenvoudig thema's aanpassen: Elke kleur, lettertype, grootte en radius is gedefinieerd als een CSS custom property.
- Eenvoudig te overschrijven: Elementstijlen hebben een specificiteit van nul, waardoor je eigen CSS altijd voorrang krijgt zonder dat
!importantnodig is. - Toegankelijk: Voorzien van zichtbare focus-ringen, ARIA-gestuurde statussen (
aria-invalid,aria-busy,aria-current) en ondersteuning voor verminderde beweging (reduced motion).
Installatie
Download
Download sumi.min.css, kopieer dit in je project en link ernaar:
<link rel="stylesheet" href="sumi.min.css">
CDN
Laad het framework direct vanuit de repository via jsDelivr:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/vladocar/Sumi.css/sumi.min.css">
Tip: Gebruik sumi.css (niet-geminificeerd) tijdens de ontwikkeling; de commentaren in het bestand leggen elke sectie uit.
Snelstart
<!doctype html>
<html lang="nl">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Mijn pagina</title>
<link rel="stylesheet" href="sumi.min.css">
</head>
<body>
<header>
<nav>
<ul><li><strong>Mijn site</strong></li></ul>
<ul>
<li><a href="/" aria-current="page">Home</a></li>
<li><a href="/about">Over</a></li>
</ul>
</nav>
</header>
<main>
<hgroup>
<h6>Welkom</h6>
<h1>Hallo, inkt.</h1>
</hgroup>
<p class="lead">Deze pagina is gestyled met Sumi, met bijna geen klassen.</p>
<a href="#start" role="button">Aan de slag</a>
</main>
<footer>
<p>© 2026 Mijn site</p>
</footer>
</body>
</html>
De elementen <header>, <main> en <footer> centreren zichzelf wanneer ze directe kinderen zijn van <body>. Behoud de viewport meta-tag voor mobiele apparaten en stel lang correct in, zodat de browser lange woorden correct kan afbreken.
Wat wordt er gestyled?
| Element | Resultaat |
|---|---|
h1–h6, p, lijsten, blockquote, code, kbd, pre, mark | Vloeiende typografische schaal en consistente verticale spatiëring |
<nav> met twee <ul> | Navigatiebalk met linker- en rechtergroepen. Verticaal binnen een <aside> |
<button>, [type=submit], <a role="button"> | Knoppen |
<input>, <select>, <textarea>, <label>, <fieldset> | Volledig breedte velden met focus-ringen en helpteksten |
type="checkbox", type="radio", type="range", type="file", type="color" | Custom controls die passen bij het thema |
<table> | Strakke lijnen en tabulaire cijfers |
<article> | Kaart. Een directe <header> en <footer> worden gearceerde banden |
<details> / <summary> | Accordeon met een geanimeerde chevron |
<dialog> | Modal met een vervaagde achtergrond |
<progress>, <meter> | Bepaalde en onbepaalde voortgangsbalken |
Klassen en attributen
Naast standaard HTML reageert Sumi op de volgende klassen en attributen:
Layout en Structuur
| Class of attribuut | Toegepast op | Effect |
|---|---|---|
.container, .container-fluid, .narrow | elk blok | Gecentreerde paginabreedte (72rem), volledige breedte, leesbreedte (44rem) |
.grid | wrapper | Auto-fitting kolommen, elk minimaal --s-grid-min (14rem) breed |
.cols-2, .cols-3, .cols-4, .cols-6, .cols-12 | .grid | Vaste kolommen vanaf 48rem breedte, één kolom daaronder |
.span-2 … .span-9, .span-full | grid-child | Beslaat meerdere kolommen |
.row, .spread, .stack | wrapper | Wrapping flex-rij, rij met ruimte ertussen, verticale stapel |
Typografie en Inhoud
| Class of attribuut | Toegepast op | Effect |
|---|---|---|
.display, .lead | kop, paragraaf | Hero-koptekst, grotere introductieparagraaf |
.prose, .serif | tekstwrapper | Kolom voor lange teksten, serif-lettertype |
Interactie en Componenten
| Class of attribuut | Toegepast op | Effect |
|---|---|---|
.secondary, .contrast, .outline | knop | Kleuren voor knoppen en outline-stijl |
.small, .large, .full | knop | Groottes, volledige breedte |
role="button" | <a> | Link gestyled als knop |
role="group" | wrapper | Voegt knoppen samen, of een input en een knop |
role="switch" | checkbox | Toggle-switch |
aria-invalid="true" / "false" | veld | Rode of groene validatiestatus |
aria-busy="true" | elk element | Laad-spinner |
aria-current="page" | nav-link | Markeert de huidige pagina |
data-tooltip="…", data-placement="bottom" | elk element | Tooltip, boven of onder |
data-theme="light" / "dark" | <html> of elk element | Forceert een kleurmodus |
.dropdown, .right | <details> | Dropdown-menu, rechts uitgelijnd |
.callout + .success, .warning, .danger | blok | Berichtvenster |
.striped | <table> | Zebra-rijen |
.muted, .small, .center, .sr-only, .overflow-auto | elk element | Utilities |
Voorbeelden
Knoppen
<button>Opslaan</button>
<button class="secondary outline">Annuleren</button>
<button aria-busy="true">Opslaan...</button>
Veld met helptekst en validatie
<label>Email
<input type="email" name="email" aria-invalid="true" aria-describedby="email-help">
<small id="email-help">Voer een geldig e-mailadres in.</small>
</label>
Switch
<label><input type="checkbox" role="switch" checked> E-mail herinneringen</label>
Kaart (Card)
<article>
<header><strong>Cursus van zes weken</strong></header>
<p>Van de eerste penseelstreken tot een voltooide hangende rol.</p>
<footer><a href="#book" role="button" class="full">€180</a></footer>
</article>
Dropdown
<details class="dropdown">
<summary>Exporteren als…</summary>
<ul>
<li><a href="#">PNG</a></li>
<li><a href="#">SVG</a></li>
</ul>
</details>
Modal
Openen met dialog.showModal(); het formulier sluit de modal.
<dialog id="confirm">
<article>
<header><h3>Dit bestand verwijderen?</h3></header>
<p>Deze actie kan niet ongedaan worden gemaakt.</p>
<footer>
<form method="dialog" class="row">
<button class="secondary outline">Behouden</button>
<button class="contrast">Verwijderen</button>
</form>
</footer>
</article>
</dialog>
Lay-out
Automatische kolommen (stapelt op mobiel):
<div class="grid">
<div>Eén</div>
<div>Twee</div>
<div>Drie</div>
</div>
12-koloms lay-out vanaf tabletbreedte:
<div class="grid cols-12">
<div class="span-8">Hoofdinhoud</div>
<div class="span-4">Zijbalk</div>
</div>
Minimale kolombreedte aanpassen voor één specifieke grid:
<div class="grid" style="--s-grid-min: 10rem">…</div>
Kaarten binnen een .grid worden automatisch uitgerekt naar gelijke hoogte en houden hun footers onderaan uitgelijnd.
Typografie
Koppen volgen een vloeiende schaal. De ratio groeit van 1.2 op telefoons naar 1.28 op desktop, en de basisgrootte loopt op van 16px naar 17px. Er zijn geen media queries nodig aan jouw kant. De regelafstand en letterspatiëring worden kleiner naarmate de koppen groter worden.
<hgroup>koppelt een kop aan een 'eyebrow' (<h6>ervoor) en een ondertitel (<p>erna)..leadvergroot een introductieparagraaf..displaymaakt een hero-koptekst..prosestelt een leeskolom in van ongeveer 68 tekens met afbrekingen. Een<article class="prose">blijft platte tekst in plaats van een kaart te worden..serifschakelt een element, of de gehele<body>, om naar een systeem-serif stack.
Theming
Elke ontwerpbeslissing is een custom property die begint met --s-. Je kunt deze overschrijven in een stylesheet die na Sumi wordt geladen:
:root {
--s-primary: #0f766e;
--s-radius: .25rem;
--s-font-body: "Inter", system-ui, sans-serif;
--s-font-heading: "Fraunces", Georgia, serif;
--s-container: 64rem;
}
Tokens werken ook op een enkel element:
<div class="row" style="--s-primary: #b4235a; --s-radius: 999px">
<button>Nu boeken</button>
<button class="outline">Cadeaubon</button>
</div>
Belangrijkste tokens
| Token | Controleert |
|---|---|
--s-primary, --s-on-primary | Knoppen, links, focus-ringen, geselecteerde controls en de tekst daarop |
--s-secondary, --s-contrast | Kleuren voor secundaire en contrastknoppen |
--s-bg, --s-surface, --s-card | Pagina, gearceerde gebieden, kaarten |
--s-text, --s-muted | Body-tekst, secundaire tekst |
--s-border, --s-border-strong | Lijnen, kaartranden, veldranden |
--s-success, --s-warning, --s-danger | Validatie en callouts |
--s-font-body, --s-font-heading, --s-font-mono, --s-font-serif | Lettertypes |
--s-font-size, --s-line-height, --s-heading-weight | Basisgrootte, regelafstand, gewicht van koppen |
--s-text-display, --s-text-h1 … --s-text-h4, --s-text-lead | Stappen in de typografische schaal |
--s-flow, --s-space | Ruimte na tekstblokken, ruimte na formulieren en componenten |
--s-container, --s-narrow, --s-measure, --s-gutter | Paginabreedte, leesbreedte, regelbreedte, zij-padding |
--s-radius, --s-shadow, --s-shadow-lg | Hoeken en schaduwen (elevatie) |
De volledige lijst is bovenaan in sumi.css te vinden.
Donkere modus
Sumi volgt de systeeminstellingen van de bezoeker zonder extra code. Om een modus te forceren, zet je data-theme op <html>:
<html lang="nl" data-theme="dark">
data-theme werkt ook op elk willekeurig element, waardoor één sectie donker kan zijn binnen een lichte pagina.
Voorbeeld van een thema-switch die de keuze van de bezoeker onthoudt:
const root = document.documentElement;
const saved = localStorage.getItem('theme');
if (saved) root.dataset.theme = saved;
document.querySelector('#theme-toggle').addEventListener('click', () => {
const dark = matchMedia('(prefers-color-scheme: dark)').matches;
const current = root.dataset.theme || (dark ? 'dark' : 'light');
const next = current === 'dark' ? 'light' : 'dark';
root.dataset.theme = next;
localStorage.setItem('theme', next);
});
Het donkere palet komt twee keer voor in sumi.css: één keer voor de systeeminstelling en één keer voor data-theme="dark". Als je de donkere kleuren aanpast, wijzig dan beide blokken.
Stijlen overschrijven
Elementstijlen zijn ingepakt in :where(), wat een specificiteit van nul heeft. Een gewone selector is dus voldoende om ze te overschrijven:
/* Sumi: :where(blockquote) { border-left: 3px solid … } */
blockquote { border-left-color: var(--s-warning); }
Je kunt eigen componenten bouwen met de tokens van Sumi, waardoor ze automatisch meegaan in je thema en de donkere modus:
.badge {
padding: .1em .55em;
border: 1px solid var(--s-border);
border-radius: 999px;
background: var(--s-surface);
color: var(--s-muted);
font-size: .8rem;
}
Browserondersteuning
Huidige versies van Chrome, Edge, Firefox en Safari. Sumi maakt gebruik van :where(), :has() en color-mix(), die beschikbaar zijn vanaf Chrome en Edge 111, Firefox 121 en Safari 16.2. Oudere browsers tonen nog steeds leesbare pagina's, maar met simpelere hover- en focuskleuren.
Bestanden
| Bestand | Doel |
|---|---|
sumi.css | Bronbestand met commentaren, voor ontwikkeling |
sumi.min.css | Geminificeerde build, voor productie |
docs.html | Overzicht van alle componenten met HTML, een light/dark switch en een live token-editor |
tutorial.html | Stap-voor-stap gids voor het bouwen van een pagina met Sumi |
Om het geminificeerde bestand opnieuw te genereren na het bewerken van de bron: npx lightningcss-cli --minify sumi.css -o sumi.min.css
Licentie
MIT © 2026 Vladimir Carrer
Groetjes,