---
title: "WebGL canvas rendered inside `.map()` (lint/webgl-in-map)"
description: "lint/webgl-in-map: Browsers cap live WebGL contexts at roughly 8–16 per page and silently evict the oldest one, so lists of shader avatars/cards go blank."
canonical: https://void-design.vercel.app/rules/lint/webgl-in-map
lastModified: 2026-09-16
---

# WebGL canvas rendered inside `.map()`

`lint/webgl-in-map` · severity **error** · category Lint · detected by `void lint` and `void audit`

## Why it matters

Browsers cap live WebGL contexts at roughly 8–16 per page and silently evict the oldest one, so lists of shader avatars/cards go blank. Each context also costs GPU memory and a render loop.

## How to fix it

Render one shared canvas (e.g. a single `<Canvas>` with many meshes, or `@react-three/drei` `View`), use a static frame/CSS gradient per item, or mount the WebGL piece only for the hovered/visible item.

## Example

```tsx
// one context, many views
<Canvas eventSource={ref}><View.Port /></Canvas>
{items.map((i) => <View key={i.id}><Orb seed={i.id} /></View>)}
```

## References

- https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/WebGL_best_practices
- https://drei.docs.pmnd.rs/portals/view

## More lint rules

`void lint` reports 67 rules in this category. Static source checks with no browser: Tailwind v4 silent failures, Next.js 16 API traps, React render-body bugs, accessibility markup, SEO files and motion hygiene.

- `script-strategy` Third-party script loads too early — [lint/script-strategy](https://void-design.vercel.app/rules/lint/script-strategy)
- `browser-global-in-render` Browser global (`window`, `document`, `navigator`, `localStorage`) at module scope or during render — [lint/browser-global-in-render](https://void-design.vercel.app/rules/lint/browser-global-in-render)
- `timer-in-render` `setTimeout` / `setInterval` called in a component body — [lint/timer-in-render](https://void-design.vercel.app/rules/lint/timer-in-render)
- `motionvalue-subscribe-in-render` MotionValue `.on("change")` subscription in a component body — [lint/motionvalue-subscribe-in-render](https://void-design.vercel.app/rules/lint/motionvalue-subscribe-in-render)
- `raf-without-cancel` `requestAnimationFrame` loop in an effect without `cancelAnimationFrame` — [lint/raf-without-cancel](https://void-design.vercel.app/rules/lint/raf-without-cancel)
- `listener-without-cleanup` Event listener or interval added in an effect without cleanup — [lint/listener-without-cleanup](https://void-design.vercel.app/rules/lint/listener-without-cleanup)
- `scroll-listener-nonpassive` `wheel` / `touchstart` / `touchmove` listener without `{ passive: true }` — [lint/scroll-listener-nonpassive](https://void-design.vercel.app/rules/lint/scroll-listener-nonpassive)
- `unload-listener` `unload` event listener — [lint/unload-listener](https://void-design.vercel.app/rules/lint/unload-listener)

Detected by `void lint` and `void audit`. Explain it in a terminal: `void rules lint/webgl-in-map`
