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 }
});