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:

  1. Semantic HTML elements - Use the right element for the job (<article>, <nav>, <header>)
  2. Attribute selectors - Style via attributes like layout="grid" or variant="primary"
  3. 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 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

  1. First step
  2. Second step
  3. 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

1
2
3
4
5
6

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

Left Center Right
<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)
000px
xs0.25rem4px
sm0.5rem8px
md1rem16px
lg1.5rem24px
xl2rem32px
2xl3rem48px

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

Sample image
A sample image with centered caption
<figure> <img src="image.jpg" alt="Description" rounded> <figcaption align="center">Caption text</figcaption> </figure>

Aside

<aside> <h4>Related Information</h4> <p>Secondary content here.</p> </aside>

Buttons

Style buttons with variant and size attributes.

Button Variants

<button>Primary</button> <button variant="secondary">Secondary</button> <button variant="danger">Danger</button> <button variant="success">Success</button> <button variant="ghost">Ghost</button> <button variant="link">Link Style</button>

Button Sizes

<button size="xs">Extra Small</button> <button size="sm">Small</button> <button>Default</button> <button size="lg">Large</button> <button size="xl">Extra Large</button>

Button States

<button disabled>Disabled</button> <button loading>Loading</button> <button full>Full Width</button>

Forms

Form elements are styled automatically with validation states.

Basic Form

<form layout="stack"> <div> <label for="name">Name</label> <input type="text" id="name" required> </div> <div> <label for="email">Email</label> <input type="email" id="email" required> </div> <div> <label for="message">Message</label> <textarea id="message"></textarea> </div> <button type="submit">Submit</button> </form>

Input Types

Checkboxes & Radio Buttons

Checkboxes
Radio Buttons
<label inline><input type="checkbox"> Option A</label> <label inline><input type="radio" name="group"> Choice 1</label>

Inline Form

<form layout="inline"> <input type="email" placeholder="Email address"> <button type="submit">Subscribe</button> </form>

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)

Dialog Title

This is a native HTML <dialog> element. Click outside or press Escape to close.

<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

// 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 });

Card Structure

Enhanced <article> with semantic <header> and <footer> elements.

Card with Header and Footer

Card Title

Card subtitle or meta info

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

Feature 1

Description of the first feature.

Feature 2

Description of the second feature.

Feature 3

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

<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

Small
Default
Large
<div loading="sm">Small spinner</div> <div loading>Default spinner</div> <div loading="lg">Large spinner</div>

Button Loading (Existing)

Image Utilities

Responsive images, object-fit, and scroll containers.

Fluid Images

Sample image
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

1:1
16:9
3:4
4:3
<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>

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

<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

<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

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
  • 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

    70%
    100%
    45%
    25%
    <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

    30%
    60%
    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>

    Enhanced Forms

    Advanced form patterns including input groups, floating labels, and styled controls.

    Input Groups

    <label layout="input-group"> <span>$</span> <input type="number" placeholder="0.00"> <span>.00</span> </label> <label layout="input-group"> <span>https://</span> <input type="text" placeholder="example.com"> </label> <label layout="input-group"> <input type="email" placeholder="Enter email"> <button>Subscribe</button> </label>

    Floating Labels

    <label floating> <input type="text" placeholder=" "> <span>Full Name</span> </label> <label floating> <input type="email" placeholder=" "> <span>Email Address</span> </label> <label floating> <textarea placeholder=" "></textarea> <span>Message</span> </label>

    Styled Checkboxes & Radios

    Checkboxes

    Radio Buttons

    <label inline><input type="checkbox" styled> Option A</label> <label inline><input type="checkbox" styled checked> Option B</label> <label inline><input type="radio" name="group" styled> Choice 1</label> <label inline><input type="radio" name="group" styled checked> Choice 2</label>

    Switch Toggle

    <label inline><input type="checkbox" switch> Enable notifications</label> <label inline><input type="checkbox" switch checked> Dark mode</label>

    Display Headings

    Display 1

    Display 2

    Display 3

    Display 4

    <h1 display="1">Display 1</h1> <h2 display="2">Display 2</h2> <h3 display="3">Display 3</h3> <h4 display="4">Display 4</h4>

    Lead Paragraph

    This is a lead paragraph. It stands out from regular paragraphs with larger text and a lighter weight, perfect for introductory content.

    This is a regular paragraph for comparison. Notice the difference in size and emphasis.

    <p lead>This is a lead paragraph...</p>

    Smart Tooltips

    <button data-tooltip="Helpful info">Hover me</button> <button data-tooltip="Bottom tip" data-tooltip-position="bottom">Bottom</button> <button data-tooltip="Left tip" data-tooltip-position="left">Left</button> <button data-tooltip="Right tip" data-tooltip-position="right">Right</button>

    Tabs

    Accessible tabs with keyboard navigation using ARIA roles.

    Basic Tabs

    Tab 1 Content

    This is the content for the first tab. Use arrow keys to navigate between tabs.

    <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 content with pills-style tabs.

    <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 Settings

    Manage your account details and preferences.

    <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

    This panel slides in from the right.

    This panel slides down from the top of the screen.

    This panel slides up from the bottom, like a mobile action sheet.

    <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:

    // 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