Create a Staggered Zigzag Grid Layout with CSS Transform

By

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:

Related Articles

Recommended

Discover More

6 Key Takeaways from Remedy's Latest Business Update on Control, FBC Firebreak, and ResonantThe Cracks in AI's Foundation: Insights from Five Industry Architects8 Crucial Facts About Venmo's Long-Awaited Privacy FixHow Here&#8217;s how the new Microsoft and OpenAI deal breaks downInside Build Application Firewalls: A New Defense Against Software Supply Chain Attacks