Shine CSS reference

Every class and data attribute in Shine, with live examples. This page is generated from the CSS source, so it always matches the code. Try the playground.

Getting started

Shine is a pure-CSS utility framework. Add one stylesheet and use class names. There is no JavaScript to load and no build step to run.

<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/asticore/shine@v1.0.0/dist/shine.min.css">

How classes combine

A component class gives you the base look. Modifier classes change it. Tone classes recolor it. Utilities adjust it locally.

<button class="btn btn-outline tone-danger mt-4 md:mt-0">Delete</button>
<!--     base   style       tone         utilities    -->

Knobs first, utilities second

Start by setting a few master knobs on <html>: theme, corner radius, shadow, density and brand colors. The whole site follows. Reach for utility classes only when one element needs to differ. Your own CSS always wins over Shine, so you never need !important.

<html data-theme="auto" data-radius="3" data-shadow="2" style="--sh-primary:#0ea5e9">

Master knobs

Knobs are data attributes and CSS variables. Set them on <html> for the whole site, or on any element to restyle just that subtree.

Data attributes

AttributeValuesWhat it changes
data-themelight · dark · autoPage background, surfaces, text, borders and shadows. A themed element paints its own background, so a dark section can sit inside a light page. Set on: html or any section.
data-radius0 · 1 · 2 · 3 · 4 · 5Corner level for every rounded thing: buttons, cards, inputs, modals and the rounded-* utilities. Set on: html or any element.
data-btn-radius0 · 1 · 2 · 3 · 4 · 5Corner level for buttons only (and pagination, tabs pills, close buttons). 5 makes pills. Set on: any element.
data-card-radius0 · 1 · 2 · 3 · 4 · 5Corner level for cards, modals, menus and accordions. Set on: any element.
data-input-radius0 · 1 · 2 · 3 · 4 · 5Corner level for text inputs, selects and textareas. 5 makes pills. Set on: any element.
data-shadow0 · 1 · 2 · 3 · 4 · 5Elevation of cards, from none (0) to very high (5). Also drives the shadow-elevation utility. Set on: html or any element.
data-densitycompact · comfortableComponent padding multiplier: compact = .75, comfortable = 1.25, default = 1. Set on: html or any element.

data-theme

light
dark
auto

data-radius

data-btn-radius

data-input-radius

data-card-radius

0
2
5

data-shadow

0
1
3
5

data-density

CSS variables (tokens)

Every --sh-* variable defined on :root. Override any of them on any element: style="--sh-primary:#e11d48" re-brands that subtree.

VariableDefaultPreviewNote
--sh-primary#4f46e5Brand
--sh-secondary#64748bBrand
--sh-accent#db2777Brand
--sh-success#15803dBrand
--sh-warning#b45309Brand
--sh-danger#dc2626Brand
--sh-info#0369a1Brand
--sh-on-primary#fffBrand
--sh-on-secondary#fffBrand
--sh-on-accent#fffBrand
--sh-on-success#fffBrand
--sh-on-warning#fffBrand
--sh-on-danger#fffBrand
--sh-on-info#fffBrand
--sh-bg#fffpage
--sh-surface#f8fafccards, panels
--sh-surface-2#f1f5f9inputs, wells, hover
--sh-text#0f172aSurfaces (light)
--sh-text-muted#5f6e84Surfaces (light)
--sh-border#e2e8f0Surfaces (light)
--sh-radius.5remglobal corner level (see data-radius)
--sh-border-width1pxShape
--sh-space.25remspacing unit: p-4 = 4 x this
--sh-density1component padding multiplier
--sh-shadow-10 1px 2px rgb(0 0 0 / .06), 0 1px 3px rgb(0 0 0 / .08)Elevation
--sh-shadow-20 2px 4px rgb(0 0 0 / .06), 0 4px 8px rgb(0 0 0 / .08)Elevation
--sh-shadow-30 4px 8px rgb(0 0 0 / .06), 0 10px 20px rgb(0 0 0 / .10)Elevation
--sh-shadow-40 8px 16px rgb(0 0 0 / .08), 0 20px 40px rgb(0 0 0 / .12)Elevation
--sh-shadow-50 12px 24px rgb(0 0 0 / .10), 0 32px 64px rgb(0 0 0 / .18)Elevation
--sh-font-sansui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serifTypography
--sh-font-serifui-serif, Georgia, Cambria, "Times New Roman", serifTypography
--sh-font-monoui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospaceTypography
--sh-leading1.5Typography
--sh-duration150msMotion
--sh-easecubic-bezier(.4, 0, .2, 1)Motion

Components also read optional variables that are not set by default. Set them to override one component: --sh-stack-gap --sh-center-max --sh-section-gap --sh-tone --sh-on-tone --sh-btn-radius --sh-card-radius --sh-input-radius --sh-badge-radius --sh-card-shadow --sh-elevation --sh-ring.

Tones

Tone classes recolor any component: buttons, badges, alerts, tabs, progress bars, switches. Without a tone, components use --sh-primary.

ClassPreview
tone-primaryBadge
tone-secondaryBadge
tone-accentBadge
tone-successBadge
tone-warningBadge
tone-dangerBadge
tone-infoBadge
tone-neutralBadge
<button class="btn tone-danger">Delete</button>
<span class="badge tone-success">Live</span>
<div class="alert tone-warning">Heads up</div>

Components

Eight small files. Each example below is live, followed by its exact HTML and a table of every class in the source file.

Layout primitives

Easy-to-use building blocks for spacing and page width. Gap, width and section padding follow --sh-stack-gap, --sh-center-max and --sh-section-gap; utilities such as gap-2 or py-4 override them.

Stack

Children are spaced evenly.

Clusterofitems
<div class="stack">
  <strong>Stack</strong>
  <p class="m-0">Children are spaced evenly.</p>
  <div class="cluster">
    <span class="badge">Cluster</span><span class="badge">of</span><span class="badge">items</span><button class="btn btn-sm">Action</button>
  </div>
</div>

Eyebrow, display, banner, segmented, hairline grid, full-bleed

Layout

Fluid headings

  • One
  • Two
  • Three
Full-bleed band
<div class="banner tone-accent"><span>Shine 1.1 is out.</span><a href="#c-layout">See what is new</a></div>
<div class="stack gap-2">
  <p class="eyebrow m-0">Layout</p>
  <h3 class="display-3 m-0">Fluid headings</h3>
</div>
<div class="segmented" role="radiogroup" aria-label="Billing period">
  <label><input type="radio" name="ex-billing" checked> Monthly</label>
  <label><input type="radio" name="ex-billing"> Yearly</label>
</div>
<ul class="grid grid-cols-1 sm:grid-cols-3 grid-hairline list-none p-0 m-0">
  <li class="p-4">One</li><li class="p-4">Two</li><li class="p-4">Three</li>
</ul>
<div class="full-bleed bg-surface-2 py-6 text-center">Full-bleed band</div>
ClassWhat it does
.stackVertical flex column with a consistent gap.
.clusterWrapping horizontal row, vertically centered, with a gap.
.centerCentered container with a max width and side padding.
.sectionLarge vertical padding for a page section (scales with density, or set --sh-section-gap).
.full-bleedEdge-to-edge band (100vw) inside a centered page. The body clips horizontal overflow.
.grid-hairlineItems separated by 1px lines instead of gaps. Use with grid or flex; direct children get the page background.
.eyebrowSmall uppercase label above a heading, colored by the tone.
.display-1Largest fluid hero heading (2.5rem to 4.5rem).
.display-2Large fluid hero heading (2rem to 3.5rem).
.display-3Medium fluid hero heading (1.75rem to 2.75rem).
.bannerThin announcement strip filled with the tone color; links inside are underlined.
.segmentedSegmented switch: radio labels, or buttons with aria-pressed, aria-selected or .active.
.activeMarks the selected button inside a .segmented switch (aria-pressed="true" does the same).

Button

A btn is solid by default. Add a style (outline, soft, ghost, link), a size, and a tone class to recolor it.

<button class="btn">Solid</button>
<button class="btn btn-outline">Outline</button>
<button class="btn btn-soft tone-success">Soft</button>
<button class="btn btn-ghost">Ghost</button>
<button class="btn btn-link">Link</button>
<button class="btn btn-sm">Small</button>
<button class="btn btn-lg tone-danger">Large</button>
<button class="btn btn-icon" aria-label="Star">★</button>
<button class="btn" disabled>Disabled</button>
ClassWhat it does
.btnBase solid button. Works on button, a and summary.
.btn-smSmaller padding and text.
.btn-lgLarger padding and text.
.btn-outlineTransparent with a tone-colored border.
.btn-ghostNo background until hover.
.btn-softLight tinted background.
.btn-linkLooks like an underlined text link.
.btn-blockFull-width, block-level button.
.btn-iconSquare button for a single icon or glyph.

Card

A bordered surface. Radius follows data-card-radius, elevation follows data-shadow.

Title

Body text. Radius and shadow follow the knobs.
<article class="card">
  <div class="card-header"><h3 class="card-title">Title</h3></div>
  <div class="card-body">Body text. Radius and shadow follow the knobs.</div>
  <div class="card-footer"><button class="btn btn-sm">Save</button></div>
</article>
ClassWhat it does
.cardBordered surface with radius and shadow.
.card-flatRemoves the shadow.
.card-headerPadded top area with a bottom border.
.card-bodyPadded main area.
.card-footerPadded bottom area with a top border.
.card-titleHeading style for a card.
.card-mediaFull-width image at the top, rounded to match the card.

Form

Native controls, styled. Wrap a label, control and hint in field for even spacing. Mark errors with is-invalid or aria-invalid="true".

Helper text
Enter a valid email
https://
<div class="field">
  <label class="label" for="ex-name">Name</label>
  <input class="input" id="ex-name" placeholder="Ada Lovelace">
  <span class="hint">Helper text</span>
</div>
<div class="field">
  <label class="label" for="ex-mail">Email</label>
  <input class="input is-invalid" id="ex-mail" value="nope" aria-invalid="true">
  <span class="hint">Enter a valid email</span>
</div>
<div class="field">
  <label class="label" for="ex-plan">Plan</label>
  <select class="select" id="ex-plan"><option>Free</option><option>Pro</option></select>
</div>
<div class="field">
  <label class="label" for="ex-msg">Message</label>
  <textarea class="textarea" id="ex-msg"></textarea>
</div>
<label class="flex items-center gap-2"><input type="checkbox" class="checkbox" checked> Checkbox</label>
<label class="flex items-center gap-2"><input type="radio" class="radio" name="ex-r" checked> Radio</label>
<label class="flex items-center gap-2"><input type="checkbox" class="switch" checked> Switch</label>
<div class="input-group">
  <span class="input-addon">https://</span>
  <input class="input" aria-label="Domain" placeholder="example.com">
  <button class="btn">Go</button>
</div>
<input type="range" class="range" aria-label="Volume" value="40">
<input type="file" class="file" aria-label="Upload file">
ClassWhat it does
.inputText input.
.selectDropdown select with a custom arrow.
.textareaMulti-line text input.
.is-invalidRed error state (aria-invalid="true" does the same). Turns the next hint red.
.input-smSmaller input.
.input-lgLarger input.
.checkboxCheckbox tinted with the tone.
.radioRadio button tinted with the tone.
.switchToggle switch (use on a checkbox input).
.labelForm label.
.fieldGroups label, control and hint in a tidy grid.
.hintSmall helper text under a control.
.input-groupJoins inputs, buttons and addons into one bar with shared borders. Items must be direct children.
.input-addonMuted text cell (a prefix, suffix or unit) inside an input-group.
.rangeSlider (use on input type=range), tinted with the tone.
.fileFile picker (use on input type=file) with a soft-button style.

Badge, avatar, divider

Small status chips, round avatars and separators. Badges take tone classes.

Default Success Solid Outline AB
ABCDEF

or
<span class="badge">Default</span>
<span class="badge tone-success">Success</span>
<span class="badge badge-solid tone-danger">Solid</span>
<span class="badge badge-outline tone-info">Outline</span>
<span class="avatar">AB</span>
<div class="avatar-group"><span class="avatar">AB</span><span class="avatar">CD</span><span class="avatar">EF</span></div>
<hr class="divider">
<div class="divider">or</div>
ClassWhat it does
.badgeSmall tinted pill.
.badge-solidSolid tone fill.
.badge-outlineOutlined, no fill.
.avatarRound box for initials or an image.
.avatar-groupOverlapping row of avatars, each ringed in the page background. On a card, set style="--sh-avatar-ring:var(--sh-surface)".
.dividerHorizontal rule; put text inside for a labelled divider.

Alert and kbd

Inline messages and keyboard keys. Alerts take tone classes.

Heads up Soft alert.
Failed Solid alert.

Press Ctrl + K

<div class="alert tone-info"><span class="alert-title">Heads up</span> Soft alert.</div>
<div class="alert alert-solid tone-danger"><span class="alert-title">Failed</span> Solid alert.</div>
<p>Press <kbd class="kbd">Ctrl</kbd> + <kbd class="kbd">K</kbd></p>
ClassWhat it does
.alertTinted message box.
.alert-solidSolid tone fill.
.alert-titleBold first line.
.kbdKeyboard key cap.

Overlays: modal, offcanvas, dropdown, tooltip

No JavaScript. Modals use <dialog> with command / commandfor (Invoker Commands). Offcanvas uses the Popover API. Dropdowns use <details>. Tooltips use a data attribute.

Toast

Saved. Your changes are live.
A static toast is just a card notice.
<button class="btn" popovertarget="demo-toast">Show toast</button>
<div id="demo-toast" popover="manual" class="toast tone-success" role="status">
  <strong>Saved.</strong> Your changes are live.
  <button class="btn-close" popovertarget="demo-toast" popovertargetaction="hide" aria-label="Dismiss"></button>
</div>
<div class="toast tone-info">A static toast is just a card notice.</div>

Modal

<button class="btn" command="show-modal" commandfor="demo-modal">Open modal</button>
<dialog id="demo-modal" class="modal" aria-labelledby="demo-modal-title">
  <div class="modal-header">
    <h3 class="card-title" id="demo-modal-title">Modal title</h3>
    <button class="btn-close" command="close" commandfor="demo-modal" aria-label="Close"></button>
  </div>
  <div class="modal-body">Esc or the backdrop closes it. Focus is trapped natively.</div>
  <div class="modal-footer">
    <button class="btn btn-ghost" command="close" commandfor="demo-modal">Cancel</button>
    <button class="btn" command="close" commandfor="demo-modal">OK</button>
  </div>
</dialog>

Offcanvas

<button class="btn" popovertarget="demo-oc">Open panel</button>
<aside id="demo-oc" popover class="offcanvas" aria-label="Demo panel">
  <div class="offcanvas-header">
    <strong>Panel</strong>
    <button class="btn-close" popovertarget="demo-oc" popovertargetaction="hide" aria-label="Close"></button>
  </div>
  <div class="offcanvas-body">Slides in from the left. Add offcanvas-right, -top or -bottom to change the side.</div>
</aside>

Dropdown

<details class="dropdown">
  <summary class="btn btn-outline">Menu</summary>
  <ul class="menu">
    <li><a href="#overlay" class="active">Profile</a></li>
    <li><a href="#overlay">Settings</a></li>
    <li><hr class="menu-divider"></li>
    <li><button type="button">Sign out</button></li>
  </ul>
</details>

Tooltip

<button class="btn btn-outline" data-tooltip="Saved to your account">Hover me</button>
<button class="btn btn-outline" data-tooltip="Below" data-tooltip-pos="bottom">Bottom</button>
<button class="btn btn-outline" data-tooltip="Right" data-tooltip-pos="right">Right</button>
ClassWhat it does
.modalCentered dialog. Put it on a <dialog>.
.offcanvasSide panel that slides in. Put it on an element with the popover attribute.
.modal-smNarrower modal.
.modal-lgWider modal.
.modal-fullNearly full-screen modal.
.modal-headerTop bar of a modal.
.modal-bodyPadded content of a modal.
.modal-footerBottom bar for action buttons.
.offcanvas-headerTop bar of an offcanvas.
.offcanvas-bodyPadded content of an offcanvas.
.offcanvas-rightSlides in from the right.
.offcanvas-topSlides in from the top.
.offcanvas-bottomSlides in from the bottom.
.btn-closeRound close button with a multiplication sign.
.dropdownWrapper for a details/summary dropdown.
.menuVertical list of links or buttons.
.dropdown-menuPopover menu: put on an element with popover, open with a popovertarget button. Closes on outside click and Esc.
.dropdown-endAligns the menu to the right edge.
.dropdown-menu-endAligns a popover menu to the end edge of its button.
.activeHighlights the current menu or tab item.
.menu-dividerThin separator line between menu items.
data-tooltipAttribute: text shown on hover or focus.
.toastNotification box. On an element with popover="manual" it floats bottom-right; without popover it is a static notice. Tone sets the left border. Show one floating toast at a time; they share the same corner.
.toast-topPositions the toast at the top.
.toast-leftPositions the toast at the left.
.toast-centerCenters the toast horizontally.

Navigation

Navbar, breadcrumb, pagination and tabs. Use real <nav>, lists, and aria-current="page" for the active item.

<nav class="navbar" aria-label="Demo">
  <a class="navbar-brand" href="#nav">Brand</a>
  <ul class="navbar-nav">
    <li><a href="#nav" aria-current="page">Home</a></li>
    <li><a href="#nav">Docs</a></li>
  </ul>
  <a class="navbar-end btn btn-sm" href="#nav">Sign in</a>
</nav>

<nav aria-label="Breadcrumb">
  <ol class="breadcrumb">
    <li><a href="#nav">Home</a></li>
    <li><a href="#nav">Docs</a></li>
    <li aria-current="page">Navigation</li>
  </ol>
</nav>

<ul class="tabs">
  <li><a href="#nav" aria-current="page">Overview</a></li>
  <li><a href="#nav">Usage</a></li>
  <li><a href="#nav">API</a></li>
</ul>

<ul class="tabs tabs-pills">
  <li><a href="#nav" aria-current="page">One</a></li>
  <li><a href="#nav">Two</a></li>
</ul>

<nav aria-label="Pages">
  <ul class="pagination">
    <li><a href="#nav">Prev</a></li>
    <li><a href="#nav" aria-current="page">1</a></li>
    <li><a href="#nav">2</a></li>
    <li><a href="#nav">Next</a></li>
  </ul>
</nav>
ClassWhat it does
.navbarHorizontal bar that wraps on small screens.
.navbar-brandLogo or site name link.
.navbar-navList of navbar links.
.navbar-endPushes an item to the right edge.
.breadcrumbSlash-separated trail (use on ol/ul).
.paginationRow of page links (use on ul).
.tabsUnderlined tab row (use on ul).
.activeMarks the current tab or menu item (aria-current works too).
.tabs-pillsCombine with tabs for pill-shaped tabs.

Content: accordion, table, progress, meter, stat, prose

Building blocks for documents. The accordion is plain <details>; the progress bar is a native <progress>; prose styles long-form HTML such as articles.

First item

Opens and closes natively.

Second item

More content.

Team (sort arrows come from aria-sort; stacks into cards on phones)
NameRoleCommits
AdaEngineer1,204
GraceAdmiral982
AlanResearcher640
Total2,826
PlanPrice
Free$0
LegacyEnds soon
Revenue$12,480+8% from last month
<div class="accordion">
  <details open><summary>First item</summary><p>Opens and closes natively.</p></details>
  <details><summary>Second item</summary><p>More content.</p></details>
</div>

<div class="table-wrap max-h-full">
  <table class="table table-striped table-hover table-stack">
    <caption>Team (sort arrows come from aria-sort; stacks into cards on phones)</caption>
    <thead><tr><th aria-sort="ascending">Name</th><th aria-sort="none">Role</th><th class="text-right">Commits</th></tr></thead>
    <tbody>
      <tr><td data-label="Name">Ada</td><td data-label="Role">Engineer</td><td data-label="Commits" class="text-right">1,204</td></tr>
      <tr class="tone-success"><td data-label="Name">Grace</td><td data-label="Role">Admiral</td><td data-label="Commits" class="text-right">982</td></tr>
      <tr aria-selected="true"><td data-label="Name">Alan</td><td data-label="Role">Researcher</td><td data-label="Commits" class="text-right">640</td></tr>
    </tbody>
    <tfoot><tr><td>Total</td><td></td><td class="text-right">2,826</td></tr></tfoot>
  </table>
</div>

<table class="table table-bordered table-compact">
  <thead><tr><th>Plan</th><th>Price</th></tr></thead>
  <tbody><tr><td>Free</td><td>$0</td></tr><tr class="tone-danger"><td>Legacy</td><td>Ends soon</td></tr></tbody>
</table>

<progress class="progress" value="60" max="100" aria-label="Upload"></progress>
<progress class="progress tone-success" value="30" max="100" aria-label="Done"></progress>

<meter class="meter" value="80" min="0" max="100" low="30" high="70" optimum="100" aria-label="Good"></meter>
<meter class="meter" value="50" min="0" max="100" low="30" high="70" optimum="100" aria-label="Fair"></meter>
<meter class="meter" value="15" min="0" max="100" low="30" high="70" optimum="100" aria-label="Poor"></meter>

<div class="card"><div class="card-body stat">
  <span class="stat-label">Revenue</span><span class="stat-value">$12,480</span><span class="stat-desc">+8% from last month</span>
</div></div>

<a class="skip-link" href="#main">Skip to content</a>
ClassWhat it does
.accordionBordered stack of <details> items with a chevron.
.tableFull-width table with row borders.
.table-stripedZebra rows.
.table-hoverHighlights the row under the pointer.
.table-compactTighter cell padding.
.table-borderedBorders on every cell.
.table-borderlessNo cell borders.
.activeHighlights a row or cell (also aria-selected="true" or any tone-* class).
.table-wrapScroll container for a table. Give it max-h-* and the header row sticks.
.table-sticky-colPins the first column while the table scrolls sideways (inside .table-wrap).
.table-stackOn phones, each row becomes a card. Put data-label="Column" on every td.
data-labelAttribute on a td: the column name shown in .table-stack mode.
.progressRounded progress bar (use on <progress>).
.meterGauge bar (use on <meter>); green, amber or red from low/high/optimum.
.statMetric block: label, big value, description. Works inside a card.
.stat-labelSmall muted label above the value.
.stat-descSmall muted note under the value.
.stat-valueLarge bold number.
.proseStyles plain h1-h4, p, lists, code, tables and quotes inside it.
.skip-linkHidden link that appears on keyboard focus; place first in body.

Extras: list group, button group, floating label, carousel

Small add-ons. The carousel is plain scroll-snap (link to item ids, no JS); the floating label needs placeholder=" " on the input.

Frosted glass card
3 Online marked

A lead paragraph.

<div class="btn-group">
  <button class="btn">Save</button>
  <button class="btn btn-caret" popovertarget="split-menu" aria-label="More save options"></button>
</div>
<div id="split-menu" popover class="menu dropdown-menu dropdown-menu-end">
  <a href="#extras">Save as…</a><a href="#extras">Export PDF</a>
</div>

<div class="card glass p-6">Frosted glass card</div>

<ul class="list-group">
  <li>Plain item</li>
  <li><a href="#extras" aria-current="true">Current link</a></li>
  <li><a href="#extras">Link item</a></li>
</ul>

<div class="btn-group"><button class="btn btn-outline">Left</button><button class="btn btn-outline">Middle</button><button class="btn btn-outline">Right</button></div>

<div class="floating"><input class="input" placeholder=" " id="fl-email"><label for="fl-email">Email</label></div>

<div class="carousel carousel-peek carousel-hide-bar">
  <div id="s1" class="card card-body">Slide 1 <a href="#s2">Next</a></div>
  <div id="s2" class="card card-body">Slide 2 <a href="#s1">Prev</a></div>
</div>

<div class="card card-body"><a class="stretched-link" href="#extras">Whole card is a link</a></div>

<div class="cluster"><span class="indicator"><span class="indicator-item badge badge-solid tone-danger">3</span><button class="btn">Inbox</button></span><span class="dot tone-success"></span> Online <span class="vr"></span> <mark>marked</mark></div>
<p class="lead">A lead paragraph.</p>
ClassWhat it does
.list-groupBordered stacked list; a/button items get hover, [aria-current] or .active is solid.
.activeWith .list-group items: marks the current item.
.btn-groupJoins adjacent .btn elements into one segmented control.
.btn-group-verticalButton group stacked vertically.
.btnUsed inside .btn-group.
.floatingWrapper whose label floats above the input when focused or filled.
.inputUsed inside .floating.
.textareaUsed inside .floating.
.carouselScroll-snap slider; each child fills the width.
.carousel-peekItems are 85% wide so the next one peeks in.
.carousel-hide-barHides the carousel scrollbar.
.stretched-linkMakes a link cover its whole positioned parent, such as a card.
.cardCards containing a .stretched-link become positioned.
.indicatorWrapper that pins an .indicator-item to its top-right corner.
.indicator-itemBadge or dot placed on the corner of an .indicator.
.dotSmall status dot colored by tone.
.vrVertical rule for flex rows.
.leadLarger intro paragraph.
.markHighlighted text (also styles the mark element).
.btn-caretAdds a down chevron; pair with popovertarget for a split button menu.
.glassFrosted-glass surface (blurred, translucent). Tune with --sh-glass-blur and --sh-glass-opacity.
.modal-blurBlurs the page behind an open modal.

Utilities

819 utility rules, generated from src/utilities/*.css when this page is built. Class names follow familiar utility conventions (inspired by Tailwind CSS). The last column lists the prefixed versions that the build creates, such as md:p-4 or hover:bg-primary.

layout

Layout: display, position, overflow, container, misc (66 rules)

ClassCSSVariants
.blockdisplay:blocksm md lg xl print
.inline-blockdisplay:inline-blocksm md lg xl print
.inlinedisplay:inlinesm md lg xl print
.flexdisplay:flexsm md lg xl print
.inline-flexdisplay:inline-flexsm md lg xl print
.griddisplay:gridsm md lg xl print
.inline-griddisplay:inline-gridsm md lg xl print
.contentsdisplay:contentssm md lg xl print
.hiddendisplay:nonesm md lg xl print
.containerwidth:100%; margin-inline:auto; padding-inline:calc(var(--sh-space)*4)-
.staticposition:static-
.relativeposition:relative-
.absoluteposition:absolute-
.fixedposition:fixed-
.stickyposition:sticky-
.inset-0inset:0-
.inset-x-0inset-inline:0-
.inset-y-0inset-block:0-
.top-0top:0-
.top-autotop:auto-
.right-0right:0-
.right-autoright:auto-
.bottom-0bottom:0-
.bottom-autobottom:auto-
.left-0left:0-
.left-autoleft:auto-
.z-0z-index:0-
.z-10z-index:10-
.z-20z-index:20-
.z-30z-index:30-
.z-40z-index:40-
.z-50z-index:50-
.z-autoz-index:auto-
.overflow-autooverflow:auto-
.overflow-hiddenoverflow:hidden-
.overflow-visibleoverflow:visible-
.overflow-scrolloverflow:scroll-
.overflow-x-autooverflow-x:auto-
.overflow-x-hiddenoverflow-x:hidden-
.overflow-y-autooverflow-y:auto-
.overflow-y-hiddenoverflow-y:hidden-
.box-borderbox-sizing:border-box-
.box-contentbox-sizing:content-box-
.visiblevisibility:visible-
.invisiblevisibility:hidden-
.isolateisolation:isolate-
.object-coverobject-fit:cover-
.object-containobject-fit:contain-
.aspect-squareaspect-ratio:1/1-
.aspect-videoaspect-ratio:16/9-
.aspect-autoaspect-ratio:auto-
.aspect-4/3aspect-ratio:4/3-
.columns-1columns:1-
.columns-2columns:2-
.columns-3columns:3-
.align-baselinevertical-align:baseline-
.align-topvertical-align:top-
.align-middlevertical-align:middle-
.align-bottomvertical-align:bottom-
.align-text-topvertical-align:text-top-
.scroll-mt-4scroll-margin-top:calc(var(--sh-space)*4)-
.scroll-mt-16scroll-margin-top:calc(var(--sh-space)*16)-
.scroll-mt-20scroll-margin-top:calc(var(--sh-space)*20)-
.scroll-mt-24scroll-margin-top:calc(var(--sh-space)*24)-
.sr-onlyposition:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border-width:0sm md lg xl
.not-sr-onlyposition:static; width:auto; height:auto; padding:0; margin:0; overflow:visible; clip:auto; white-space:normalsm md lg xl

flex-grid

Flex & grid (123 rules)

ClassCSSVariants
.flex-rowflex-direction:rowsm md lg xl
.flex-colflex-direction:columnsm md lg xl
.flex-wrapflex-wrap:wrapsm md lg xl
.flex-nowrapflex-wrap:nowrapsm md lg xl
.flex-row-reverseflex-direction:row-reverse-
.flex-col-reverseflex-direction:column-reverse-
.flex-wrap-reverseflex-wrap:wrap-reverse-
.flex-1flex:1 1 0%-
.flex-autoflex:1 1 auto-
.flex-initialflex:0 1 auto-
.flex-noneflex:none-
.growflex-grow:1-
.grow-0flex-grow:0-
.shrinkflex-shrink:1-
.shrink-0flex-shrink:0-
.basis-0flex-basis:0-
.basis-autoflex-basis:auto-
.basis-fullflex-basis:100%-
.basis-1/2flex-basis:50%-
.basis-1/3flex-basis:33.333333%-
.basis-2/3flex-basis:66.666667%-
.basis-1/4flex-basis:25%-
.basis-3/4flex-basis:75%-
.items-startalign-items:flex-startsm md lg xl
.items-centeralign-items:centersm md lg xl
.items-endalign-items:flex-endsm md lg xl
.items-baselinealign-items:baselinesm md lg xl
.items-stretchalign-items:stretchsm md lg xl
.justify-startjustify-content:flex-startsm md lg xl
.justify-centerjustify-content:centersm md lg xl
.justify-endjustify-content:flex-endsm md lg xl
.justify-betweenjustify-content:space-betweensm md lg xl
.justify-aroundjustify-content:space-aroundsm md lg xl
.justify-evenlyjustify-content:space-evenlysm md lg xl
.self-autoalign-self:auto-
.self-startalign-self:flex-start-
.self-centeralign-self:center-
.self-endalign-self:flex-end-
.self-baselinealign-self:baseline-
.self-stretchalign-self:stretch-
.content-startalign-content:flex-start-
.content-centeralign-content:center-
.content-endalign-content:flex-end-
.content-betweenalign-content:space-between-
.place-items-centerplace-items:center-
.place-content-centerplace-content:center-
.justify-items-centerjustify-items:center-
.justify-self-startjustify-self:start-
.justify-self-centerjustify-self:center-
.justify-self-endjustify-self:end-
.place-self-centerplace-self:center-
.grid-cols-1grid-template-columns:repeat(1,minmax(0,1fr))sm md lg xl
.grid-cols-2grid-template-columns:repeat(2,minmax(0,1fr))sm md lg xl
.grid-cols-3grid-template-columns:repeat(3,minmax(0,1fr))sm md lg xl
.grid-cols-4grid-template-columns:repeat(4,minmax(0,1fr))sm md lg xl
.grid-cols-5grid-template-columns:repeat(5,minmax(0,1fr))sm md lg xl
.grid-cols-6grid-template-columns:repeat(6,minmax(0,1fr))sm md lg xl
.grid-cols-12grid-template-columns:repeat(12,minmax(0,1fr))sm md lg xl
.grid-cols-nonegrid-template-columns:none-
.col-span-1grid-column:span 1sm md lg xl
.col-span-2grid-column:span 2sm md lg xl
.col-span-3grid-column:span 3sm md lg xl
.col-span-4grid-column:span 4sm md lg xl
.col-span-5grid-column:span 5sm md lg xl
.col-span-6grid-column:span 6sm md lg xl
.col-span-8grid-column:span 8sm md lg xl
.col-span-9grid-column:span 9sm md lg xl
.col-span-12grid-column:span 12sm md lg xl
.col-span-fullgrid-column:1/-1sm md lg xl
.col-span-7grid-column:span 7-
.col-span-10grid-column:span 10-
.col-span-11grid-column:span 11-
.col-start-1grid-column-start:1sm md lg xl
.col-start-2grid-column-start:2sm md lg xl
.col-start-3grid-column-start:3sm md lg xl
.col-start-4grid-column-start:4sm md lg xl
.col-start-autogrid-column-start:auto-
.grid-rows-1grid-template-rows:repeat(1,minmax(0,1fr))-
.grid-rows-2grid-template-rows:repeat(2,minmax(0,1fr))-
.grid-rows-3grid-template-rows:repeat(3,minmax(0,1fr))-
.row-span-1grid-row:span 1-
.row-span-2grid-row:span 2-
.row-span-3grid-row:span 3-
.row-span-fullgrid-row:1/-1-
.row-start-1grid-row-start:1-
.grid-flow-rowgrid-auto-flow:row-
.grid-flow-colgrid-auto-flow:column-
.grid-flow-densegrid-auto-flow:dense-
.gap-0gap:0sm md lg xl
.gap-2gap:calc(var(--sh-space)*2)sm md lg xl
.gap-4gap:calc(var(--sh-space)*4)sm md lg xl
.gap-6gap:calc(var(--sh-space)*6)sm md lg xl
.gap-8gap:calc(var(--sh-space)*8)sm md lg xl
.gap-pxgap:1px-
.gap-0.5gap:calc(var(--sh-space)*0.5)-
.gap-1gap:calc(var(--sh-space)*1)-
.gap-1.5gap:calc(var(--sh-space)*1.5)-
.gap-2.5gap:calc(var(--sh-space)*2.5)-
.gap-3gap:calc(var(--sh-space)*3)-
.gap-5gap:calc(var(--sh-space)*5)-
.gap-10gap:calc(var(--sh-space)*10)-
.gap-12gap:calc(var(--sh-space)*12)-
.gap-16gap:calc(var(--sh-space)*16)-
.gap-x-0column-gap:0-
.gap-y-0row-gap:0-
.gap-x-1column-gap:calc(var(--sh-space)*1)-
.gap-y-1row-gap:calc(var(--sh-space)*1)-
.gap-x-2column-gap:calc(var(--sh-space)*2)-
.gap-y-2row-gap:calc(var(--sh-space)*2)-
.gap-x-3column-gap:calc(var(--sh-space)*3)-
.gap-y-3row-gap:calc(var(--sh-space)*3)-
.gap-x-4column-gap:calc(var(--sh-space)*4)-
.gap-y-4row-gap:calc(var(--sh-space)*4)-
.gap-x-6column-gap:calc(var(--sh-space)*6)-
.gap-y-6row-gap:calc(var(--sh-space)*6)-
.gap-x-8column-gap:calc(var(--sh-space)*8)-
.gap-y-8row-gap:calc(var(--sh-space)*8)-
.order-firstorder:-9999sm md lg xl
.order-lastorder:9999sm md lg xl
.order-noneorder:0-
.order-1order:1-
.order-2order:2-
.order-3order:3-

spacing

Spacing: padding, margin, space-x/y (scale via --sh-space) (181 rules)

ClassCSSVariants
.p-0padding:0sm md lg xl
.p-2padding:calc(var(--sh-space)*2)sm md lg xl
.p-4padding:calc(var(--sh-space)*4)sm md lg xl
.p-6padding:calc(var(--sh-space)*6)sm md lg xl
.p-8padding:calc(var(--sh-space)*8)sm md lg xl
.p-12padding:calc(var(--sh-space)*12)sm md lg xl
.p-16padding:calc(var(--sh-space)*16)sm md lg xl
.p-pxpadding:1px-
.p-0.5padding:calc(var(--sh-space)*0.5)-
.p-1padding:calc(var(--sh-space)*1)-
.p-1.5padding:calc(var(--sh-space)*1.5)-
.p-2.5padding:calc(var(--sh-space)*2.5)-
.p-3padding:calc(var(--sh-space)*3)-
.p-5padding:calc(var(--sh-space)*5)-
.p-10padding:calc(var(--sh-space)*10)-
.px-0padding-inline:0sm md lg xl
.px-2padding-inline:calc(var(--sh-space)*2)sm md lg xl
.px-4padding-inline:calc(var(--sh-space)*4)sm md lg xl
.px-6padding-inline:calc(var(--sh-space)*6)sm md lg xl
.px-8padding-inline:calc(var(--sh-space)*8)sm md lg xl
.px-pxpadding-inline:1px-
.px-0.5padding-inline:calc(var(--sh-space)*0.5)-
.px-1padding-inline:calc(var(--sh-space)*1)-
.px-1.5padding-inline:calc(var(--sh-space)*1.5)-
.px-2.5padding-inline:calc(var(--sh-space)*2.5)-
.px-3padding-inline:calc(var(--sh-space)*3)-
.px-5padding-inline:calc(var(--sh-space)*5)-
.px-10padding-inline:calc(var(--sh-space)*10)-
.px-12padding-inline:calc(var(--sh-space)*12)-
.py-0padding-block:0sm md lg xl
.py-2padding-block:calc(var(--sh-space)*2)sm md lg xl
.py-4padding-block:calc(var(--sh-space)*4)sm md lg xl
.py-8padding-block:calc(var(--sh-space)*8)sm md lg xl
.py-12padding-block:calc(var(--sh-space)*12)sm md lg xl
.py-16padding-block:calc(var(--sh-space)*16)sm md lg xl
.py-20padding-block:calc(var(--sh-space)*20)sm md lg xl
.py-24padding-block:calc(var(--sh-space)*24)sm md lg xl
.py-pxpadding-block:1px-
.py-0.5padding-block:calc(var(--sh-space)*0.5)-
.py-1padding-block:calc(var(--sh-space)*1)-
.py-1.5padding-block:calc(var(--sh-space)*1.5)-
.py-2.5padding-block:calc(var(--sh-space)*2.5)-
.py-3padding-block:calc(var(--sh-space)*3)-
.py-5padding-block:calc(var(--sh-space)*5)-
.py-6padding-block:calc(var(--sh-space)*6)-
.py-10padding-block:calc(var(--sh-space)*10)-
.pt-0padding-top:0-
.pt-1padding-top:calc(var(--sh-space)*1)-
.pt-2padding-top:calc(var(--sh-space)*2)-
.pt-3padding-top:calc(var(--sh-space)*3)-
.pt-4padding-top:calc(var(--sh-space)*4)-
.pt-6padding-top:calc(var(--sh-space)*6)-
.pt-8padding-top:calc(var(--sh-space)*8)-
.pt-12padding-top:calc(var(--sh-space)*12)-
.pt-16padding-top:calc(var(--sh-space)*16)-
.pt-24padding-top:calc(var(--sh-space)*24)-
.pr-0padding-right:0-
.pr-1padding-right:calc(var(--sh-space)*1)-
.pr-2padding-right:calc(var(--sh-space)*2)-
.pr-3padding-right:calc(var(--sh-space)*3)-
.pr-4padding-right:calc(var(--sh-space)*4)-
.pr-6padding-right:calc(var(--sh-space)*6)-
.pr-8padding-right:calc(var(--sh-space)*8)-
.pb-0padding-bottom:0-
.pb-1padding-bottom:calc(var(--sh-space)*1)-
.pb-2padding-bottom:calc(var(--sh-space)*2)-
.pb-3padding-bottom:calc(var(--sh-space)*3)-
.pb-4padding-bottom:calc(var(--sh-space)*4)-
.pb-6padding-bottom:calc(var(--sh-space)*6)-
.pb-8padding-bottom:calc(var(--sh-space)*8)-
.pb-12padding-bottom:calc(var(--sh-space)*12)-
.pb-16padding-bottom:calc(var(--sh-space)*16)-
.pb-24padding-bottom:calc(var(--sh-space)*24)-
.pl-0padding-left:0-
.pl-1padding-left:calc(var(--sh-space)*1)-
.pl-2padding-left:calc(var(--sh-space)*2)-
.pl-3padding-left:calc(var(--sh-space)*3)-
.pl-4padding-left:calc(var(--sh-space)*4)-
.pl-6padding-left:calc(var(--sh-space)*6)-
.pl-8padding-left:calc(var(--sh-space)*8)-
.m-automargin:autosm md lg xl
.m-0margin:0sm md lg xl
.m-pxmargin:1px-
.m-1margin:calc(var(--sh-space)*1)-
.m-2margin:calc(var(--sh-space)*2)-
.m-3margin:calc(var(--sh-space)*3)-
.m-4margin:calc(var(--sh-space)*4)-
.m-5margin:calc(var(--sh-space)*5)-
.m-6margin:calc(var(--sh-space)*6)-
.m-8margin:calc(var(--sh-space)*8)-
.mx-automargin-inline:autosm md lg xl
.mx-0margin-inline:0-
.mx-pxmargin-inline:1px-
.mx-1margin-inline:calc(var(--sh-space)*1)-
.mx-2margin-inline:calc(var(--sh-space)*2)-
.mx-3margin-inline:calc(var(--sh-space)*3)-
.mx-4margin-inline:calc(var(--sh-space)*4)-
.mx-5margin-inline:calc(var(--sh-space)*5)-
.mx-6margin-inline:calc(var(--sh-space)*6)-
.mx-8margin-inline:calc(var(--sh-space)*8)-
.my-automargin-block:autosm md lg xl
.my-0margin-block:0-
.my-pxmargin-block:1px-
.my-1margin-block:calc(var(--sh-space)*1)-
.my-2margin-block:calc(var(--sh-space)*2)-
.my-3margin-block:calc(var(--sh-space)*3)-
.my-4margin-block:calc(var(--sh-space)*4)-
.my-5margin-block:calc(var(--sh-space)*5)-
.my-6margin-block:calc(var(--sh-space)*6)-
.my-8margin-block:calc(var(--sh-space)*8)-
.my-10margin-block:calc(var(--sh-space)*10)-
.my-12margin-block:calc(var(--sh-space)*12)-
.my-16margin-block:calc(var(--sh-space)*16)-
.my-24margin-block:calc(var(--sh-space)*24)-
.mt-0margin-top:0sm md lg xl
.mt-4margin-top:calc(var(--sh-space)*4)sm md lg xl
.mt-8margin-top:calc(var(--sh-space)*8)sm md lg xl
.mt-automargin-top:auto-
.mt-1margin-top:calc(var(--sh-space)*1)-
.mt-2margin-top:calc(var(--sh-space)*2)-
.mt-3margin-top:calc(var(--sh-space)*3)-
.mt-6margin-top:calc(var(--sh-space)*6)-
.mt-12margin-top:calc(var(--sh-space)*12)-
.mt-16margin-top:calc(var(--sh-space)*16)-
.mt-24margin-top:calc(var(--sh-space)*24)-
.mr-automargin-right:auto-
.mr-0margin-right:0-
.mr-1margin-right:calc(var(--sh-space)*1)-
.mr-2margin-right:calc(var(--sh-space)*2)-
.mr-3margin-right:calc(var(--sh-space)*3)-
.mr-4margin-right:calc(var(--sh-space)*4)-
.mr-6margin-right:calc(var(--sh-space)*6)-
.mr-8margin-right:calc(var(--sh-space)*8)-
.mb-0margin-bottom:0sm md lg xl
.mb-4margin-bottom:calc(var(--sh-space)*4)sm md lg xl
.mb-8margin-bottom:calc(var(--sh-space)*8)sm md lg xl
.mb-automargin-bottom:auto-
.mb-1margin-bottom:calc(var(--sh-space)*1)-
.mb-2margin-bottom:calc(var(--sh-space)*2)-
.mb-3margin-bottom:calc(var(--sh-space)*3)-
.mb-6margin-bottom:calc(var(--sh-space)*6)-
.mb-12margin-bottom:calc(var(--sh-space)*12)-
.mb-16margin-bottom:calc(var(--sh-space)*16)-
.mb-24margin-bottom:calc(var(--sh-space)*24)-
.ml-automargin-left:auto-
.ml-0margin-left:0-
.ml-1margin-left:calc(var(--sh-space)*1)-
.ml-2margin-left:calc(var(--sh-space)*2)-
.ml-3margin-left:calc(var(--sh-space)*3)-
.ml-4margin-left:calc(var(--sh-space)*4)-
.ml-6margin-left:calc(var(--sh-space)*6)-
.ml-8margin-left:calc(var(--sh-space)*8)-
.-mx-1margin-inline:calc(var(--sh-space)*-1)-
.-mx-2margin-inline:calc(var(--sh-space)*-2)-
.-mx-4margin-inline:calc(var(--sh-space)*-4)-
.-mx-8margin-inline:calc(var(--sh-space)*-8)-
.-my-1margin-block:calc(var(--sh-space)*-1)-
.-my-2margin-block:calc(var(--sh-space)*-2)-
.-my-4margin-block:calc(var(--sh-space)*-4)-
.-my-8margin-block:calc(var(--sh-space)*-8)-
.-mt-1margin-top:calc(var(--sh-space)*-1)-
.-mt-2margin-top:calc(var(--sh-space)*-2)-
.-mt-4margin-top:calc(var(--sh-space)*-4)-
.-mt-8margin-top:calc(var(--sh-space)*-8)-
.space-x-0>:not(:last-child)margin-inline-end:0-
.space-y-0>:not(:last-child)margin-block-end:0-
.space-x-1>:not(:last-child)margin-inline-end:calc(var(--sh-space)*1)-
.space-y-1>:not(:last-child)margin-block-end:calc(var(--sh-space)*1)-
.space-x-2>:not(:last-child)margin-inline-end:calc(var(--sh-space)*2)-
.space-y-2>:not(:last-child)margin-block-end:calc(var(--sh-space)*2)-
.space-x-3>:not(:last-child)margin-inline-end:calc(var(--sh-space)*3)-
.space-y-3>:not(:last-child)margin-block-end:calc(var(--sh-space)*3)-
.space-x-4>:not(:last-child)margin-inline-end:calc(var(--sh-space)*4)-
.space-y-4>:not(:last-child)margin-block-end:calc(var(--sh-space)*4)-
.space-x-6>:not(:last-child)margin-inline-end:calc(var(--sh-space)*6)-
.space-y-6>:not(:last-child)margin-block-end:calc(var(--sh-space)*6)-
.space-x-8>:not(:last-child)margin-inline-end:calc(var(--sh-space)*8)-
.space-y-8>:not(:last-child)margin-block-end:calc(var(--sh-space)*8)-
.space-y-10>:not(:last-child)margin-block-end:calc(var(--sh-space)*10)-
.space-y-12>:not(:last-child)margin-block-end:calc(var(--sh-space)*12)-
.space-y-16>:not(:last-child)margin-block-end:calc(var(--sh-space)*16)-

sizing

Sizing: width, height, min/max, size (84 rules)

ClassCSSVariants
.w-fullwidth:100%sm md lg xl
.w-autowidth:autosm md lg xl
.w-1/2width:50%sm md lg xl
.w-1/3width:33.333333%sm md lg xl
.w-2/3width:66.666667%sm md lg xl
.w-1/4width:25%sm md lg xl
.w-3/4width:75%sm md lg xl
.w-0width:0-
.w-pxwidth:1px-
.w-1width:calc(var(--sh-space)*1)-
.w-2width:calc(var(--sh-space)*2)-
.w-3width:calc(var(--sh-space)*3)-
.w-4width:calc(var(--sh-space)*4)-
.w-5width:calc(var(--sh-space)*5)-
.w-6width:calc(var(--sh-space)*6)-
.w-8width:calc(var(--sh-space)*8)-
.w-10width:calc(var(--sh-space)*10)-
.w-12width:calc(var(--sh-space)*12)-
.w-16width:calc(var(--sh-space)*16)-
.w-20width:calc(var(--sh-space)*20)-
.w-24width:calc(var(--sh-space)*24)-
.w-32width:calc(var(--sh-space)*32)-
.w-40width:calc(var(--sh-space)*40)-
.w-48width:calc(var(--sh-space)*48)-
.w-64width:calc(var(--sh-space)*64)-
.w-80width:calc(var(--sh-space)*80)-
.w-screenwidth:100vw-
.w-minwidth:min-content-
.w-maxwidth:max-content-
.w-fitwidth:fit-content-
.h-autoheight:autosm md lg xl
.h-fullheight:100%sm md lg xl
.h-0height:0-
.h-pxheight:1px-
.h-1height:calc(var(--sh-space)*1)-
.h-2height:calc(var(--sh-space)*2)-
.h-3height:calc(var(--sh-space)*3)-
.h-4height:calc(var(--sh-space)*4)-
.h-5height:calc(var(--sh-space)*5)-
.h-6height:calc(var(--sh-space)*6)-
.h-8height:calc(var(--sh-space)*8)-
.h-10height:calc(var(--sh-space)*10)-
.h-12height:calc(var(--sh-space)*12)-
.h-16height:calc(var(--sh-space)*16)-
.h-20height:calc(var(--sh-space)*20)-
.h-24height:calc(var(--sh-space)*24)-
.h-32height:calc(var(--sh-space)*32)-
.h-40height:calc(var(--sh-space)*40)-
.h-48height:calc(var(--sh-space)*48)-
.h-64height:calc(var(--sh-space)*64)-
.h-80height:calc(var(--sh-space)*80)-
.h-screenheight:100vh; height:100dvh-
.h-minheight:min-content-
.h-maxheight:max-content-
.h-fitheight:fit-content-
.min-h-0min-height:0-
.min-h-fullmin-height:100%-
.min-h-screenmin-height:100vh; min-height:100dvh-
.min-h-dvhmin-height:100dvh-
.min-w-0min-width:0-
.min-w-fullmin-width:100%-
.max-w-mdmax-width:28remsm md lg xl
.max-w-lgmax-width:32remsm md lg xl
.max-w-xlmax-width:36remsm md lg xl
.max-w-2xlmax-width:42remsm md lg xl
.max-w-4xlmax-width:56remsm md lg xl
.max-w-fullmax-width:100%sm md lg xl
.max-w-nonemax-width:nonesm md lg xl
.max-w-xsmax-width:20rem-
.max-w-smmax-width:24rem-
.max-w-3xlmax-width:48rem-
.max-w-5xlmax-width:64rem-
.max-w-6xlmax-width:72rem-
.max-w-7xlmax-width:80rem-
.max-w-prosemax-width:65ch-
.max-h-fullmax-height:100%-
.max-h-screenmax-height:100vh; max-height:100dvh-
.size-4width:calc(var(--sh-space)*4); height:calc(var(--sh-space)*4)-
.size-5width:calc(var(--sh-space)*5); height:calc(var(--sh-space)*5)-
.size-6width:calc(var(--sh-space)*6); height:calc(var(--sh-space)*6)-
.size-8width:calc(var(--sh-space)*8); height:calc(var(--sh-space)*8)-
.size-10width:calc(var(--sh-space)*10); height:calc(var(--sh-space)*10)-
.size-12width:calc(var(--sh-space)*12); height:calc(var(--sh-space)*12)-
.size-fullwidth:100%; height:100%-

typography

Shine — typography utilities (66 rules)

ClassCSSVariants
.font-sansfont-family: var(--sh-font-sans)-
.font-seriffont-family: var(--sh-font-serif)-
.font-monofont-family: var(--sh-font-mono)-
.font-headingfont-family: var(--sh-font-heading, var(--sh-font-sans))-
.text-xsfont-size: .75rem; line-height: 1remsm md lg xl
.text-smfont-size: .875rem; line-height: 1.25remsm md lg xl
.text-basefont-size: 1rem; line-height: 1.5remsm md lg xl
.text-lgfont-size: 1.125rem; line-height: 1.75remsm md lg xl
.text-xlfont-size: 1.25rem; line-height: 1.75remsm md lg xl
.text-2xlfont-size: 1.5rem; line-height: 2remsm md lg xl
.text-3xlfont-size: 1.875rem; line-height: 2.25remsm md lg xl
.text-4xlfont-size: 2.25rem; line-height: 2.5remsm md lg xl
.text-5xlfont-size: 3rem; line-height: 1sm md lg xl
.text-6xlfont-size: 3.75rem; line-height: 1-
.font-thinfont-weight: 100-
.font-lightfont-weight: 300-
.font-normalfont-weight: 400-
.font-mediumfont-weight: 500-
.font-semiboldfont-weight: 600-
.font-boldfont-weight: 700-
.font-extraboldfont-weight: 800-
.font-blackfont-weight: 900-
.italicfont-style: italic-
.not-italicfont-style: normal-
.text-lefttext-align: leftsm md lg xl
.text-centertext-align: centersm md lg xl
.text-righttext-align: rightsm md lg xl
.text-justifytext-align: justify-
.leading-noneline-height: 1-
.leading-tightline-height: 1.25-
.leading-snugline-height: 1.375-
.leading-normalline-height: 1.5-
.leading-relaxedline-height: 1.625-
.leading-looseline-height: 2-
.tracking-tightletter-spacing: -.025em-
.tracking-normalletter-spacing: 0-
.tracking-wideletter-spacing: .025em-
.tracking-widerletter-spacing: .05em-
.uppercasetext-transform: uppercase-
.lowercasetext-transform: lowercase-
.capitalizetext-transform: capitalize-
.normal-casetext-transform: none-
.underlinetext-decoration-line: underlinehover
.no-underlinetext-decoration-line: nonehover
.line-throughtext-decoration-line: line-through-
.underline-offset-2text-underline-offset: 2px-
.underline-offset-4text-underline-offset: 4px-
.truncateoverflow: hidden; text-overflow: ellipsis; white-space: nowrap-
.line-clamp-1display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 1; line-clamp: 1; overflow: hidden-
.line-clamp-2display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden-
.line-clamp-3display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; line-clamp: 3; overflow: hidden-
.whitespace-nowrapwhite-space: nowrap-
.whitespace-normalwhite-space: normal-
.whitespace-prewhite-space: pre-
.whitespace-pre-wrapwhite-space: pre-wrap-
.break-wordsoverflow-wrap: break-word-
.break-allword-break: break-all-
.text-balancetext-wrap: balance-
.text-prettytext-wrap: pretty-
.text-wraptext-wrap: wrap-
.text-nowraptext-wrap: nowrap-
.tabular-numsfont-variant-numeric: tabular-nums-
.list-disclist-style-type: disc-
.list-decimallist-style-type: decimal-
.list-nonelist-style-type: none-
.list-insidelist-style-position: inside-

color

Shine — color utilities (semantic + gray). Opacity: .bg-o-50 etc. set --sh-*-o (112 rules)

ClassCSSVariants
.bg-primarybackground-color: color-mix(in oklab, var(--sh-primary) var(--sh-bg-o), transparent)hover
.bg-secondarybackground-color: color-mix(in oklab, var(--sh-secondary) var(--sh-bg-o), transparent)hover
.bg-accentbackground-color: color-mix(in oklab, var(--sh-accent) var(--sh-bg-o), transparent)hover
.bg-successbackground-color: color-mix(in oklab, var(--sh-success) var(--sh-bg-o), transparent)hover
.bg-warningbackground-color: color-mix(in oklab, var(--sh-warning) var(--sh-bg-o), transparent)hover
.bg-dangerbackground-color: color-mix(in oklab, var(--sh-danger) var(--sh-bg-o), transparent)hover
.bg-infobackground-color: color-mix(in oklab, var(--sh-info) var(--sh-bg-o), transparent)hover
.bg-surface-2background-color: color-mix(in oklab, var(--sh-surface-2) var(--sh-bg-o), transparent)hover
.bg-basebackground-color: color-mix(in oklab, var(--sh-bg) var(--sh-bg-o), transparent)-
.bg-surfacebackground-color: color-mix(in oklab, var(--sh-surface) var(--sh-bg-o), transparent)-
.bg-whitebackground-color: color-mix(in oklab, #fff var(--sh-bg-o), transparent)-
.bg-blackbackground-color: color-mix(in oklab, #000 var(--sh-bg-o), transparent)-
.bg-gray-50background-color: color-mix(in oklab, #f8fafc var(--sh-bg-o), transparent)-
.bg-gray-100background-color: color-mix(in oklab, #f1f5f9 var(--sh-bg-o), transparent)-
.bg-gray-200background-color: color-mix(in oklab, #e2e8f0 var(--sh-bg-o), transparent)-
.bg-gray-300background-color: color-mix(in oklab, #cbd5e1 var(--sh-bg-o), transparent)-
.bg-gray-400background-color: color-mix(in oklab, #94a3b8 var(--sh-bg-o), transparent)-
.bg-gray-500background-color: color-mix(in oklab, #64748b var(--sh-bg-o), transparent)-
.bg-gray-600background-color: color-mix(in oklab, #475569 var(--sh-bg-o), transparent)-
.bg-gray-700background-color: color-mix(in oklab, #334155 var(--sh-bg-o), transparent)-
.bg-gray-800background-color: color-mix(in oklab, #1e293b var(--sh-bg-o), transparent)-
.bg-gray-900background-color: color-mix(in oklab, #0f172a var(--sh-bg-o), transparent)-
.bg-gray-950background-color: color-mix(in oklab, #020617 var(--sh-bg-o), transparent)-
.bg-transparentbackground-color: transparent-
.bg-currentbackground-color: currentColor-
.bg-primary-softbackground-color: color-mix(in oklab, var(--sh-primary) 15%, transparent)-
.bg-secondary-softbackground-color: color-mix(in oklab, var(--sh-secondary) 15%, transparent)-
.bg-accent-softbackground-color: color-mix(in oklab, var(--sh-accent) 15%, transparent)-
.bg-success-softbackground-color: color-mix(in oklab, var(--sh-success) 15%, transparent)-
.bg-warning-softbackground-color: color-mix(in oklab, var(--sh-warning) 15%, transparent)-
.bg-danger-softbackground-color: color-mix(in oklab, var(--sh-danger) 15%, transparent)-
.bg-info-softbackground-color: color-mix(in oklab, var(--sh-info) 15%, transparent)-
.text-primarycolor: color-mix(in oklab, color-mix(in oklab, var(--sh-primary) var(--sh-brand-text, 100%), var(--sh-text)) var(--sh-text-o), transparent)hover
.text-secondarycolor: color-mix(in oklab, color-mix(in oklab, var(--sh-secondary) var(--sh-brand-text, 100%), var(--sh-text)) var(--sh-text-o), transparent)hover
.text-accentcolor: color-mix(in oklab, color-mix(in oklab, var(--sh-accent) var(--sh-brand-text, 100%), var(--sh-text)) var(--sh-text-o), transparent)hover
.text-successcolor: color-mix(in oklab, color-mix(in oklab, var(--sh-success) var(--sh-brand-text, 100%), var(--sh-text)) var(--sh-text-o), transparent)hover
.text-warningcolor: color-mix(in oklab, color-mix(in oklab, var(--sh-warning) var(--sh-brand-text, 100%), var(--sh-text)) var(--sh-text-o), transparent)hover
.text-dangercolor: color-mix(in oklab, color-mix(in oklab, var(--sh-danger) var(--sh-brand-text, 100%), var(--sh-text)) var(--sh-text-o), transparent)hover
.text-infocolor: color-mix(in oklab, color-mix(in oklab, var(--sh-info) var(--sh-brand-text, 100%), var(--sh-text)) var(--sh-text-o), transparent)hover
.text-defaultcolor: color-mix(in oklab, var(--sh-text) var(--sh-text-o), transparent)-
.text-mutedcolor: color-mix(in oklab, var(--sh-text-muted) var(--sh-text-o), transparent)-
.text-whitecolor: color-mix(in oklab, #fff var(--sh-text-o), transparent)-
.text-blackcolor: color-mix(in oklab, #000 var(--sh-text-o), transparent)-
.text-gray-50color: color-mix(in oklab, #f8fafc var(--sh-text-o), transparent)-
.text-gray-100color: color-mix(in oklab, #f1f5f9 var(--sh-text-o), transparent)-
.text-gray-200color: color-mix(in oklab, #e2e8f0 var(--sh-text-o), transparent)-
.text-gray-300color: color-mix(in oklab, #cbd5e1 var(--sh-text-o), transparent)-
.text-gray-400color: color-mix(in oklab, #94a3b8 var(--sh-text-o), transparent)-
.text-gray-500color: color-mix(in oklab, #64748b var(--sh-text-o), transparent)-
.text-gray-600color: color-mix(in oklab, #475569 var(--sh-text-o), transparent)-
.text-gray-700color: color-mix(in oklab, #334155 var(--sh-text-o), transparent)-
.text-gray-800color: color-mix(in oklab, #1e293b var(--sh-text-o), transparent)-
.text-gray-900color: color-mix(in oklab, #0f172a var(--sh-text-o), transparent)-
.text-gray-950color: color-mix(in oklab, #020617 var(--sh-text-o), transparent)-
.text-transparentcolor: transparent-
.text-currentcolor: currentColor-
.text-on-primarycolor: var(--sh-on-primary)-
.text-on-secondarycolor: var(--sh-on-secondary)-
.text-on-accentcolor: var(--sh-on-accent)-
.text-on-successcolor: var(--sh-on-success)-
.text-on-warningcolor: var(--sh-on-warning)-
.text-on-dangercolor: var(--sh-on-danger)-
.text-on-infocolor: var(--sh-on-info)-
.bg-o-0--sh-bg-o: 0%-
.bg-o-5--sh-bg-o: 5%-
.bg-o-10--sh-bg-o: 10%-
.bg-o-20--sh-bg-o: 20%-
.bg-o-25--sh-bg-o: 25%-
.bg-o-30--sh-bg-o: 30%-
.bg-o-40--sh-bg-o: 40%-
.bg-o-50--sh-bg-o: 50%-
.bg-o-60--sh-bg-o: 60%-
.bg-o-70--sh-bg-o: 70%-
.bg-o-75--sh-bg-o: 75%-
.bg-o-80--sh-bg-o: 80%-
.bg-o-90--sh-bg-o: 90%-
.bg-o-95--sh-bg-o: 95%-
.bg-o-100--sh-bg-o: 100%-
.text-o-50--sh-text-o: 50%-
.text-o-60--sh-text-o: 60%-
.text-o-70--sh-text-o: 70%-
.text-o-75--sh-text-o: 75%-
.text-o-80--sh-text-o: 80%-
.text-o-90--sh-text-o: 90%-
border colors
.border-primaryborder-color: color-mix(in oklab, var(--sh-primary) var(--sh-border-o), transparent)-
.border-secondaryborder-color: color-mix(in oklab, var(--sh-secondary) var(--sh-border-o), transparent)-
.border-accentborder-color: color-mix(in oklab, var(--sh-accent) var(--sh-border-o), transparent)-
.border-successborder-color: color-mix(in oklab, var(--sh-success) var(--sh-border-o), transparent)-
.border-warningborder-color: color-mix(in oklab, var(--sh-warning) var(--sh-border-o), transparent)-
.border-dangerborder-color: color-mix(in oklab, var(--sh-danger) var(--sh-border-o), transparent)-
.border-infoborder-color: color-mix(in oklab, var(--sh-info) var(--sh-border-o), transparent)-
.border-defaultborder-color: color-mix(in oklab, var(--sh-border) var(--sh-border-o), transparent)-
.border-gray-100border-color: color-mix(in oklab, #f1f5f9 var(--sh-border-o), transparent)-
.border-gray-200border-color: color-mix(in oklab, #e2e8f0 var(--sh-border-o), transparent)-
.border-gray-300border-color: color-mix(in oklab, #cbd5e1 var(--sh-border-o), transparent)-
.border-gray-400border-color: color-mix(in oklab, #94a3b8 var(--sh-border-o), transparent)-
.border-gray-500border-color: color-mix(in oklab, #64748b var(--sh-border-o), transparent)-
.border-gray-600border-color: color-mix(in oklab, #475569 var(--sh-border-o), transparent)-
.border-gray-700border-color: color-mix(in oklab, #334155 var(--sh-border-o), transparent)-
.border-gray-800border-color: color-mix(in oklab, #1e293b var(--sh-border-o), transparent)-
.border-whiteborder-color: #fff-
.border-blackborder-color: #000-
.border-transparentborder-color: transparent-
.border-currentborder-color: currentColor-
.border-o-50--sh-border-o: 50%-
.border-o-60--sh-border-o: 60%-
.border-o-70--sh-border-o: 70%-
.border-o-75--sh-border-o: 75%-
.border-o-80--sh-border-o: 80%-
.border-o-90--sh-border-o: 90%-
.fill-currentfill: currentColor-
.stroke-currentstroke: currentColor-

borders

Shine — borders, radius, rings. Loads after color.css: default border-color uses :where() (0 specificity) so .border-{color} always wins. (57 rules)

ClassCSSVariants
.borderborder-width: var(--sh-border-width); border-style: solidsm md lg xl
.border-0border-width: 0sm md lg xl
.border-2border-width: 2px; border-style: solid-
.border-4border-width: 4px; border-style: solid-
.border-xborder-left-width: var(--sh-border-width); border-right-width: var(--sh-border-width); border-style: solid-
.border-x-0border-left-width: 0; border-right-width: 0-
.border-yborder-top-width: var(--sh-border-width); border-bottom-width: var(--sh-border-width); border-style: solid-
.border-y-0border-top-width: 0; border-bottom-width: 0-
.border-tborder-top-width: var(--sh-border-width); border-style: solid-
.border-t-0border-top-width: 0-
.border-rborder-right-width: var(--sh-border-width); border-style: solid-
.border-r-0border-right-width: 0-
.border-bborder-bottom-width: var(--sh-border-width); border-style: solid-
.border-b-0border-bottom-width: 0-
.border-lborder-left-width: var(--sh-border-width); border-style: solid-
.border-l-0border-left-width: 0-
.border-solidborder-style: solid-
.border-dashedborder-style: dashed-
.border-dottedborder-style: dotted-
.border-noneborder-style: none-
.rounded-noneborder-radius: 0-
.rounded-smborder-radius: calc(var(--sh-radius) * .5)-
.roundedborder-radius: var(--sh-radius)-
.rounded-mdborder-radius: calc(var(--sh-radius) * 1.25)-
.rounded-lgborder-radius: calc(var(--sh-radius) * 1.5)-
.rounded-xlborder-radius: calc(var(--sh-radius) * 2)-
.rounded-2xlborder-radius: calc(var(--sh-radius) * 3)-
.rounded-fullborder-radius: 9999px-
.rounded-tborder-top-left-radius: var(--sh-radius); border-top-right-radius: var(--sh-radius)-
.rounded-t-lgborder-top-left-radius: calc(var(--sh-radius) * 1.5); border-top-right-radius: calc(var(--sh-radius) * 1.5)-
.rounded-t-noneborder-top-left-radius: 0; border-top-right-radius: 0-
.rounded-rborder-top-right-radius: var(--sh-radius); border-bottom-right-radius: var(--sh-radius)-
.rounded-r-lgborder-top-right-radius: calc(var(--sh-radius) * 1.5); border-bottom-right-radius: calc(var(--sh-radius) * 1.5)-
.rounded-r-noneborder-top-right-radius: 0; border-bottom-right-radius: 0-
.rounded-bborder-bottom-left-radius: var(--sh-radius); border-bottom-right-radius: var(--sh-radius)-
.rounded-b-lgborder-bottom-left-radius: calc(var(--sh-radius) * 1.5); border-bottom-right-radius: calc(var(--sh-radius) * 1.5)-
.rounded-b-noneborder-bottom-left-radius: 0; border-bottom-right-radius: 0-
.rounded-lborder-top-left-radius: var(--sh-radius); border-bottom-left-radius: var(--sh-radius)-
.rounded-l-lgborder-top-left-radius: calc(var(--sh-radius) * 1.5); border-bottom-left-radius: calc(var(--sh-radius) * 1.5)-
.rounded-l-noneborder-top-left-radius: 0; border-bottom-left-radius: 0-
.divide-x > :not(:last-child)border-right-width: var(--sh-border-width); border-style: solid-
.divide-y > :not(:last-child)border-bottom-width: var(--sh-border-width); border-style: solid-
.divide-x-0 > :not(:last-child)border-right-width: 0-
.divide-y-0 > :not(:last-child)border-bottom-width: 0-
.ring-0box-shadow: 0 0 0 0 var(--sh-ring-color, color-mix(in oklab, var(--sh-tone, var(--sh-primary)) 50%, transparent))-
.ring-1box-shadow: 0 0 0 1px var(--sh-ring-color, color-mix(in oklab, var(--sh-tone, var(--sh-primary)) 50%, transparent))-
.ringbox-shadow: 0 0 0 3px var(--sh-ring-color, color-mix(in oklab, var(--sh-tone, var(--sh-primary)) 50%, transparent))-
.ring-2box-shadow: 0 0 0 2px var(--sh-ring-color, color-mix(in oklab, var(--sh-tone, var(--sh-primary)) 50%, transparent))-
.ring-4box-shadow: 0 0 0 4px var(--sh-ring-color, color-mix(in oklab, var(--sh-tone, var(--sh-primary)) 50%, transparent))-
.ring-primary--sh-ring-color: color-mix(in oklab, var(--sh-primary) 50%, transparent)-
.ring-secondary--sh-ring-color: color-mix(in oklab, var(--sh-secondary) 50%, transparent)-
.ring-accent--sh-ring-color: color-mix(in oklab, var(--sh-accent) 50%, transparent)-
.ring-success--sh-ring-color: color-mix(in oklab, var(--sh-success) 50%, transparent)-
.ring-warning--sh-ring-color: color-mix(in oklab, var(--sh-warning) 50%, transparent)-
.ring-danger--sh-ring-color: color-mix(in oklab, var(--sh-danger) 50%, transparent)-
.ring-info--sh-ring-color: color-mix(in oklab, var(--sh-info) 50%, transparent)-
.outline-noneoutline: 2px solid transparent; outline-offset: 2px-

effects

Shine — minimal effects (shadows, opacity, backdrop blur) (28 rules)

ClassCSSVariants
.shadow-nonebox-shadow: nonehover
.shadow-smbox-shadow: var(--sh-shadow-1)hover
.shadowbox-shadow: var(--sh-shadow-2)hover
.shadow-mdbox-shadow: var(--sh-shadow-3)hover
.shadow-lgbox-shadow: var(--sh-shadow-4)hover
.shadow-xl, .shadow-2xlbox-shadow: var(--sh-shadow-5)hover
.shadow-tonebox-shadow: 0 8px 24px -6px color-mix(in oklab, var(--sh-tone, var(--sh-primary)) 50%, transparent)hover
.shadow-innerbox-shadow: inset 0 2px 4px rgb(0 0 0 / .08)-
.shadow-elevationbox-shadow: var(--sh-elevation, var(--sh-shadow-1))-
.opacity-0opacity: 0hover
.opacity-50opacity: .5hover
.opacity-75opacity: .75hover
.opacity-100opacity: 1hover
.opacity-5opacity: .05-
.opacity-10opacity: .1-
.opacity-20opacity: .2-
.opacity-25opacity: .25-
.opacity-80opacity: .8-
.opacity-90opacity: .9-
.opacity-95opacity: .95-
Backdrop filters: blur and saturate combine (frosted glass)
:where(.backdrop-blur-none, .backdrop-blur-sm, .backdrop-blur, .backdrop-blur-md, .backdrop-blur-lg, .backdrop-blur-xl, .backdrop-saturate-150)backdrop-filter: blur(var(--sh-bd-blur, 0)) saturate(var(--sh-bd-sat, 1))-
.backdrop-blur-none--sh-bd-blur: 0-
.backdrop-blur-sm--sh-bd-blur: 4px-
.backdrop-blur--sh-bd-blur: 8px-
.backdrop-blur-md--sh-bd-blur: 12px-
.backdrop-blur-lg--sh-bd-blur: 16px-
.backdrop-blur-xl--sh-bd-blur: 24px-
.backdrop-saturate-150--sh-bd-sat: 1.5-

interactivity

Shine — interactivity & transitions (38 rules)

ClassCSSVariants
.cursor-pointercursor: pointer-
.cursor-defaultcursor: default-
.cursor-not-allowedcursor: not-allowed-
.cursor-waitcursor: wait-
.cursor-textcursor: text-
.cursor-movecursor: move-
.cursor-grabcursor: grab-
.pointer-events-nonepointer-events: none-
.pointer-events-autopointer-events: auto-
.select-noneuser-select: none-
.select-textuser-select: text-
.select-alluser-select: all-
.select-autouser-select: auto-
.resizeresize: both-
.resize-noneresize: none-
.resize-xresize: horizontal-
.resize-yresize: vertical-
.scroll-smoothscroll-behavior: smooth-
.snap-xscroll-snap-type: x mandatory-
.snap-yscroll-snap-type: y mandatory-
.snap-startscroll-snap-align: start-
.snap-centerscroll-snap-align: center-
.appearance-noneappearance: none-
.touch-nonetouch-action: none-
.touch-manipulationtouch-action: manipulation-
.transitiontransition-property: color, background-color, border-color, opacity, box-shadow, transform; transition-timing-function: var(--sh-ease); transition-duration: var(--sh-duration)-
.transition-colorstransition-property: color, background-color, border-color; transition-timing-function: var(--sh-ease); transition-duration: var(--sh-duration)-
.transition-opacitytransition-property: opacity; transition-timing-function: var(--sh-ease); transition-duration: var(--sh-duration)-
.transition-nonetransition-property: none-
.duration-75transition-duration: 75ms-
.duration-150transition-duration: 150ms-
.duration-200transition-duration: 200ms-
.duration-300transition-duration: 300ms-
.duration-500transition-duration: 500ms-
.ease-lineartransition-timing-function: linear-
.ease-intransition-timing-function: cubic-bezier(.4, 0, 1, 1)-
.ease-outtransition-timing-function: cubic-bezier(0, 0, .2, 1)-
.ease-in-outtransition-timing-function: cubic-bezier(.4, 0, .2, 1)-

extras

Extras: centering/position helpers, translate, object/overflow/overscroll, container queries (64 rules)

ClassCSSVariants
.top-1/2top:50%-
.left-1/2left:50%-
.right-1/2right:50%-
.bottom-1/2bottom:50%-
.top-fulltop:100%-
.left-fullleft:100%-
.right-fullright:100%-
.bottom-fullbottom:100%-
.inset-2inset:calc(var(--sh-space)*2)-
.inset-4inset:calc(var(--sh-space)*4)-
.-translate-x-1/2translate:-50% 0-
.-translate-y-1/2translate:0 -50%-
.-translate-1/2translate:-50% -50%-
.object-centerobject-position:center-
.object-topobject-position:top-
.overflow-clipoverflow:clip-
.overscroll-containoverscroll-behavior:contain-
.cqcontainer-type:inline-size-
Tables
.table-autotable-layout:auto-
.table-fixedtable-layout:fixed-
.border-collapseborder-collapse:collapse-
.border-separateborder-collapse:separate-
.caption-topcaption-side:top-
.caption-bottomcaption-side:bottom-
Logical / RTL-aware spacing and edges
.ps-0padding-inline-start:0-
.ps-2padding-inline-start:calc(var(--sh-space)*2)-
.ps-4padding-inline-start:calc(var(--sh-space)*4)-
.pe-0padding-inline-end:0-
.pe-2padding-inline-end:calc(var(--sh-space)*2)-
.pe-4padding-inline-end:calc(var(--sh-space)*4)-
.ms-automargin-inline-start:auto-
.ms-2margin-inline-start:calc(var(--sh-space)*2)-
.ms-4margin-inline-start:calc(var(--sh-space)*4)-
.me-automargin-inline-end:auto-
.me-2margin-inline-end:calc(var(--sh-space)*2)-
.me-4margin-inline-end:calc(var(--sh-space)*4)-
.start-0inset-inline-start:0-
.end-0inset-inline-end:0-
.text-starttext-align:start-
.text-endtext-align:end-
.border-sborder-inline-start-width:var(--sh-border-width)-
.border-eborder-inline-end-width:var(--sh-border-width)-
.rounded-sborder-start-start-radius:var(--sh-radius); border-end-start-radius:var(--sh-radius)-
.rounded-eborder-start-end-radius:var(--sh-radius); border-end-end-radius:var(--sh-radius)-
Background images
.bg-coverbackground-size:cover-
.bg-containbackground-size:contain-
.bg-centerbackground-position:center-
.bg-topbackground-position:top-
.bg-bottombackground-position:bottom-
.bg-no-repeatbackground-repeat:no-repeat-
.bg-fixedbackground-attachment:fixed-
Floats
.float-leftfloat:left-
.float-rightfloat:right-
.float-nonefloat:none-
.clear-bothclear:both-
Text and flow
.antialiased-webkit-font-smoothing:antialiased; -moz-osx-font-smoothing:grayscale-
.hyphens-autohyphens:auto-
.text-ellipsistext-overflow:ellipsis-
.break-inside-avoidbreak-inside:avoid-
Grid tracks, sizing, forms
.auto-rows-frgrid-auto-rows:minmax(0,1fr)-
.auto-cols-frgrid-auto-columns:minmax(0,1fr)-
.min-w-maxmin-width:max-content-
.min-h-svhmin-height:100svh-
.field-sizing-contentfield-sizing:content-

Variants and cascade

Responsive prefixes

Mobile first. An unprefixed class applies everywhere; a prefixed class applies at that width and up. Only layout-critical utilities have them (see the Variants column above).

PrefixMin widthExample
sm:640px and upsm:grid-cols-3
md:768px and upmd:grid-cols-3
lg:1024px and uplg:grid-cols-3
xl:1280px and upxl:grid-cols-3
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">…</div>

Hover and focus

hover: applies on pointer hover. focus: applies on :focus-visible, so it only shows for keyboard focus. They exist on colors, opacity, shadow and underline.

<a class="text-muted hover:text-primary focus:underline" href="#">Link</a>

There is no dark: variant. Themes switch dark mode through tokens, so the same classes work in both.

Cascade layers

Shine is built with CSS @layer. Utilities beat components, components beat base, and your own unlayered CSS beats everything, with no specificity fights.

@layer shine.tokens, shine.reset, shine.base, shine.components, shine.utilities;

Opacity modifiers

Opacity is a second class, not a slash. Add bg-o-50 next to a background color (also text-o-* and border-o-*).

<div class="bg-primary bg-o-50 p-4">Half-transparent primary</div>

Differences from Tailwind

  • Semantic colors. bg-primary, text-danger, bg-primary-soft, text-muted, bg-surface, plus one gray-50 to gray-950 scale. Add brand colors as tokens.
  • Opacity modifier classes (bg-o-50) instead of bg-primary/50.
  • Radius scales with data-radius: rounded-lg is 1.5 times the global radius.
  • Spacing scales with --sh-space (default .25rem): p-4 is 4 units.
  • No arbitrary values like w-[13px]; use inline styles or your own CSS.
  • No dark: variant. Use data-theme.
  • Fewer variants. Only responsive on layout, hover and focus on colors and effects.