Getting Started
Add these lines to your HTML:
<!-- In your <head> -->
<link rel="stylesheet" href="css/semantic.css">
<!-- Before closing </body> -->
<script src="js/semantic.js"></script>
<script>Semantic.init();</script>
Philosophy
Semantic CSS uses three mechanisms for styling:
Semantic HTML elements - Use the right element for the job (<article>, <nav>, <header>)
Attribute selectors - Style via attributes like layout="grid" or variant="primary"
CSS custom properties - Override design tokens to customize
Example Page
<body>
<header layout="row" justify="between" align="center" p="md">
<strong>My Site</strong>
<nav layout="row" gap="md">
<a href="/">Home</a>
<a href="/about">About</a>
</nav>
</header>
<main size="md" py="xl">
<h1>Welcome</h1>
<p>Semantic HTML with attribute-based styling.</p>
<section layout="grid" cols="auto" gap="lg">
<article variant="elevated">
<h3>Feature One</h3>
<p>Description here.</p>
</article>
<article variant="elevated">
<h3>Feature Two</h3>
<p>Description here.</p>
</article>
</section>
</main>
<footer p="lg" text="center" border="top">
<small>Made with semantic HTML</small>
</footer>
</body>
Typography
Semantic elements are styled automatically. No classes needed.
Headings
Heading 1
Heading 2
Heading 3
Heading 4
Heading 5
Heading 6
<h1>Heading 1</h1>
<h2>Heading 2</h2>
<h3>Heading 3</h3>
<h4>Heading 4</h4>
<h5>Heading 5</h5>
<h6>Heading 6</h6>
Paragraphs & Inline Elements
This is a paragraph with bold text , italic text , and a link .
You can also use highlighted text , small text , and inline code.
The January 29, 2025 element provides semantic dates.
<p>This is a paragraph with <strong>bold text</strong>, <em>italic text</em>, and <a href="#">a link</a>.</p>
<p>You can also use <mark>highlighted text</mark>, <small>small text</small>, and <code>inline code</code>.</p>
<p>The <time datetime="2025-01-29">January 29, 2025</time> element provides semantic dates.</p>
Blockquotes
The best way to predict the future is to invent it.
— Alan Kay
<blockquote>
The best way to predict the future is to invent it.
<cite>— Alan Kay</cite>
</blockquote>
Lists
Unordered List
First item
Second item
Third item
Ordered List
First step
Second step
Third step
Code Blocks
function greet(name) {
return `Hello, ${name}!`;
}
console.log(greet('World'));
Text Attributes
Centered text with text="center"
Serif font with font="serif"
Bold weight with weight="bold"
Large size with size="lg"
Primary color with color="primary"
Muted color with color="muted"
<p text="center">Centered text</p>
<p font="serif">Serif font</p>
<p weight="bold">Bold weight</p>
<p size="lg">Large size</p>
<p color="primary">Primary color</p>
<p color="muted">Muted color</p>
Layout
Use attributes to control layout without classes.
Container Sizing
The <main> element acts as a container with optional size variants:
<main>...</main> <!-- Default: 80rem -->
<main size="sm">...</main> <!-- 40rem -->
<main size="md">...</main> <!-- 48rem -->
<main size="lg">...</main> <!-- 64rem -->
<main size="full">...</main> <!-- 100% -->
Flex Layouts
Flex item 1
Flex item 2
Flex item 3
<section layout="row" gap="md">
<div grow>Flex item 1</div>
<div grow>Flex item 2</div>
<div grow>Flex item 3</div>
</section>
Stack (Vertical) Layout
Stack item 1
Stack item 2
Stack item 3
<section layout="stack" gap="sm">
<div>Stack item 1</div>
<div>Stack item 2</div>
<div>Stack item 3</div>
</section>
Grid Layouts
Add responsive for single column on mobile
<section layout="grid" cols="3" gap="md" responsive>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
</section>
Auto-fit Grid
Auto 1
Auto 2
Auto 3
Auto 4
<section layout="grid" cols="auto" gap="md">
<div>Auto 1</div>
<div>Auto 2</div>
<div>Auto 3</div>
<div>Auto 4</div>
</section>
Alignment
<section layout="row" justify="between" align="center">
<span>Left</span>
<span>Center</span>
<span>Right</span>
</section>
Layout Attribute Reference
Attribute
Values
Description
layout
flex, grid, stack, row, center
Display type
cols
1-6, 12, auto, auto-fill
Grid columns
gap
0, xs, sm, md, lg, xl, 2xl
Gap between items
align
start, center, end, stretch, baseline
Cross-axis alignment
justify
start, center, end, between, around, evenly
Main-axis alignment
wrap
(boolean)
Enable flex wrap
Spacing
Control padding and margin with intuitive attributes.
Padding
p="xs" (0.25rem)
p="sm" (0.5rem)
p="md" (1rem)
p="lg" (1.5rem)
p="xl" (2rem)
<div p="xs">...</div> <!-- 0.25rem all sides -->
<div p="md">...</div> <!-- 1rem all sides -->
<div px="lg">...</div> <!-- 1.5rem left/right -->
<div py="xl">...</div> <!-- 2rem top/bottom -->
<div pt="md">...</div> <!-- 1rem top only -->
Margin
<div m="md">...</div> <!-- 1rem all sides -->
<div mx="auto">...</div> <!-- center horizontally -->
<div my="xl">...</div> <!-- 2rem top/bottom -->
<div mt="lg">...</div> <!-- 1.5rem top only -->
<div mb="2xl">...</div> <!-- 3rem bottom only -->
Spacing Scale
Value
Size
Pixels (at 16px)
0 0 0px
xs 0.25rem 4px
sm 0.5rem 8px
md 1rem 16px
lg 1.5rem 24px
xl 2rem 32px
2xl 3rem 48px
Content Blocks
Semantic elements for content organization.
Article (Card-like)
The <article> element is styled as a card by default:
Default Article
Basic card styling with border and background.
Elevated
Uses shadow instead of border.
Outlined
Transparent background, just border.
Flat
No border, no background, no padding.
<article>Default</article>
<article variant="elevated">With shadow</article>
<article variant="outlined">Transparent bg</article>
<article variant="flat">No styling</article>
Clickable Article
Clickable Card
Hover to see the lift effect. Click to trigger an action.
<article variant="elevated" clickable onclick="handleClick()">
<h4>Clickable Card</h4>
<p>Hover to see the lift effect.</p>
</article>
Figure & Figcaption
A sample image with centered caption
<figure>
<img src="image.jpg" alt="Description" rounded>
<figcaption align="center">Caption text</figcaption>
</figure>
Aside
Related Information
The aside element is styled as a secondary content block, perfect for sidebars or callouts.
<aside>
<h4>Related Information</h4>
<p>Secondary content here.</p>
</aside>
Interactive Elements
Native HTML interactive elements enhanced with Semantic.js.
Details / Summary (Accordion)
Click to expand
This content is revealed when you click the summary. Uses native HTML <details> element.
Another section
Multiple details elements work independently by default.
<details>
<summary>Click to expand</summary>
<p>Hidden content here.</p>
</details>
Accordion Group
Add group="name" to close others when one opens:
Question 1: What is Semantic CSS?
Semantic CSS is a framework that uses semantic HTML elements and attribute selectors instead of classes.
Question 2: Do I need JavaScript?
JavaScript is optional. The CSS works standalone, but semantic.js adds enhancements like toasts and theme switching.
Question 3: Browser support?
Modern browsers only. We use CSS features like :has(), container queries concepts, and modern attribute selectors.
<details group="faq">
<summary>Question 1</summary>
<p>Answer 1</p>
</details>
<details group="faq">
<summary>Question 2</summary>
<p>Answer 2</p>
</details>
Dialog (Modal)
Open Dialog
Dialog Title
This is a native HTML <dialog> element. Click outside or press Escape to close.
Cancel
Confirm
<button data-dialog-open="my-dialog">Open</button>
<dialog id="my-dialog">
<h3>Dialog Title</h3>
<p>Dialog content here.</p>
<nav layout="row" gap="sm" justify="end">
<button variant="ghost" data-dialog-close>Cancel</button>
<button data-dialog-close>Confirm</button>
</nav>
</dialog>
Toast Notifications
Default
Success
Error
Warning
Info
// JavaScript API
Semantic.toast.show('Message');
Semantic.toast.success('Success!');
Semantic.toast.error('Error!');
Semantic.toast.warning('Warning!');
Semantic.toast.info('Info');
// With options
Semantic.toast.show('Message', {
type: 'success',
duration: 5000,
closable: true
});
Dropdowns
Semantic dropdowns using native <details> and <menu> elements.
Basic Dropdown
<details dropdown>
<summary>Open Menu</summary>
<menu>
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else</a></li>
</menu>
</details>
Dropdown with Divider
<details dropdown>
<summary>Account</summary>
<menu>
<li><a href="#">Profile</a></li>
<li><a href="#">Settings</a></li>
<li divider></li>
<li><button>Logout</button></li>
</menu>
</details>
Right-Aligned Dropdown
<details dropdown align="right">
<summary>Align Right</summary>
<menu>...</menu>
</details>
Card Structure
Enhanced <article> with semantic <header> and <footer> elements.
Card with Header and Footer
This is the card body content. It can contain any content like text, images, or other elements.
<article>
<header>
<h4 card-title>Card Title</h4>
<p card-subtitle>Card subtitle</p>
</header>
<p>Card body content...</p>
<footer layout="row" gap="sm" justify="end">
<button variant="ghost">Cancel</button>
<button>Save</button>
</footer>
</article>
Card Grid
Description of the first feature.
Description of the second feature.
Description of the third feature.
Bottom Navigation
Fixed bottom navigation bar for mobile apps with iOS safe area support.
Basic Bottom Nav
The bottom nav is fixed to the viewport. Here's the markup:
<nav position="bottom">
<a href="/">
<span emoji="lg">🏠</span>
Home
</a>
<a href="/search">
<span emoji="lg">🔍</span>
Search
</a>
<a href="/profile" aria-current="page">
<span emoji="lg">👤</span>
Profile
</a>
</nav>
<!-- Add to body to prevent content overlap -->
<body has-bottom-nav>
Features
Automatically handles iOS safe area (notch/home indicator)
Fixed to bottom of viewport
Use aria-current="page" for active state
Add has-bottom-nav to body for proper content padding
Icons & Emoji
Utilities for sizing SVG icons and emoji.
Icon Sizing
<svg icon="xs">...</svg> <!-- 0.75em -->
<svg icon="sm">...</svg> <!-- 0.875em -->
<svg icon>...</svg> <!-- 1em (default) -->
<svg icon="lg">...</svg> <!-- 1.25em -->
<svg icon="xl">...</svg> <!-- 1.5em -->
<svg icon="2xl">...</svg> <!-- 2em -->
Emoji Sizing
🎉
xs
🎉
sm
🎉
md
🎉
lg
🎉
xl
🎉
2xl
<span emoji="sm">🎉</span> <!-- 1.25em -->
<span emoji="lg">🎉</span> <!-- 2em -->
<span emoji="xl">🎉</span> <!-- 3em -->
<span emoji="2xl">🎉</span> <!-- 4em -->
Icon Grid
⭐
Star
❤️
Heart
🔥
Fire
✅
Check
<div icon-grid>
<span>
<span emoji="lg">⭐</span>
<small>Star</small>
</span>
...
</div>
Loading States
General-purpose loading indicator for any element.
Basic Loading
This content is loading...
<article loading>
<p>This content is loading...</p>
</article>
Loading Sizes
<div loading="sm">Small spinner</div>
<div loading>Default spinner</div>
<div loading="lg">Large spinner</div>
Button Loading (Existing)
Loading...
Processing...
Image Utilities
Responsive images, object-fit, and scroll containers.
Fluid Images
A fluid image that scales with its container
<img src="..." alt="..." fluid>
<!-- Or wrap in a container -->
<figure fluid>
<img src="..." alt="...">
</figure>
Aspect Ratios
<div aspect="square">1:1</div>
<div aspect="video">16:9</div>
<div aspect="portrait">3:4</div>
<div aspect="landscape">4:3</div>
Scroll Containers
Line 1
Line 2
Line 3
Line 4
Line 5
Line 6
Line 7
Line 8
<div scroll style="max-height: 150px;">
<!-- Scrollable content -->
</div>
<div scroll-x>
<!-- Horizontal scroll -->
</div>
Link Variants
Different link styles for various contexts.
Variant Styles
<a href="#">Default link</a>
<a href="#" variant="subtle">Subtle link</a>
<a href="#" variant="muted">Muted link</a>
<a href="#" variant="contrast">Contrast link</a>
<a href="#" disabled>Disabled link</a>
External Links
<a href="https://example.com" external>Example.com</a>
<!-- Adds ↗ indicator automatically -->
Block Links
<a href="#" block>
<article clickable>
<h4>Clickable Card</h4>
<p>The entire card is a link.</p>
</article>
</a>
Utilities
Visual utilities for borders, shadows, colors, and more.
Borders & Radius
border
border="top"
rounded
rounded="lg"
rounded="full"
<div border>...</div>
<div border="top">...</div>
<div border rounded>...</div>
<div border rounded="lg">...</div>
<div rounded="full">...</div>
Shadows
shadow
shadow="md"
shadow="lg"
shadow="xl"
Backgrounds
bg="surface"
bg="primary"
bg="primary-light"
bg="danger"
bg="success"
Visibility
<div hidden>...</div> <!-- Hidden (native HTML) -->
<div hide="mobile">...</div> <!-- Hidden on mobile -->
<div hide="desktop">...</div> <!-- Hidden on desktop -->
<div sr-only>...</div> <!-- Screen reader only -->
Utility Reference
Attribute
Values
roundednone, sm, (default), lg, xl, full
shadownone, (default), md, lg, xl
border(boolean), none, top, right, bottom, left
bgsurface, background, primary, primary-light, danger, success, warning, transparent
colormuted, primary, danger, success, warning, inherit
textleft, center, right, justify
fontsans, serif, mono
weightlight, normal, medium, semibold, bold
sizexs, sm, base, lg, xl, 2xl, 3xl, 4xl
truncate(boolean)
opacity0, 25, 50, 75, 100
Alerts
Use <aside role="alert"> for dismissible messages and notifications.
Alert Variants
<aside role="alert" type="info">
<div>
<strong>Information</strong>
<p>This is an informational alert.</p>
</div>
</aside>
<aside role="alert" type="success">...</aside>
<aside role="alert" type="warning">...</aside>
<aside role="alert" type="danger">...</aside>
Dismissible Alerts
<aside role="alert" type="info">
<div grow>
<strong>Dismissible Alert</strong>
<p>Click the X button to dismiss this alert.</p>
</div>
<button close aria-label="Dismiss">×</button>
</aside>
Badges
Use <data> or <output> elements for badges and status indicators.
Badge Variants
Primary
Secondary
Success
Danger
Warning
Info
Light
Dark
<data value="1" variant="primary">Primary</data>
<data value="2" variant="secondary">Secondary</data>
<data value="3" variant="success">Success</data>
<data value="4" variant="danger">Danger</data>
<data value="5" variant="warning">Warning</data>
Pill Badges
99
New
Sale
3 items
<data value="99" variant="primary" pill>99</data>
<data value="new" variant="success" pill>New</data>
<output variant="warning" pill>3 items</output>
Badges in Context
Notifications 5
Messages 3
Navigation Components
Breadcrumbs, pagination, and button groups using semantic HTML.
Breadcrumbs
<nav aria-label="Breadcrumb">
<ol>
<li><a href="#">Home</a></li>
<li><a href="#">Products</a></li>
<li aria-current="page">Current Page</li>
</ol>
</nav>
Pagination
<nav aria-label="Pagination">
<ol>
<li><a href="#" aria-label="Previous">←</a></li>
<li><a href="#">1</a></li>
<li><a href="#" aria-current="page">2</a></li>
<li><a href="#">3</a></li>
<li><a href="#" aria-label="Next">→</a></li>
</ol>
</nav>
Button Groups
Left
Middle
Right
Top
Middle
Bottom
<nav role="group">
<button>Left</button>
<button variant="secondary">Middle</button>
<button variant="secondary">Right</button>
</nav>
<nav role="group" vertical>
<button>Top</button>
<button>Middle</button>
<button>Bottom</button>
</nav>
Responsive Navbar
Brand
☰ Menu
Resize your browser to see the toggle behavior.
<nav data-navbar>
<strong>Brand</strong>
<button data-navbar-toggle aria-label="Toggle menu">☰</button>
<div data-navbar-menu hidden>
<a href="#">Home</a>
<a href="#">About</a>
<button>Sign Up</button>
</div>
</nav>
Lists & Progress
List groups and progress indicators using semantic elements.
List Groups
Basic list item
Selected item
Another item
Disabled item
<menu role="listbox">
<li>Basic list item</li>
<li aria-selected="true">Selected item</li>
<li>Another item</li>
<li disabled>Disabled item</li>
</menu>
List with Actions
Clickable item
New
Item with action
Edit
Active item
3
<menu role="list">
<li clickable>
<span>Clickable item</span>
<data variant="primary" pill>New</data>
</li>
<li>
<span>Item with action</span>
<button size="sm" variant="ghost">Edit</button>
</li>
</menu>
Progress Bars
<progress value="70" max="100">70%</progress>
<progress value="100" max="100" variant="success">100%</progress>
<progress value="45" max="100" variant="warning">45%</progress>
<progress value="25" max="100" variant="danger">25%</progress>
Meter Element
Disk Usage (optimum)
30%
Memory Usage (suboptimum)
60%
CPU Usage (critical)
90%
<meter value="0.3" min="0" max="1" low="0.3" high="0.7" optimum="0.1">30%</meter>
<meter value="0.6" min="0" max="1" low="0.3" high="0.7" optimum="0.1">60%</meter>
<meter value="0.9" min="0" max="1" low="0.3" high="0.7" optimum="0.1">90%</meter>
Tabs
Accessible tabs with keyboard navigation using ARIA roles.
Basic Tabs
Tab 1
Tab 2
Tab 3
Tab 1 Content
This is the content for the first tab. Use arrow keys to navigate between tabs.
Tab 2 Content
Here's some different content for the second tab.
Tab 3 Content
And finally, content for the third tab.
<nav role="tablist">
<button role="tab" aria-selected="true" aria-controls="panel-1">Tab 1</button>
<button role="tab" aria-selected="false" aria-controls="panel-2">Tab 2</button>
<button role="tab" aria-selected="false" aria-controls="panel-3">Tab 3</button>
</nav>
<section role="tabpanel" id="panel-1">Content 1</section>
<section role="tabpanel" id="panel-2" hidden>Content 2</section>
<section role="tabpanel" id="panel-3" hidden>Content 3</section>
Pills Variant
Overview
Features
Pricing
Overview content with pills-style tabs.
Pricing information here.
<nav role="tablist" variant="pills">
<button role="tab" aria-selected="true">Overview</button>
<button role="tab">Features</button>
<button role="tab">Pricing</button>
</nav>
Vertical Tabs
Account
Security
Notifications
Account Settings
Manage your account details and preferences.
Security Settings
Update password and security options.
Notification Preferences
Control how you receive notifications.
<nav role="tablist" vertical>
<button role="tab" aria-selected="true">Account</button>
<button role="tab">Security</button>
<button role="tab">Notifications</button>
</nav>
Offcanvas
Slide-in panels using the native <dialog> element with position attributes.
Offcanvas Positions
Open Left
Open Right
Open Top
Open Bottom
Left Panel
×
Menu Item 1
Menu Item 2
Menu Item 3
Menu Item 4
Right Panel
×
This panel slides in from the right.
Close
Top Panel
×
This panel slides down from the top of the screen.
Bottom Panel
×
This panel slides up from the bottom, like a mobile action sheet.
Cancel
Delete
<button data-dialog-open="sidebar">Open Sidebar</button>
<dialog id="sidebar" position="left">
<nav layout="row" justify="between" align="center" mb="lg">
<strong>Menu</strong>
<button close data-dialog-close>×</button>
</nav>
<nav layout="stack" gap="sm">
<a href="#">Home</a>
<a href="#">About</a>
<a href="#">Contact</a>
</nav>
</dialog>
Position Options
Attribute
Description
position="left"Slides in from the left edge
position="right"Slides in from the right edge
position="top"Slides down from the top
position="bottom"Slides up from the bottom (action sheet style)
Theming
Customize the design system with CSS variables.
Dark Mode
Dark mode works automatically via system preference, or can be toggled:
Light Mode
Dark Mode
System
Toggle
// JavaScript
Semantic.theme.set('dark'); // Force dark
Semantic.theme.set('light'); // Force light
Semantic.theme.set('system'); // Follow system
Semantic.theme.toggle(); // Toggle current
// HTML attribute
<button data-theme-toggle>Toggle</button>
Custom Colors
Override CSS variables to customize:
:root {
/* Primary brand color */
--primary: #your-color;
--primary-dark: #darker-shade;
--primary-rgb: r, g, b;
/* Other colors */
--danger: #d0021b;
--success: #7ed321;
--warning: #f5a623;
}
Typography
:root {
/* Font families */
--sans: 'Your Sans Font', system-ui, sans-serif;
--serif: 'Your Serif Font', Georgia, serif;
--mono: 'Your Mono Font', monospace;
/* Font sizes */
--text-base: 1rem;
--text-lg: 1.125rem;
--text-xl: 1.25rem;
}
Spacing
:root {
--space-xs: 0.25rem; /* 4px */
--space-sm: 0.5rem; /* 8px */
--space-md: 1rem; /* 16px */
--space-lg: 1.5rem; /* 24px */
--space-xl: 2rem; /* 32px */
--space-2xl: 3rem; /* 48px */
}
Design Token Reference
--primary
--danger
--success
--warning
--muted
--surface
Accessibility
Built-in accessibility features:
Focus visible: Clear focus indicators for keyboard navigation
Reduced motion: Respects prefers-reduced-motion
High contrast: Enhanced colors for prefers-contrast: high
Screen reader: Use sr-only for visually hidden but accessible content
Touch targets: Minimum 48px tap targets for mobile