UtilitiesFree

Adaptive Card

Image-and-text card that goes from a vertical stack to a row as soon as its container reaches 280 px, with no media query and no JavaScript.

CSS@containerLayout

Updated

Adaptive Card

Layout switches from column to row based on container width.

@container CSS
Hover or click the scene to interact

This effect is free — the Utilities category contains 43 effects total, including 3 free. Effect.Labs has 840 vanilla effects. Explore the category →

Usage examples

Featured this week

Lisbon, 5 nights

Flight and hotel in Alfama, breakfast included.

From €640May

Fjords by train, 7 nights

Bergen, Flåm and the mountain line in a panoramic car.

From €1,190June

① Valtrécy travel agency — the same trip card in the featured list and in “Recently viewed”

WhenThe results page shows two featured trips in the main column and one recently viewed trip in a narrow right-hand column. No action needed: each card takes the shape that suits its slot.
WhyOne component to maintain for two places. The 168 px column keeps the picture on top; the main column puts it on the left so two trips fit without scrolling.
SettingsThree .fx-0745-root elements with their headings, text and labels replaced; different gradients set with style="background-image:…" on .adc-img. 168 px side column in the scene grid.
Card block
TitleAutumn workshop
Imageforet.jpg
ColumnResizable

Drag the handle: below 280 px the card stacks its image above the text.

Preview — Brindolis page

Autumn workshop

Two days of basket weaving in the woods.

12 seatsOctober

② Brindolis site editor — previewing a card in a column you widen with a handle

WhenIn the preview you drag the handle (mouse, finger, or arrow keys once the handle is focused): under 280 px the card stacks picture and text, above it the card becomes a row. On load the column sweeps back and forth to show the switch.
WhyAuthors see straight away how their block behaves in a narrow or wide column, without resizing the window.
SettingsThe handle only changes the width of the root's parent (160 to 300 px), wired in <script data-scenes>. The card code is untouched.
  1. 1. The pass at dawn
  2. 2. Hut and soup
  3. 3. The way down
  4. 4. Gear list

Three days on the high trail

Hiking · 9 min read

We left the village before sunrise, headlamps on, with the col still hidden in the clouds.

By noon the path turned to scree and the first marmots whistled.

③ “Ferouze's notebook” blog — the “Read next” card folds when the contents drawer opens

WhenThe reader clicks “Contents”: a drawer opens on the left, the article shifts and the sidebar goes from 292 to 176 px. The next-article card then goes back to a stack.
WhyThe recommendation stays readable however much room the navigation leaves, with no special rule for the “drawer open” state.
SettingsThe button (a real <button> with aria-expanded) changes the scene grid columns; the card reacts on its own through its container query.

How it works

The .fx-0745-root element declares container: adc-card / inline-size: the browser measures that box, not the viewport. It takes width: 100% of its parent, on a #0a0a0f background with 14 px corners. Inside, .adc-card is a column flexbox: the .adc-img picture (80 px tall, violet-to-pink gradient) spans the full width, followed by the heading, the paragraph and the .adc-tag labels.

A single @container adc-card (min-width: 280px) rule does the job: the card switches to flex-direction: row, centred, and the picture becomes a 100 × 100 px square left of the text. Under 280 px it falls back to the stack. Because the query targets the card's own box, one card can sit as a row in a wide column while another is stacked in a sidebar, on the same page, at the same moment.

Going from one shape to the other uses an all 0.3s ease transition on the card and the picture (the picture eases to its square size). No script at all: the HTML and CSS provided are the whole thing.

Accessibility

  • Nothing to operate: the card is static content with no focusable element. If you make it clickable, wrap the heading in a real <a> rather than the whole box.
  • Stable reading order: only the display changes between stack and row; the HTML order (picture, heading, text, labels) is what a screen reader follows.
  • Decorative picture: .adc-img is a gradient div, skipped by assistive technology. If your visual carries meaning, put an <img alt="…"> inside it.
  • Reduced motion: under prefers-reduced-motion: reduce, the card and picture transitions are switched off; the layout changes in one step.
  • Zoom: zooming the page leaves the container fewer CSS pixels, so the card may go back to the stack, which keeps text readable.

Browser compatibility

Built on container queries (container-type, @container). Measured in Chromium 151, Firefox 153 and WebKit 26.5: same switch at 280 px, no overflow at 390 px, two independent copies on one page.

Chrome 105+✓ Full (measured)
Firefox 110+✓ Full (measured)
Safari 16+✓ Full (measured in WebKit)
Edge 105+✓ Full
Mobile iOS 16+✓ Full
Android Chrome 105+✓ Full

An older browser ignores the @container rule: the card stays stacked, readable at any width.

The code

Copy the two blocks (HTML and CSS) into your page. No JavaScript, no dependencies.

HTML
<div class="fx-0745-root">
  <div class="adc-card">
    <div class="adc-img"></div>
    <div class="adc-body">
      <h4>Adaptive Card</h4>
      <p>Layout switches from column to row based on container width.</p>
      <div class="adc-tags">
        <span class="adc-tag">@container</span>
        <span class="adc-tag">CSS</span>
      </div>
    </div>
  </div>
</div>
CSS
.fx-0745-root,
.fx-0745-root *,
.fx-0745-root *::before,
.fx-0745-root *::after {
  box-sizing: border-box
}

.fx-0745-root {
  container: adc-card / inline-size;
  display: block;
  width: 100%;
  background: #0a0a0f;
  border-radius: 14px;
  color: #fff;
  font-family: sans-serif;
}

.fx-0745-root .adc-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 16px;
  background: rgba(255, 255, 255, 0.04);
  border-radius: 14px;
  transition: all 0.3s ease;
}

.fx-0745-root .adc-img {
  width: 100%;
  height: 80px;
  border-radius: 10px;
  background: linear-gradient(135deg, #8b5cf6, #ec4899);
  background-size: cover;
  background-position: center;
  flex-shrink: 0;
  transition: all 0.3s ease;
}

.fx-0745-root .adc-body {
  min-width: 0;
}

.fx-0745-root .adc-body h4 {
  font-size: 0.85rem;
  font-weight: 700;
  color: #fff;
  margin: 0 0 4px;
}

.fx-0745-root .adc-body p {
  font-size: 0.72rem;
  color: rgba(255, 255, 255, 0.6);
  margin: 0 0 8px;
  line-height: 1.5;
}

.fx-0745-root .adc-tags {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.fx-0745-root .adc-tag {
  padding: 3px 8px;
  border-radius: 6px;
  background: rgba(139, 92, 246, 0.15);
  font-size: 0.6rem;
  font-weight: 600;
  color: #a78bfa;
}

@container adc-card (min-width: 280px) {
  .fx-0745-root .adc-card {
    flex-direction: row;
    align-items: center;
  }
  .fx-0745-root .adc-img {
    width: 100px;
    height: 100px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .fx-0745-root .adc-card,
  .fx-0745-root .adc-img {
    transition: none;
  }
}
JavaScript

Pure CSS — no JavaScript needed.

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
Switch point (CSS — @container adc-card (min-width: 280px)) 280 px Raise it to 340 px for long text, lower it to 240 px to get the row sooner. A second rule (e.g. min-width: 480px) can enlarge the picture in wide columns.
Visual (CSS or HTML — .adc-img) #8b5cf6 → #ec4899 gradient Set your photo with style="background-image:url(…)"; background-size: cover is already there. For a meaningful picture, put an <img> inside the div.
Picture size in the row (CSS — width/height in the @container rule) 100 × 100 px 120 × 120 px for a bolder thumbnail, 72 × 72 px for a dense list.
Picture height when stacked (CSS — .adc-img { height }) 80 px Use 140 px for a more photographic card in narrow columns.
Background and corners (CSS — .fx-0745-root and .adc-card) #0a0a0f, card rgba(255,255,255,.04), 14 px radius For a light theme: white root background, dark text on h4 and p.
Labels (HTML — .adc-tag) 2 labels Add or remove <span class="adc-tag"> elements; the row wraps by itself.
Transition length (CSS — transition: all 0.3s) 0.3 s none for an instant switch; the reduced-motion rule already does that for people who ask.

FAQ

My card is squashed or tiny inside a flex row: why?

An inline-size container does not take its width from its content. The root has width: 100%, which is enough in a block or a 1fr grid track; in a flex row, give it flex: 1 or an explicit width.

How is this different from a media query?

A media query looks at the window: every card would change at once. Here each card looks at the room it really has, so a sidebar card stays stacked while the one in the main content is a row.

Can I put several cards side by side?

Yes: each .fx-0745-root is its own container. In grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)), each card picks its shape from the width of its cell.