Glassmorphism UI Library
A complete CSS component library with glassmorphism aesthetics β built by Jungherz GmbH. Pure CSS, no dependencies, Dark & Light mode.
Installation
Include one CSS file β done. Optionally add a theme override for custom brand colors.
Design Tokens
All visual values are controlled via CSS Custom Properties.
Color Palette
| Token | Dark Value | Usage |
|---|---|---|
--gl-color-primary | #f5a623 | Primary color, buttons, active elements |
--gl-color-primary-dark | #d4692a | Gradient end value |
--gl-color-text | #ffffff | Default text color |
--gl-color-text-muted | rgba(255,255,255,0.60) | Secondary text |
--gl-color-success | #34c759 | Success status |
--gl-color-error | #ff3b30 | Error status |
--gl-color-warning | #ffcc00 | Warning status |
--gl-color-{state}-surface, -border, -on-surface | color-mix(…) | Tinted fill, border and text of a state badge, derived from the state colour — for success, error and, since 1.18.0, warning |
Glass Surfaces
| Token | Value | Usage |
|---|---|---|
--gl-surface-1 | rgba(β¦, 0.08) | Subtlest surface (status) |
--gl-surface-2 | rgba(β¦, 0.10) | Default (inputs, cards) |
--gl-surface-3 | rgba(β¦, 0.14) | Nav pills, badges |
--gl-surface-4 | rgba(β¦, 0.16) | Hover states |
--gl-surface-5 | rgba(β¦, 0.22) | Strong hover |
--gl-surface-milk-strong | rgba(β¦, 0.75) | Secondary button |
Spacing & Radii
| Token | Value | Token | Value |
|---|---|---|---|
--gl-space-2xs | 4px | --gl-radius-xs | 8px |
--gl-space-xs | 8px | --gl-radius-sm | 12px |
--gl-space-sm | 12px | --gl-radius-input | 14px |
--gl-space-md | 16px | --gl-radius-btn | 16px |
--gl-space-lg | 20px | --gl-radius-card | 24px |
--gl-space-xl | 24px | --gl-radius-full | 9999px |
--gl-space-2xl | 32px | --gl-radius-pill | 50% |
Theming (Light / Dark)
The theme is controlled via data-theme on the <html> element.
Background
The glass effect requires a colored background.
| Class | Description |
|---|---|
.glass-bg | Full background with aurora light effects |
.glass-bg--has-tab-bar | Modifier: bottom padding for tab bar |
.glass-bg--has-tab-bar-floating | Modifier: bottom padding for floating tab bar + accessory |
Pill-Buttons
Round icon buttons for navigation and actions.
| Class | Description |
|---|---|
.glass-pill | Standard glass circle (46Γ46px) |
.glass-theme-toggle | Pill with moon/sun icon switch |
Tab-Bar
Fixed bottom navigation with glass background and optional badge.
Tab-Bar β Floating
Pill-shaped, centered, floating variant inspired by iOS 26 Liquid Glass. Pair with an optional .glass-tab-bar__accessory capsule (e.g. search, compose) β sits next to the bar with its own glass material. The active tab gets a soft radial Spotlight halo instead of the underline dot.
Accessory accent variants
Add --accent, --success, or --error to highlight the accessory with a colored capsule (filled background, white icon).
| Class | Description |
|---|---|
.glass-tab-bar-dock | Wrapper: fixed bottom-center, holds bar + accessory |
.glass-tab-bar-dock--accessory-left | Modifier: place accessory on the left |
.glass-tab-bar--floating | Modifier on .glass-tab-bar: pill shape, max-content width |
.glass-tab-bar__accessory | Standalone glass capsule next to the bar |
.glass-tab-bar__accessory--accent | Filled with primary color |
.glass-tab-bar__accessory--success | Filled with success color |
.glass-tab-bar__accessory--error | Filled with error color |
.glass-bg--has-tab-bar-floating | Background padding helper for the floating variant |
Title
Capture Contracts
& Upload
Card
Photograph your document, verify edges, and upload in batch.
| Class | Description |
|---|---|
.glass-card | Base glass surface |
.glass-card--glow | Light β milky gradient + light streak |
.glass-card__icon | Centered icon wrapper |
.glass-card__text | Description text |
Buttons
| Class | Description |
|---|---|
.glass-btn | Base (56px, full width) |
--primary | Colored gradient |
--secondary | Milky white |
--tertiary | Subtle glass |
--sm | 44px height |
--lg | 64px height |
--auto | Auto width |
svg.glass-icon--fill | Deliberately filled icon (e.g. brand logos) |
Badge
Variants: --primary, --success, --warning (since 1.18.0) and --error. Each draws its fill, border and text from the state colour’s -surface, -border and -on-surface tokens, so re-colouring the state colour moves the whole badge.
Chips
A badge doubles as a filter chip. --interactive carries the affordance — pointer cursor, hover tint, focus ring — and --selected says which chip is on. Use a real <button> and put the state in aria-pressed, so the row works by keyboard and is announced as a toggle.
--selected deepens the colour the badge already carries instead of overruling it, so a status chip stays in its own colour when it is picked.
| Class | Description |
|---|---|
--interactive | Pressable: cursor, hover tint, focus ring, press feedback |
--selected | The chip that is on — deepens the badge's own colour |
--gl-badge-accent | The colour both states deepen. Set it per badge to give a chip a colour of its own. |
Avatar
Divider
Status Notice
No documents captured yet.
List
Grouped settings-style container for stacked rows. Items support a leading icon, title + optional subtitle, and a trailing element (chevron, value, button). Dividers between items are drawn automatically — no extra markup needed.
Settings style (icon + title + subtitle + trailing)
-
iOS 26.4 Update2.1 GB · Available now
-
Apple OneFamily — renews Apr 28$22.95
-
Notifications
- View all subscriptions
Compact menu (centered text, no icons)
- Share document
- Duplicate
- Delete
Grouped sections with large icons
-
Review downloaded mediaSave up to 1.38 GB. Review all videos and audio files downloaded on your device and remove them as needed.
-
AusweisApp BundVersion 2.5.124 MB
-
Ghost in the MachinePartially watched237.1 MB
- View all downloads
Class reference
| Class | Description |
|---|---|
.glass-list | Grouped surface container |
.glass-list--flush | Edge-to-edge variant (no side margin / radius). Assumes parent has --gl-space-lg horizontal padding. |
.glass-list--bare | Strips background, border & shadow — for embedding inside .glass-popover or .glass-card. |
.glass-list__item | List row (use <li>, <a>, or <button>) |
.glass-list__section-header | Section label above a .glass-list — uppercase, small, muted |
.glass-list__item--interactive | Adds hover / focus / active states |
.glass-list__item--center | Centered single-text variant with ellipsis truncation |
.glass-list__item--danger | Red text for destructive actions |
.glass-list__item--accent | Primary-colored text for accent actions |
.glass-list__leading | Leading slot (28×28, holds an icon SVG) |
.glass-list__leading--lg | Large leading slot (40×40, rounded square, supports <img>) |
.glass-list__content | Flexible middle slot — takes remaining width, enables truncation |
.glass-list__title | Primary text (medium weight, ellipsis) |
.glass-list__subtitle | Secondary text (small, muted, ellipsis) |
.glass-list__subtitle--wrap | Multi-line subtitle (up to 3 lines, clamped with ellipsis) |
.glass-list__trailing | Trailing slot — chevron, value, button, badge |
.glass-list__value | Muted text inside .glass-list__trailing (e.g. file size) |
Dividers between rows are rendered automatically via ::after. Items with a leading icon get an icon-aligned inset; items without get a standard left/right padding inset. The last item never has a divider. SVG icon convention: 24px for leading, 18px for trailing, stroke: currentColor, stroke-width: 2.
Modal
Centered dialog with blur overlay. Visibility is controlled via the .is-active class on the overlay element — toggling it requires a tiny bit of JavaScript.
Delete document?
This action cannot be undone.
Class reference
| Class | Description |
|---|---|
.glass-modal-overlay | Fullscreen blur overlay |
.glass-modal-overlay.is-active | Visible + animated |
.glass-modal | Dialog container (max-width 340px) |
__header / __title | Title area |
__body | Content area |
__footer / __action | Action bar |
__action--primary | Primary action |
__action--danger | Dangerous action |
Note: the .is-active class belongs on the .glass-modal-overlay, not on .glass-modal itself. The overlay handles the fullscreen backdrop, and its :is-active state triggers both the backdrop fade-in and the inner dialog's scale-up animation.
Toast
Visible via .is-visible. Variants: --success, --error, --warning.
With an action (since 1.19.0): __action is a small pill in the toast’s own tone — primary on a plain toast, the state colour on a variant — and __close the × at the end; give it an aria-label. Both have a 44 px hit area. A toast with an action may grow to 480 px, the text wraps, the buttons never shrink; it should stay until one of them is used. The toast sits --gl-toast-top from the top (56 px unless set) — set it below your header, and add env(safe-area-inset-top) with viewport-fit=cover. It stays at the top also with an action: one place for every toast.
| Class | Description |
|---|---|
.glass-toast, .is-visible | Fixed at the top, faded in while visible |
--success, --error, --warning | Colour the icon; tint the action in the state colour |
__icon, __text | 22 px stroked icon, message (wraps and yields) |
__action | One action: pill in the toast’s tone, 44 px hit area, never shrinks (since 1.19.0) |
__close | The ×, 28 px with a 44 px hit area (since 1.19.0) |
--gl-toast-top | Distance from the top, default var(--gl-space-4xl) (since 1.19.0) |
Popover
Anchored dropdown / menu container. Wrap a trigger and a .glass-popover in a .glass-popover-anchor. Visibility is controlled via the .is-open class — toggling it requires a tiny bit of JavaScript.
Class reference
| Class | Description |
|---|---|
.glass-popover-anchor | Positioning context for the popover (wraps trigger + popover) |
.glass-popover | Floating glass surface, hidden until .is-open |
.glass-popover.is-open | Visible state — fade + scale animation |
.glass-popover--top | Opens upward (above the trigger) |
.glass-popover--start | Aligns left edge with trigger |
.glass-popover--end | Aligns right edge with trigger |
Note: name your toggle function anything except togglePopover — that name collides with the native HTMLElement.togglePopover() method from the HTML Popover API and inline onclick handlers will throw a NotSupportedError.
Input
Date and time fields — type="date", time, datetime-local, month — take the same class. They drop the native appearance (since 1.17.0): iOS drew them wider than their column, an empty one narrower than a filled one, with the value centred. Now they sit in their column like every other field, the value at the start; the native picker still opens.
Textarea
Select
Search
Toggle Switch
Checkbox
Radio Button
Range Slider
Progress Bar
| Class | Description |
|---|---|
.glass-progress | Base container |
--sm / --lg | Track height: 4px / 12px |
--success / --error | Color variants |
Accordion
Skeleton
Loading placeholder: shimmer lines standing in for text that has not arrived. Set each line's width; the shimmer follows the theme and holds still under prefers-reduced-motion. Mark the region aria-busy="true" so assistive tech knows it is loading.
| Class | Description |
|---|---|
.glass-skeleton | Stack of lines, 10px apart |
.glass-skeleton__line | One shimmer line (12px); width via inline style |
.glass-skeleton__line--title | Taller line (18px) standing in for a heading |
Table
A plain <table> on glass: hairline rows, a muted header, numbers right-aligned in tabular figures. The .glass-table-wrap wrapper scrolls sideways where the columns do not fit. Put the class on the table itself — from a shadow root, ::slotted() cannot reach the cells, so this is document-level CSS by design.
| Date | Item | Amount |
|---|---|---|
| 2026-09-18 | Invoice #1042 | 1,240.00 |
| 2026-09-19 | Refund | −80.00 |
| 2026-09-20 | Pending | β |
| Class | Description |
|---|---|
.glass-table-wrap | Optional horizontal scroll container |
.glass-table | The table: hairline rows, hover highlight |
.glass-table__num | Right-aligned, tabular figures — on th and td |
.glass-table__muted | Secondary text colour on a cell |
Prose
Running text the app did not write by hand — rendered Markdown, help and info pages. One class on the container styles headings, paragraphs, lists, links, code, quotes, images and tables. Document-level by design: the content is light DOM, and ::slotted() stops at the first level.
Getting started
Include glasskit.css, set data-theme on <html>, done. Everything else is optional — see the design tokens.
- Dark mode is the default
- Light mode via
data-theme="light"
The glass effect needs a coloured background to show.
Segmented
A small, exclusive choice as one control — traffic light, morning / afternoon, mode. Buttons inside a role="group"; the chosen one carries aria-pressed="true", and the styling hangs on exactly that attribute, so state and semantics cannot drift apart. The tone modifiers put a dot in a state colour before the label. Try it: click or Tab to a button and press Space. More options than fit? Without a modifier the row stays one line and runs past the edge; --scroll lets it scroll sideways, --wrap breaks it into lines. Both combine with --full.
| Class | Description |
|---|---|
.glass-segmented | The group: inset glass track, buttons inside |
--full | Buttons share the width |
--scroll | One row that scrolls sideways when the options do not fit, scrollbar hidden (since 1.17.0) |
--wrap | Breaks the row into lines when the options do not fit (since 1.17.0) |
__item | One option; aria-pressed="true" marks the chosen one, disabled dims it |
__item--success / --warning / --error | Tone: sets --gl-segmented-tone for the dot |
__dot | The dot before the label, in the tone colour |
Steps
Progress through a short flow: numbered circles joined by hairlines, done ones on the success surface (with an SVG check), the current one in the primary colour and marked aria-current="step".
- Day
- Slot
- 3Dog
- 4Confirm
The list is a size container: narrower than 360 px only the current step keeps its label, the others show their number; before that, labels shorten with an ellipsis. Keyed to the block's own width, not the viewport — here in a 300 px frame:
- Day
- 2Choose a slot
- 3Dog
- 4Confirm
| Class | Description |
|---|---|
.glass-steps | The list; a size container, so give it a width inside a flex row |
__item, __item--done, __item--current | One step and its states |
__num | The circle: number, or an SVG check when done |
__label | The label; hidden below 360 px except on the current step |
__line | Hairline connector between steps |
Sheet
The bottom sheet is the mobile sibling of the modal: an overlay that fades and a panel that rises from the bottom edge, only the top corners rounded, a grip, safe-area padding. Its own block, not a modal modifier, because layout, entry motion and gesture differ. --inline embeds the panel in the flow without an overlay; the overlay form needs a little JavaScript, shown below and mirrored by <glk-sheet> in GlassKit Elements.
Rebook to …
| Class | Description |
|---|---|
.glass-sheet-overlay | Fixed overlay: scrim, blur, panel aligned to the bottom; starts at opacity 0 |
.is-active | Overlay visible, panel risen — toggled by script |
.glass-sheet | The panel: milky glass, top corners rounded, bottom safe-area padding |
--inline | In the flow, no overlay, all corners rounded |
__grip, __title, __body, __actions | Grip bar, heading, body, action column |
Empty state
For empty lists and result pages: a centred column with a round icon plate, a title, a short muted text and room for one action or several, side by side.
No bookings yet
Pick a day and a dog — the team is looking forward to it.
| Class | Description |
|---|---|
.glass-empty | Centred column |
__icon | 48 px round plate, 24 px stroked icon inside (::slotted(svg) twin for Elements) |
__title, __text | Heading and muted text (max 38 ch) |
__action | Room for one action or several: side by side with 8 px between them, wrapping and centred when narrow (since 1.17.0) |
Date strip
A row of day chips that scrolls sideways — a booking horizon, the days around today. Each chip is a <button> with the weekday, the day number and a dot that a tone modifier lights up; without a tone the dot is transparent, so chips with and without a mark keep the same height. The chosen chip carries aria-pressed="true", as in the segmented control; :disabled or aria-disabled="true" dims a day that cannot be chosen. The scrollbar is hidden. Give each button an aria-label with the full date — the visible “Tu 22” is no name. <glk-date-strip> in GlassKit Elements builds this from dates, with arrow keys and the chosen chip centred.
| Class | Description |
|---|---|
.glass-date-strip | Scrolling row; hidden scrollbar; 4 px padding so its own overflow does not clip the focus ring |
__day | Chip button, 44 px minimum; [aria-pressed="true"] chosen, :disabled / [aria-disabled="true"] dimmed |
__day--today | Underlines the number |
__wd, __num | Weekday in small caps, day number |
__mark | 6 px dot; transparent without a tone |
__mark--primary, --success, --warning, --error | Tone of the dot via --gl-date-strip-tone; on the chosen chip every tone becomes the ink on primary (--gl-date-strip-ink) |
Calendar
One month: a title between two round nav buttons, a weekday row and 42 square day buttons with up to three dots beneath the number. The chosen day carries aria-pressed="true", --today draws a warm border, --other dims a day of the neighbouring month, :disabled or aria-disabled="true" dims a day outside the allowed range — the second keeps it focusable for arrow keys. It is a role="group" of buttons named with their full date, not a role="grid". <glk-calendar> in GlassKit Elements builds it, with keyboard navigation and Intl names.
| Class | Description |
|---|---|
.glass-calendar | Block; __head with __title (ellipsis when tight) and two __nav buttons, 32 px round, with an SVG chevron |
__grid | Seven columns, 4 px gap |
__wd | Weekday header cell, muted small caps |
__day | Square day button; [aria-pressed="true"] chosen, --today warm border, --other dimmed neighbour month, :disabled / [aria-disabled="true"] dimmed and unpickable |
__marks, __mark | 5 px dots beneath the number, up to three; __mark--primary / --success / --warning / --error via --gl-calendar-tone, the ink on the chosen day via --gl-calendar-ink |
Image picker
Choosing one image with a preview: a 72 px plate — the picture with object-fit: cover, or a placeholder icon — and a column with the label, a hint and the actions, which are ordinary .glass-btn buttons; the block brings no button look of its own. --round makes the plate a circle for avatars; a long label wraps and never squeezes the plate. Any image, not only photos. <glk-image-picker> in GlassKit Elements adds the file dialog, EXIF rotation and resizing.
| Class | Description |
|---|---|
.glass-image-picker | Row: plate left, column right, 14 px gap |
__preview | 72 px plate; img covers it, svg is the 28 px placeholder in the muted icon colour |
__preview--round | Circle, for avatars |
__meta | Column that yields (min-width: 0) |
__label, __hint | Label in the look of .glass-label, wraps anywhere; small muted hint |
__actions | Wrapping row of .glass-btn buttons |
Utilities
Stack (vertikal)
.gl-stack
.gl-stack--xs (8px)
.gl-stack--sm (12px)
.gl-stack--md (16px)
.gl-stack--lg (20px)
.gl-stack--xl (24px)
Row (horizontal)
.gl-row
.gl-row--xs (8px)
.gl-row--sm (12px)
.gl-row--md (16px)
Margin Top
.gl-mt-sm (12px)
.gl-mt-md (16px)
.gl-mt-lg (20px)
.gl-mt-xl (24px)
Margin Bottom
.gl-mb-sm (12px)
.gl-mb-md (16px)
.gl-mb-lg (20px)
.gl-mb-xl (24px)
Text
.gl-text-center
.gl-text-muted
.gl-text-sm
Layout
.gl-px (padding horizontal)
.gl-w-full (width: 100%)
.gl-flex-1 (flex: 1)
π All Classes at a Glance
| Component | Classes | Modifier / States |
|---|---|---|
| Background | .glass-bg | --has-tab-bar |
| Navigation | .glass-nav | β |
| Pill-Button | .glass-pill | β |
| Theme-Toggle | .glass-theme-toggle | β |
| Title | .glass-title | β |
| Card | .glass-card | --glow |
| Button | .glass-btn | --primary, --secondary, --tertiary, --sm, --lg, --auto |
| Badge | .glass-badge | --primary, --success, --warning, --error, --interactive, --selected |
| Avatar | .glass-avatar | --sm, --lg |
| Divider | .glass-divider | β |
| Status | .glass-status | β |
| List | .glass-list | --flush, --bare, __item--interactive, __item--center, __item--danger, __item--accent, __leading--lg, __subtitle--wrap, __value, __section-header |
| Skeleton | .glass-skeleton | __line, __line--title |
| Table | .glass-table | -wrap, __num, __muted |
| Prose | .glass-prose | β |
| Segmented | .glass-segmented | --full, --scroll, --wrap, __item, __item--success/--warning/--error, __dot, [aria-pressed] |
| Steps | .glass-steps | __item, __item--done, __item--current, __num, __label, __line |
| Sheet | .glass-sheet-overlay + .glass-sheet | .is-active, --inline, __grip, __title, __body, __actions |
| Empty state | .glass-empty | __icon, __title, __text, __action |
| Date strip | .glass-date-strip | __day, __day--today, __wd, __num, __mark, __mark--primary/--success/--warning/--error, [aria-pressed], :disabled |
| Calendar | .glass-calendar | __head, __title, __nav, __grid, __wd, __day, __day--today, __day--other, __marks, __mark--primary/--success/--warning/--error, [aria-pressed], [aria-disabled] |
| Image picker | .glass-image-picker | __preview, __preview--round, __meta, __label, __hint, __actions |
| Popover | .glass-popover | --top, --start, --end, .is-open |
| Input | .glass-input | --error, :disabled |
| Textarea | .glass-textarea | β |
| Select | .glass-select | β |
| Search | .glass-search | β |
| Toggle | .glass-toggle | :checked |
| Checkbox | .glass-checkbox | :checked |
| Radio | .glass-radio | :checked |
| Range | .glass-range | β |
| Progress | .glass-progress | --sm, --lg, --success, --error |
| Modal | .glass-modal-overlay | .is-active |
| Toast | .glass-toast | --success, --error, --warning, .is-visible, __action, __close |
| Tab-Bar | .glass-tab-bar | .is-active auf Items |
| Tab-Bar Floating | .glass-tab-bar-dock + .glass-tab-bar--floating | __accessory, __accessory--accent/--success/--error, --accessory-left |
| Accordion | .glass-accordion | .is-open auf Items |
π€ AI / LLM Reference
GlassKit ships with SKILL.md β a structured, machine-readable component reference designed for AI assistants, LLMs, and code-generation tools.
| Feature | Description |
|---|---|
| Copy-paste HTML | All 31 components with exact nesting and BEM hierarchy |
| Design token tables | Colors, surfaces, blur, radii, spacing, shadows, typography |
| State class mapping | is-active, is-open, is-visible, :checked β where each belongs |
| Composition patterns | 6 full page layouts: Login, Dashboard, Form, Modal, Settings, Progress |
| Common mistakes | Frequent errors and their corrections |
Attach or reference SKILL.md when asking an AI to generate GlassKit HTML for production-ready output.
π§© The GlassKit Family
GlassKit is the CSS foundation of a three-layer family β three layers, one design language. For everything beyond single components, the sister projects are the intended path.
| Layer | Project | Use it for |
|---|---|---|
| CSS foundation | π§ GlassKit (you are here) | The design language: pure-CSS components, design tokens, dark & light. |
| App layer | GlassKit Elements | Drop-in web components (glk-button, glk-card, β¦) for application UIs. |
| Website layer | GlassKit Web | Building a complete website β the official Astro template with sections, i18n and SEO on the GlassKit foundation. |