Create a Staggered Zigzag Grid Layout with CSS Transform

By ✦ min read

Introduction

Ever wanted a grid where items flow diagonally, like falling dominos, instead of sitting in rigid rows? That's a zigzag layout. It adds dynamic rhythm to your design. With a simple CSS Grid plus a tiny transform trick, you can achieve this effect without messing up keyboard navigation. This guide walks you through the process step by step.

Create a Staggered Zigzag Grid Layout with CSS Transform
Source: css-tricks.com

What You Need

Step-by-Step Instructions

  1. Create the HTML Skeleton

    Start with a div wrapper containing several item elements. The items represent your cards or content blocks. You can have any number of items – for this demo, we'll use five.

    <div class="wrapper">
      <div class="item">1</div>
      <div class="item">2</div>
      <div class="item">3</div>
      <div class="item">4</div>
      <div class="item">5</div>
    </div>
  2. Apply Global Box-Sizing

    Add a universal CSS rule to make sizing predictable. Without it, borders increase element height, breaking the staggered alignment we'll add later.

    *, *::before, *::after {
      box-sizing: border-box;
    }
  3. Set Up the Grid Container

    Define the wrapper as a grid with two equal columns, a 16-pixel gap, and a maximum width for centered layout.

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

    Give each item a fixed height and a visible border. The height sets the baseline for the vertical offset later.

    .item {
      height: 100px;
      border: 2px solid #333;
      /* Optional: add background, padding, text styling */
    }
  5. Offset Even Items Vertically

    This is the key trick. Use :nth-child(even of .item) to select every second item by its class, then shift it down by half its height. The translateY(50%) moves the item 50% of its own height, aligning its top edge to the middle of the previous item.

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

    Why this selector? You might think of nth-of-type(even), but that matches by HTML tag, not class. If you ever mix <div> with <article> inside the wrapper, nth-of-type will break. :nth-child(even of .item) precisely targets items with the .item class, keeping your layout robust.

  6. Check the Result

    Open your HTML file in a browser. The first column stays flush, while the second column items descend by half a step, creating a staggered zigzag pattern. The tab order flows naturally down the first column and then down the second – unlike a flexbox wrap approach that would jump columns.

  7. Fine-Tune Spacing (Optional)

    If the offset looks too large or small, adjust the translateY value. Use 40% for a tighter stagger or 60% for a wider one. You can also change the grid gap to control horizontal spacing.

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

    For responsive designs, consider using clamp() or media queries to modify item height and offset at different screen sizes.

Tips for Success

Now you have a clean, accessible zigzag grid. The transform trick gives you the visual flow without the tab-order headaches. Experiment with different offsets and column counts to create your own rhythmic layouts.

Tags:

Recommended

Discover More

The Hidden Advantages of Operating Two Wi-Fi Networks in Your HomeHow to Protect Your Open Source Repositories from AI-Driven Security Scans Without Shutting Them DownIntel Graphics Compiler IGC 2.34.4 Delivers Enhanced Performance for Compute and Shader WorkloadsHow to Install or Upgrade to Fedora Asahi Remix 44 on Apple Silicon Macs10 Astonishing Things You Need to Know About Assassin's Creed's Leap into Theatre