Isometric Grid
A slab of 4 × 4 indigo blocks in isometric view (turned 45°, tilted 60°): blocks within 60 px of the pointer rise more the closer they are (up to 25 px) and take a glow, so a bump of several blocks follows the mouse — or forms where you touch, or moves with the keyboard arrows. 4 KB of JavaScript, one instance per slab.
Updated
This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. 3D has 50 effects, including 8 free. Explore the category →
3 usage examples



How it works
The root .fx-0026-root (#0a0a0f background, at least 300 px tall) centers the slab .iso-grid[data-iso-grid]: 220 × 220 px, transform: rotateX(60deg) rotateZ(45deg), preserve-3d, crosshair cursor, tabindex="0". There is no perspective: parallel edges stay parallel, a true isometric view. The sixteen .iso-block elements are written in the HTML (42 × 42 px every 46 px, column and row in data-col and data-row); each carries a top .iso-block-top (#6366f1 → #818cf8 gradient) and two 20 px faces folded by rotateX(-90deg) and rotateY(90deg), the ones you see at this angle.
The script looks for every [data-iso-grid] on the page. It creates the blocks only if they are missing, then, on each pointermove over the slab, measures on screen the distance between the pointer and each block's center. Under 60 px, the block gets translateZ((60 − d) / 60 × 25 px) and the raised class (top #818cf8 → #a5b4fc, 20 px rgba(99, 102, 241, .5) glow); beyond, it goes back down. The 0.3 s CSS transitions smooth it all. When the mouse leaves the slab, everything drops. Measured in Chromium 151 and Firefox 153: pointer on a center block, 9 blocks raised, the highest at 25 px; 6.8% of pixels change. Distances are taken on screen, after rotation: the bump is round to the eye, not on the slab.
With a finger, pointerdown forms the bump where you touch, and it stays until the next touch (page scrolling is not blocked). With the keyboard, Tab focuses the slab (#a5b4fc outline), the bump forms on a center block, and the arrows move it one block along the columns and rows; it drops when the slab loses focus. Measured: two presses on → bring the bump against the edge. Each move reads the position of 17 elements: 0.3 ms in Chromium and 1.7 ms in Firefox per move, measured over 300 moves. Two slabs on one page: each has its own instance; measured, only the hovered slab reacts.
Accessibility
- Reduced motion: under
prefers-reduced-motion: reduce, the script sets no lift and a CSS block scoped to.fx-0026-rootcancels the one from theraisedclass: the blocks don't move, those near the pointer light up and take their glow. Measured in Chromium and Firefox: 9 blocks lit, no transform, 5.7% of pixels change (6.8% without the preference). - Keyboard: the slab takes keyboard focus (Tab), the arrows move the bump, and it carries
aria-label="Isometric grid", to translate into your page's language. It remains decoration: a screen reader only announces that name. If the slab carries information (a covered zone, a level), write it next to it as text. - Contrast: the lit top differs from the normal top by only 1.5:1; it is the relief, then the glow, that show the bump. On a light background, darken the faces to keep the volume.
- Touch: measured with Chromium touch emulation and in Firefox, a touch on the slab raises the blocks around the finger; the script does not stop the page from scrolling when you swipe.
Browser compatibility
JavaScript (Pointer Events, getBoundingClientRect, classList, matchMedia, 4 KB) + 3D CSS on three levels (preserve-3d on the slab, the blocks and their faces, no perspective), no dependencies. Measured in Chromium 151 and Firefox 153: same bump (9 blocks, 25 px at most), same keyboard, same reduced motion, two independent slabs, 0 errors. Playwright's WebKit flattens all preserve-3d 3D, even a reference cube: Safari rendering not checked on a real Safari.
Without JavaScript, the slab still shows its sixteen blocks flat: nothing rises. If the browser flattens the 3D, the faces fold into the plane and the lift no longer shows; the lighting and glow of nearby blocks remain.
The code
HTML structure to paste into your page (the CSS + JS come with your purchase):
<div class="fx-0026-root">
<div class="iso-grid" data-iso-grid tabindex="0" aria-label="Isometric grid"> <!-- rotateX(60deg) rotateZ(45deg) -->
<div class="iso-block" data-col="0" data-row="0" style="left: 0px; top: 0px; width: 42px; height: 42px;">
<div class="iso-block-top"></div>
<div class="iso-block-right"></div>
<div class="iso-block-front"></div>
</div>
… (16 blocks)
</div>
</div>
<!-- + the script: one instance per [data-iso-grid] (pointer, touch, arrows) -->
One-time payment, no subscription — the code is yours forever
Customize
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
Influence radius (JS — 60 in raiseAround, three times) |
60 px | Change all three together. 90 px gives a wider, softer bump; 40 px only raises the block under the pointer and its direct neighbors. |
Maximum height (JS — * 25) |
25 px | 40 px makes a strong bump; beyond half a block's size, raised blocks hide the ones behind them. |
Block size and count (JS — cols, rows, size, gap; HTML — block styles; CSS — .iso-grid size) |
4 × 4; 42 px; 4 px; 220 px slab | The HTML blocks keep their written sizes: change them too, or delete them and let the script create them from cols, rows, size and gap. |
Colors (CSS — .iso-block-top, .iso-block-right, .iso-block-front, .iso-block.raised) |
#6366f1 → #818cf8; faces #4f46e5 and #4338ca; raised #818cf8 → #a5b4fc, glow rgba(99, 102, 241, .5) | The faces must stay darker than the top to keep the volume. The glow is a box-shadow: on a light background, a brown or gray at 30% is enough. |
Smoothness (CSS — .iso-block transition) |
transform .3s, box-shadow .3s | 0.15 s gives a bump that sticks to the pointer; 0.6 s, a wave trailing behind. |
Angle (CSS — rotateX(60deg) rotateZ(45deg) of .iso-grid) |
60° and 45° | With rotateZ(-45deg), other faces show: .iso-block-front would have to move to the left edge. |
FAQ
cols, rows, size and gap.