Demos

Each example is a live <pattern-grid> element styled with author CSS. View source on this page to see exactly how each one is built.

1. Hello rainbow

A 64-cell grid with HSL hues driven by sibling-index() and sibling-count().

<pattern-grid cells="8x8"></pattern-grid>

<style>
  pattern-grid {
    display: grid;
    grid-template-columns: repeat(var(--pg-cols), 1fr);
  }
  pattern-grid > i {
    aspect-ratio: 1;
    background: hsl(
      calc(sibling-index() / sibling-count() * 360)
      70% 50%
    );
  }
</style>

2. Concentric rotation

32 cells stacked in the same grid cell, each smaller and more rotated than the last. No JS animation โ€” pure CSS.

<pattern-grid cells="32"></pattern-grid>

<style>
  pattern-grid {
    display: grid;
    place-items: center;
    aspect-ratio: 1;
  }
  pattern-grid > i {
    grid-area: 1 / 1;
    width: calc(100% * sibling-index() / sibling-count());
    aspect-ratio: 1;
    border: 1px solid hsl(calc(sibling-index() * 11) 70% 60%);
    border-radius: 30%;
    transform: rotate(calc(sibling-index() * 5deg));
  }
</style>

3. 2D coordinates from the sibling shim

With shim="sibling", the component sets typed integer custom properties (--i per cell, --n on the host). That lets mod() and floor() recover (x, y) coordinates reliably. Color shifts on a diagonal.

<pattern-grid cells="16x16" shim="sibling"></pattern-grid>

<style>
  /* Register so CSS math types numerically */
  @property --idx { syntax: '<integer>'; inherits: false; initial-value: 0; }
  @property --x   { syntax: '<integer>'; inherits: false; initial-value: 0; }
  @property --y   { syntax: '<integer>'; inherits: false; initial-value: 0; }

  pattern-grid > i {
    --idx: calc(var(--i) - 1);
    --x: mod(var(--idx), var(--pg-cols));
    --y: calc((var(--idx) - var(--x)) / var(--pg-cols));
    background: hsl(
      calc((var(--x) + var(--y)) * 8) 70% 50%
    );
  }
</style>

4. Template cells

Provide a <template> child and each cell becomes a clone of its content. Buttons here, but it can be anything โ€” links, images, custom elements.

<pattern-grid cells="4x4">
  <template>
    <button class="tile">+</button>
  </template>
</pattern-grid>

5. Hand-authored cells (no JS required)

When the child count already matches cols ร— rows, JS leaves them alone. This block also renders correctly with JavaScript disabled.

<pattern-grid cols="3" rows="2">
  <a href="#one"></a>
  <a href="#two"></a>
  <a href="#three"></a>
  <a href="#four"></a>
  <a href="#five"></a>
  <a href="#six"></a>
</pattern-grid>

6. Vanilla Breeze tokens

Because cells live in the light DOM, any inherited custom properties cascade in. Here the design tokens come from a parent.

/* VB tokens cascade into light DOM cells */
pattern-grid > i {
  background: hsl(
    calc(sibling-index() / sibling-count() * 360)
    var(--vb-color-saturation)
    var(--vb-color-lightness)
  );
  border-radius: var(--vb-radius-sm);
}

7. Sibling shim โ€” works in Firefox today

Setting shim="sibling" writes --i on each cell and --n on the host, so author CSS works in browsers that don't yet ship sibling-index(). Author CSS can prefer the native function with a fallback.

With shim="sibling":

Without shim:

<pattern-grid cells="36" shim="sibling"></pattern-grid>

<style>
  pattern-grid > i {
    /* prefer shim, fall back to native */
    --idx: var(--i, sibling-index());
    background: hsl(calc(var(--idx) * 10) 70% 50%);
  }
</style>

8. Seeded randomness

Wrap a <pattern-grid> in <seed-context> and the component writes --rand-0...--rand-7 floats and matching --randi-0...--randi-7 integers on each cell, derived from a seeded mulberry32 PRNG. Same seed reproduces the same randoms across reloads.

<seed-context seed="hello">
  <pattern-grid cells="8x8"></pattern-grid>
</seed-context>

<style>
  pattern-grid > i {
    background: hsl(
      calc(var(--rand-0) * 360deg) 70% 50%
    );
  }
</style>

9. API explorer

Drag the sliders to mutate cols and rows attributes live. The component listens to attribute changes and regenerates cells.

10. The render event

Every regeneration fires a pattern-grid:render event with the new { cols, rows, total } in its detail. Useful for tying side effects to grid changes.

document.querySelector('pattern-grid')
  .addEventListener('pattern-grid:render', (e) => {
    console.log('Regenerated:', e.detail);
    // e.detail === { cols: 8, rows: 8, total: 64 }
  });