Theme

A few properties, then the parts.

Accent, appearance, and the typeface first, then a knob per component. The material itself stays physical: frost, rim light, and refraction are options, not a stylesheet.

Properties

Set them on any ancestor. Every glass element inside inherits them.

theme.css
:root {
  --glass-accent: #0a84ff;          /* prominent buttons, sliders, tabs */
  --glass-appearance: light;        /* light, dark, or leave it on auto */
  --glass-font: "Outfit", system-ui;
}
  • --glass-accent tints prominent buttons and the filled portion of sliders and switches. Text on that fill is shifted so it stays readable.
  • --glass-appearance is read when an element is appearance="auto". After that, the page color-scheme is used. The operating system scheme is not consulted on its own.
  • --glass-font is the typeface inside every control. This site sets it to Outfit so the UI does not inherit the display serif.
  • --glass-foreground overrides the text color inside glass. It falls back to --gl-fg, which glass sets on the host for its appearance.
  • --glass-text-shadow overrides the text shadow. It falls back to --gl-text-shadow.
  • --glass-focus is the focus ring color.

For content you color yourself inside glass, use color: var(--gl-fg). Every glass element also sets data-appearance="light" or data-appearance="dark". After changing --glass-appearance or color-scheme on an element other than <html> or <body>, call updateAppearance().

Component knobs

Each control reads its own custom properties and has a built-in default for every one. Set them on the element or on any ancestor.

  • Button: --glass-button-height, --glass-button-padding, --glass-button-font-size, --glass-on-accent, --glass-accent-text
  • Switch: --glass-switch-on, --glass-switch-off, --glass-thumb
  • Slider: --glass-slider-track, --glass-slider-off, --glass-thumb
  • Tab bar: --glass-tab-bar-height, --glass-tab-selection, --glass-tab-selected
  • Segmented control: --glass-segmented-height, --glass-segmented-track, --glass-segmented-backdrop, --glass-segmented-selected, --glass-segmented-thumb
  • Tab bar and segmented items: --glass-selector-padding, --glass-item-direction, --glass-item-gap
  • Menu: --glass-menu-highlight, --glass-destructive
  • Search: --glass-search-height
  • Sheet: --glass-scrim, --glass-sheet-inset, --glass-sheet-max-width, --glass-sheet-padding
  • Group and toolbar: --glass-group-padding, --glass-toolbar-gap

Try it

Continue Later
Light Dark
:root {
  --glass-accent: #0a84ff;
}

Parts

Reach into a control with ::part(). The shared stack is ::part(glass). Layers inside that stack stay in the engine.

ElementParts
glass-surfaceglass
glass-buttonlabel, glass
glass-switchtrack, fill, thumb, glass
glass-slidertrack, fill, ticks, thumb, glass
glass-tab-barindicator, lens, glass
glass-segmentedtrack, indicator, lens, glass
glass-tabcontent
glass-segmentcontent
glass-menupanel, content, glass
glass-menu-itemlabel
glass-groupglass
glass-searchicon, input, clear, glass
glass-sheetscrim, sheet, grabber, body, glass
glass-scenebackdrop
parts.css
glass-scene::part(backdrop) { object-position: 50% 20%; }
glass-search::part(input) { font-size: 17px; }

Materials

regular is milky and legible over anything. clear is for photographs and video, where you want the picture to stay present. Both exist in light and dark. Per-surface options such as refraction, blur, tint, and specular are easier to feel than to describe: that is what the playground is for.

Sheet tint

glass-sheet applies material, blur, and tint to the card. Set them as attributes, or as the same props in React, Vue, and Svelte. Changing them updates an open sheet.

sheet.html
<glass-sheet tint="#c4622d" blur="14" material="clear" detents="medium large" aria-label="Details">
  Copper glass, a little more frost.
</glass-sheet>
sheet.css
glass-sheet::part(glass) {
  border-radius: 28px;
}

The shared stack is glass-sheet::part(glass). tint, blur, and material already drive that part. Use the selector when you want an extra outline or radius on top.