Xtcworld

Crafting Zigzag Patterns with CSS Grid and Transform

Learn to create a zigzag waterfall layout using CSS Grid and a transform trick, avoiding Flexbox issues like fixed height and broken tab order.

Xtcworld · 2026-05-06 17:09:56 · Web Development

Introduction

Most CSS grid layouts place items in neat, aligned rows – like soldiers on parade. But sometimes you want a layout that flows with more rhythm, where items cascade diagonally like water tumbling down a waterfall. This is the zigzag layout, and building it requires a clever trick that reveals something fascinating about how CSS transforms work.

Crafting Zigzag Patterns with CSS Grid and Transform
Source: css-tricks.com

Why Flexbox Falls Short

Your first instinct might be to reach for Flexbox. Setting up a container with flex-direction: column and flex-wrap: wrap lets items flow downward before wrapping into a second column. Flexbox works in both orientations, so this seems promising.

However, two practical problems make this approach awkward:

  • Fixed height required: You must tell the container a specific height (e.g., 500px) for wrapping to kick in. That’s brittle and hard to maintain.
  • Broken tab order: Items flow down the first column (1, 2, 3) before jumping to the second (4, 5, 6). This creates two separate buckets, not a continuous waterfall effect. Keyboard navigation also suffers.

The CSS Grid approach we’ll build next does involve a hardcoded value, but it sidesteps the Tab order problem entirely – a meaningful win.

The CSS Grid Solution

The Core Idea

The plan is simple:

  1. Create a two-column grid with items sitting side‑by‑side.
  2. Select every item in the second column (the even‑indexed ones).
  3. Shift them down by half their own height to create the staggered effect.

This shift is where the magic happens – and it’s powered by a single CSS transform.

Setting Up the Grid

Start with a wrapper and a handful of items:

<div class="wrapper">
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
</div>

Apply global box-sizing and the grid container:

*,
*::before,
*::after {
  box-sizing: border-box;
}

.wrapper {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
  max-width: 800px;
  margin: 0 auto;
}

.item {
  height: 100px;
  border: 2px solid;
}

The box-sizing: border-box is critical: without it, the items would be slightly taller than 100px once borders are added – and the half‑height shift would misalign.

Applying the Transform

Now comes the clever part. Use nth-child to target even items and translate them down:

.item:nth-child(even of .item) {
  transform: translateY(50%);
}

Selector note: You might be tempted to use .item:nth-of-type(even), which works here because all children are div elements. However, nth-of-type selects by tag name, not by class. If you ever mix different element types inside the wrapper, the selector will match in unexpected ways. The :nth-child(even of .item) syntax is more precise because it considers only elements that also have the .item class.

Fine‑Tuning the Layout

Once the basic zigzag is working, you can adapt it to your needs:

  • Responsive adjustments: Use media queries to change the number of columns or the translation amount on smaller screens.
  • Variable heights: If items have different heights, replace translateY(50%) with a fixed offset or use JavaScript to calculate dynamic shifts.
  • Add visual polish: Combine with animations, shadows, or hover effects to make the waterfall even more engaging.

Remember, the transform does not affect the document flow – items will overlap if you don’t reserve space. Using a grid gap or padding usually handles this, but test thoroughly.

Conclusion

The zigzag layout shows that CSS Grid and transforms can work together in unexpectedly powerful ways. By avoiding the pitfalls of Flexbox (fixed height, broken tab order) and using a simple translateY, you get a diagonal cascade that feels organic and interactive. Give it a try in your next project – your layouts will thank you.

Recommended