Usage

steam-block exposes two named slots content and media that accept any markup you like: headings, paragraphs, buttons, <img>, <video>, <iframe>, inline SVG, or markup styled by another CSS framework. The component only controls layout, it never touches what you put inside of it.

Basic usage

<steam-block type="split" media="fluid" order="flip">
  <div slot="content">
    <h1>Welcome to Steam Block</h1>
    <p>Flexible layouts made simple.</p>
    <a role="button" href="#">Get started</a>
  </div>
  <img slot="media" src="your-image.jpg" alt="">
</steam-block>

Welcome to Steam Block

Flexible layouts made simple.

Get started

With the steam-blockabove, everything is a plain attribute. No configuration object or JS API required:

  1. type="split" picks the side-by-side template
  2. media="fluid" lets the media bleed past its container to the viewport edge
  3. order="flip" swaps which side the media sits on. By default, content left / media right

See Attributes for the full list.

Advanced usage

Once the basics click, the real flexibility comes from combining attributes with the CSS variables. Every visual detail (borders, blend modes, masks, aspect ratios, column widths) is a variable you can layer on top of either template.

A duotone hero with a touch of over-exposure from a single photo

<style>
  .duotone-hero {
    --steam-block-media-filter: grayscale(1);
    --steam-block-media-after-opacity: .5;
    --steam-block-media-after-background: linear-gradient(315deg, #2b6d0f 0.000%, #8e7f49 14.286%, #d5847f 28.571%, #5a7ea8 42.857%, #3d6bbd 57.143%, #c14dbc 71.429%, #b223a4 85.714%, #33007a 100.000%);
    --steam-block-media-after-blend-mode: hard-light;
    --steam-block-content-before-background: black;
    --steam-block-content-before-blend-mode: saturation;
    --steam-block-media-aspect-ratio: 21 / 9;
  }
</style>
<steam-block class="duotone-hero" type="hero" media="fluid">
  <img slot="media" src="your-photo.jpg" alt="">
  <div slot="content">
    <h2>Duotone hero</h2>
    <p>One photo, one accent color, zero image editing.</p>
  </div>
</steam-block>

Duotone hero

One photo, one accent color, zero image editing.

What’s doing the work, in order:

  • --steam-block-media-filter: grayscale(1) strips the photo’s own colors.
  • --steam-block-media-after-background (a gradient) interacts with --steam-block-media-after-blend-mode and --steam-block-media-after-opacity.
  • --steam-block-content-before-background and --steam-block-content-before-blend-mode add the grayscale behind the content, leaving the content itself untouched.
  • --steam-block-media-aspect-ratio widens the media band from the 16:9 default to a cinematic 21:9.

About media="fluid" in this example

This page has a sidebar, so the steam-block above is sitting inside a narrower column, not spanning the full page width. media="fluid" still bled it to the true edges of the viewport anyway. That’s not a coincidence, see Attributes for why it holds up in layouts where the usual calc(50% - 50vw) breakout trick doesn’t.

An off-balance split with content nudged over the media

<style>
  .ratio-split {
    --steam-block-padding: 1.5rem;
    --steam-block-background: linear-gradient(135deg, #5c507b 0.000%, #71728b 16.667%, #8f8d97 33.333%, #9c9b97 50.000%, #8c998a 66.667%, #6e877b 83.333%, #5b6873 100.000%);
    --steam-block-border: 4px solid white;
    --steam-block-border-radius: 2.1rem;
    --steam-block-box-shadow: 0 1rem 3rem rgba(0, 0, 0, .15);
    --steam-block-media-border-radius: 2rem;
    --steam-block-content-margin: 0 0 0 -100%;
    --steam-block-content-padding: 5vw;
    --steam-block-content-background: #f5f5f5;
    --steam-block-content-border: 4px solid white;
    --steam-block-content-border-radius: 2rem;
    --steam-block-content-box-shadow: 0 .25rem 1rem rgba(0, 0, 0, .15);
    --steam-block-media-width: 75%;
    --steam-block-content-width: 25%;
  }
  @media (max-width: 47.99rem) {
    /*Bring back card layout with rounded corners for mobile*/
    .ratio-split {
      --steam-block-media-border-radius: 2rem 2rem 0 0;
      --steam-block-content-border-radius: 0 0 2rem 2rem;
    }
  }
</style>
<steam-block class="ratio-split" order="flip">
  <img slot="media" src="your-photo.jpg" alt="">
  <div slot="content">
    <h2>Off-balance layout</h2>
    <p>Content narrower than the media, nudged over the edge with a negative margin, with a colored border standing in for a card.</p>
  </div>
</steam-block>

Off-balance layout

Content narrower than the media, nudged over the edge with negative margin, with a colored border standing in for a card.

Here the split template’s default 50/50 columns are overridden with --steam-block-content-width / --steam-block-media-width for a 25/75 split. order="flip" puts the media first, --steam-block-content-margin pulls the content column left over the media edge. A gradient background, some box-shadows, rounded corners and fat borders make this block a retro magazine card, all without adding a single wrapper <div>.

Whenever a border, a background or a box-shadow turns the whole component into a visible card like this one, pair it with --steam-block-padding (the whole box) or --steam-block-content-padding (the content slot only), since neither is added automatically on desktop. On mobile (being below --steam-block-min-width-breakpoint, see CSS Variables) --steam-block-content-padding has a default padding for a card-like look.