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.

Recommended

Discover More

Leadership Moves in Biotech: Ailux Appoints Maria Belvisi as Chief Scientific Officer10 Key Facts About Scaling Microsoft's Sovereign Private Cloud with Azure LocalHow to Evaluate the SECURE Data Act and Its Impact on Your PrivacyBluetooth Tracker in Postcard Exposes Naval Security Flaw: Dutch Ship Tracked for a Day10 Reasons I Built My Own RSS Server After Google Reader Died