CSS variables

Every CSS variable is prefixed steam-block- by default. Set the prefix attribute on an instance to change it, e.g. prefix="hero-" turns --steam-block-background into --hero-background. Set CSS variables globally (steam-block { ... }) for a site-wide look, or scope them to a class/id for one-off instances.

A CSS variable that maps onto a native CSS shorthand (padding, border, border-image) accepts exactly the same value syntax as that property, e.g. --steam-block-padding: 2rem 1rem or --steam-block-media-border: 2px dashed red.

Info

Need a property or an effect that has no variable, like a hover state or a keyframe animation? Style the inside of the component directly with parts.

Theme

Two copy-pasteable starting points: a curated set of the CSS variables you’ll actually reach for first, and the complete set with every CSS variable’s real default value. Put either into your own stylesheet and tweak from there.

steam-block {
  /* General */
  --steam-block-min-width-breakpoint: 768px;   /* stacked below this, side-by-side/overlay above it */
  --steam-block-padding: 0px;
  --steam-block-background: transparent;
  --steam-block-border: 0px solid transparent;
  --steam-block-border-radius: 0px;
  --steam-block-box-shadow: none;

  /* Media */
  --steam-block-media-border-radius: 0px;
  --steam-block-media-blend-mode: normal;
  --steam-block-media-filter: none;

  /* Split template (type="split", the default) */
  --steam-block-gap: 1.5rem;
  --steam-block-media-width: 1fr;
  --steam-block-content-width: 1fr;

  /* Hero template (type="hero") */
  --steam-block-media-aspect-ratio: 16 / 9;

  /* shared between templates: hero defaults to center, split to left */
  --steam-block-content-text-align: left;
}

Full reference

“Active at” means viewport width relative to --steam-block-min-width-breakpoint, unless it says otherwise.

General

The component itself, both templates.

CSS variable Description Active at
--steam-block-min-width-breakpoint demo Viewport width the layout switches at. Default 768px. All widths
--steam-block-padding demo padding of the section. All widths
--steam-block-max-width demo max-width of the section, centered with margin-inline: auto. Ignored with media="fluid". All widths
--steam-block-background demo Background of the section. All widths
--steam-block-border demo border shorthand of the section. All widths
--steam-block-border-top demo border-top of the section, overrides --steam-block-border for that one side. All widths
--steam-block-border-right demo border-right of the section. All widths
--steam-block-border-bottom demo border-bottom of the section. All widths
--steam-block-border-left demo border-left of the section. All widths
--steam-block-border-radius demo border-radius of the section. hero clips its media to this radius (overflow: hidden) at every width. split doesn’t clip, so its media keeps square corners where it meets a rounded one: round it with --steam-block-media-border-radius too, or keep it off the corner with --steam-block-padding. All widths
--steam-block-box-shadow demo box-shadow of the section. All widths

Media

Control the element(s) placed in the media slot.

Media, before layer

Media, before layer (::before, painted behind the media). Clipped by --steam-block-media-clip-path/--steam-block-media-mask along with the media itself. Use --steam-block-background instead if you need color to show through a clip-path/mask cut. No border/box-shadow/margin/border-radius of its own, only the media box has those (below), and it always rounds to match the media’s own corner:

CSS variable Description Active at
--steam-block-media-before-opacity demo opacity of the layer. Default 1. All widths
--steam-block-media-before-background demo Background color/image of the layer. All widths
--steam-block-media-before-clip-path demo clip-path of the layer. All widths
--steam-block-media-before-mask demo mask of the layer. All widths

Media itself

CSS variable Description Active at
--steam-block-media-opacity demo opacity of the media itself. All widths
--steam-block-media-object-position demo object-position of the media. All widths
--steam-block-media-margin demo margin on the media box, lets it bleed past its own column/box. hero clips this at its own overflow: hidden; split doesn’t clip it. Desktop only (≥breakpoint)
--steam-block-media-margin-stacked The same margin on the media box, for the stacked layout below the breakpoint, where -media-margin is not read. A negative top margin lifts the media out of the block, see Floating in space. Clipped in hero like -media-margin. Stacked only (<breakpoint)
--steam-block-media-border demo border around the media. All widths
--steam-block-media-border-top demo border-top of the media. All widths
--steam-block-media-border-right demo border-right of the media. All widths
--steam-block-media-border-bottom demo border-bottom of the media. All widths
--steam-block-media-border-left demo border-left of the media. All widths
--steam-block-media-border-radius demo border-radius of the media. All widths
--steam-block-media-box-shadow demo box-shadow of the media. All widths
--steam-block-media-clip-path demo clip-path of the media. All widths
--steam-block-media-mask demo mask of the media. All widths
--steam-block-media-blend-mode demo mix-blend-mode of the media. All widths
--steam-block-media-filter demo filter on the media. All widths
--steam-block-media-transform demo transform on the media, e.g. scale(1.05). All widths
--steam-block-media-transition transition shorthand on the media (and, in split, the column wrapping it). Default none.
Pairs with steam-emerge or any class/attribute toggle that changes a -media-* variable’s value.
All widths

Media, after layer

Media, after layer (::after, painted on top of the media). Same property set as the before layer, plus border-image:

CSS variable Description Active at
--steam-block-media-after-opacity demo opacity of the layer. Default 1. All widths
--steam-block-media-after-background demo Background color/image of the layer. All widths
--steam-block-media-after-border-image demo border-image of the layer. Pair with --steam-block-media-border (same width, transparent) to reserve real space for it, otherwise it paints over the media’s own edge. All widths
--steam-block-media-after-clip-path demo clip-path of the layer. All widths
--steam-block-media-after-mask demo mask of the layer. All widths
--steam-block-media-after-blend-mode demo mix-blend-mode of the layer. All widths

The after layer is always pointer-events: none, so clicks still reach the media underneath (a video’s controls, an iframe’s own play button).

Content

Control the wrapping element placed in the content slot. Assumes the slot holds a single wrapper (<div slot="content">...</div>), except --steam-block-content-display, and --steam-block-content-grid-template-columns meant for the case where you skip the wrapper.

Content, before layer

Content, before layer (::before, painted on the content box itself, same box --steam-block-content-background paints on). No border/box-shadow/margin/border-radius of its own, only the content box has those (below), and it always rounds to match the content box’s own corner:

CSS variable Description Active at
--steam-block-content-before-opacity demo opacity of the layer. Default 1. All widths
--steam-block-content-before-background demo Background color/image of the layer. All widths
--steam-block-content-before-clip-path demo clip-path of the layer. All widths
--steam-block-content-before-mask demo mask of the layer. All widths
--steam-block-content-before-blend-mode demo mix-blend-mode of the layer. All widths

Content itself

CSS variable Description Active at
--steam-block-content-opacity demo opacity of the slotted content. All widths
--steam-block-content-display demo display of the content block. Default block. Set to grid or flex to arrange multiple slotted children with no wrapper <div> (see below). All widths
--steam-block-content-grid-template-columns demo grid-template-columns. Only has an effect once -content-display: grid is set. All widths
--steam-block-content-gap demo gap between children. Distinct from --steam-block-gap, which is split’s gap between the content and media columns. All widths
--steam-block-content-margin demo margin on the content block, all four sides. Desktop only (≥breakpoint)
--steam-block-content-margin-stacked The same margin on the content block, for the stacked layout below the breakpoint. A negative top margin pulls the content up over the media, see Magazine overlap. A separate variable, so a desktop offset like -50% never reaches a phone screen. Stacked only (<breakpoint)
--steam-block-content-padding demo padding inside the content block. All widths (default differs: 5vw below the breakpoint, 0px at/above it in split)
--steam-block-content-background demo Background of the content block. All widths
--steam-block-content-border demo border around the content block. All widths
--steam-block-content-border-top demo border-top of the content block. All widths
--steam-block-content-border-right demo border-right of the content block. All widths
--steam-block-content-border-bottom demo border-bottom of the content block. All widths
--steam-block-content-border-left demo border-left of the content block. All widths
--steam-block-content-border-radius demo border-radius of the content block. All widths
--steam-block-content-box-shadow demo box-shadow of the content block. All widths
--steam-block-content-clip-path demo clip-path of the content block. All widths
--steam-block-content-mask demo mask of the content block. All widths
--steam-block-content-blend-mode demo mix-blend-mode of the slotted content. All widths
--steam-block-content-filter demo filter on the slotted content. All widths
--steam-block-content-transform demo transform on the content block. All widths
--steam-block-content-transition transition shorthand on the content block (and, in split, the column wrapping it). Default none.
Pairs with steam-emerge or any class/attribute toggle that changes a -content-* CSS variable’s value.
All widths

Content, after layer

Content, after layer (::after, painted on top of the content box). Same property set as the before layer:

CSS variable Description Active at
--steam-block-content-after-opacity demo opacity of the layer. Default 1. All widths
--steam-block-content-after-background demo Background color/image of the layer. All widths
--steam-block-content-after-clip-path demo clip-path of the layer. All widths
--steam-block-content-after-mask demo mask of the layer. All widths
--steam-block-content-after-blend-mode demo mix-blend-mode of the layer. All widths

The after layer is always pointer-events: none, so clicks and text selection still reach real content underneath (buttons, links).

No media, text only

split still renders an empty media column even with nothing slotted into it. Zero --steam-block-media-width and --steam-block-gap (a Grid gap is reserved regardless of column width) so the content column takes the full row:

.text-only-block {
  --steam-block-content-display: grid;
  --steam-block-content-grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
  --steam-block-content-gap: 2rem;
  --steam-block-gap: 0;
  --steam-block-media-width: 0;
}

Multiple columns in hero

.content shrinks to fit by default, so a grid of un-wrapped slot="content" children collapses to one narrow column unless you force the overlay to fill its width first:

.hero-columns {
  --steam-block-media-after-background: linear-gradient(to top, rgba(0,0,0,.85) 30%, transparent 75%);
  --steam-block-content-display: grid;
  --steam-block-content-grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  --steam-block-content-gap: 1.5rem;
  --steam-block-hero-align-items: stretch;
  --steam-block-hero-content-max-width: 100%;
}
<steam-block class="hero-columns" type="hero" overlay="true">
  <img slot="media" src="photo.jpg" alt="">
  <div slot="content"><strong>Column one</strong></div>
  <div slot="content"><strong>Column two</strong></div>
  <div slot="content"><strong>Column three</strong></div>
  <div slot="content"><strong>Column four</strong></div>
</steam-block>

See Text columns on the examples page for both of these live.

Split-specific

For type="split", the default. The grid itself, then its media column, then its content column.

CSS variableDescriptionActive at
--steam-block-media-aspect-ratio demoaspect-ratio for the media. Shared with hero (see Hero-specific below), no fallback here. Holds only as long as the media column stays the taller of the two.All widths
--steam-block-gap demogap between the content and media columns.Desktop only (≥breakpoint)
--steam-block-media-align-items demoalign-items of the media within its column, only visible with data-size="auto". Shared with hero, defaults to flex-start here, center there.All widths
--steam-block-media-justify-content demojustify-content of the media within its column, only visible with data-size="auto". Shared with hero, both default to center.All widths
--steam-block-content-justify-content demojustify-content of the content column. Shared with hero, both default to center.All widths
--steam-block-media-width demoWidth of the media column.Desktop only (≥breakpoint); below it the column stacks full-width
--steam-block-media-min-width demoMinimum width of the media column. Default 0, no built-in floor.Desktop only (≥breakpoint)
--steam-block-content-width demoWidth of the content column.Desktop only (≥breakpoint); below it the column stacks full-width
--steam-block-content-min-width demoMinimum width of the content column. Default 0, no built-in floor.Desktop only (≥breakpoint)
--steam-block-content-text-align demotext-align of the content column. Shared with hero, split defaults to left, hero to center.All widths

--steam-block-content-transition/--steam-block-media-transition (documented under Content/Media above) also apply to .left/.right, the columns wrapping them, not just the inner box.

Hero-specific

For type="hero". The overlay itself, then its media background, then its content.

CSS variableDescriptionActive at
--steam-block-media-aspect-ratio demoaspect-ratio of the media background. Defaults to 16 / 9. Wherever the content overlays the media it is a minimum: the hero keeps the ratio while the content fits and grows taller when it doesn’t, so no text is ever clipped. Shared with split (see Split-specific above).All widths
--steam-block-hero-align-items demoalign-items of the content overlay. Hero-only, no split equivalent.Desktop only (≥breakpoint), or every width once overlay="true" forces the overlay early
--steam-block-media-align-items demoalign-items of the media within its area, only visible with data-size="auto". Shared with split, defaults to center here, flex-start there.All widths
--steam-block-media-justify-content demojustify-content of the media within its area, only visible with data-size="auto". Shared with split, both default to center.All widths
--steam-block-content-justify-content demojustify-content of the content overlay. Shared with split, both default to center.All widths
--steam-block-hero-media-max-width demoCaps the width of the background media.All widths (media="fluid" only)
--steam-block-hero-content-width demowidth of the content overlay. Default auto, the overlay sizes to its own content.
Set a value such as 45% or 32rem for a fixed box that keeps its --steam-block-hero-align-items position.
Desktop only (≥breakpoint)
--steam-block-hero-content-max-width demomax-width of the content overlay. Default 99%.Desktop only (≥breakpoint)
--steam-block-content-text-align demotext-align of the content overlay. Shared with split, hero defaults to center, split to left.All widths

Internal

CSS variableDescriptionActive at
--steam-block-scrollbar-widthSet automatically on :host from the browser’s scrollbar width, used internally by the media="fluid" breakout math. Read-only.All widths

See every variable rendered live in the Visual reference, and combined into complete examples in Usage.