---
title: "Children repeated for a marquee/loop without `aria-hidden` or `inert` on the copies (lint/duplicate-children-not-hidden)"
description: "lint/duplicate-children-not-hidden: `Array(repeat).fill(0).map(() => <div>{children}</div>)` (Magic UI marquee, Skiper TextRoll) makes screen readers…"
canonical: https://void-design.vercel.app/rules/lint/duplicate-children-not-hidden
lastModified: 2026-09-16
---

# Children repeated for a marquee/loop without `aria-hidden` or `inert` on the copies

`lint/duplicate-children-not-hidden` · severity **warn** · category Lint · detected by `void lint` and `void audit`

## Why it matters

`Array(repeat).fill(0).map(() => <div>{children}</div>)` (Magic UI marquee, Skiper TextRoll) makes screen readers announce the content N times and adds N× tab stops for every link inside. Crawlers also see duplicated text.

## How to fix it

Render the first copy normally and mark every duplicate `aria-hidden` and `inert` (both: aria-hidden alone leaves focusable links). Add a pause control and stop the animation under `prefers-reduced-motion`.

## Example

```tsx
{Array.from({ length: repeat }, (_, i) => (
  <div key={i} aria-hidden={i > 0 || undefined} inert={i > 0 || undefined} className="animate-marquee">
    {children}
  </div>
))}
```

## References

- https://www.w3.org/WAI/WCAG22/Understanding/pause-stop-hide.html

## 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.

- `jsonld-deprecated-type` JSON-LD type that no longer produces rich results — [lint/jsonld-deprecated-type](https://void-design.vercel.app/rules/lint/jsonld-deprecated-type)
- `route-js-budget` Route first-load JS over budget (from `.next` build output) — [lint/route-js-budget](https://void-design.vercel.app/rules/lint/route-js-budget)
- `animate-undefined` `animate-*` class with no matching `--animate-*` theme variable or `@keyframes` — [lint/animate-undefined](https://void-design.vercel.app/rules/lint/animate-undefined)
- `random-in-render` `Math.random()` / `Date.now()` / `new Date()` evaluated in a component render body — [lint/random-in-render](https://void-design.vercel.app/rules/lint/random-in-render)
- `conditional-hook` Hook called inside a JSX expression, `&&`, ternary or callback — [lint/conditional-hook](https://void-design.vercel.app/rules/lint/conditional-hook)
- `svg-global-id` Hardcoded `id` on an SVG `<filter>`, gradient, `<clipPath>` or `<mask>` inside a reusable component — [lint/svg-global-id](https://void-design.vercel.app/rules/lint/svg-global-id)
- `allocation-per-frame` `new Intl.NumberFormat` / `Intl.NumberFormat(` / `new Color(` inside an animation-frame callback — [lint/allocation-per-frame](https://void-design.vercel.app/rules/lint/allocation-per-frame)
- `setstate-per-pointer-move` React state set inside a `mousemove` / `pointermove` / `scroll` handler — [lint/setstate-per-pointer-move](https://void-design.vercel.app/rules/lint/setstate-per-pointer-move)

Detected by `void lint` and `void audit`. Explain it in a terminal: `void rules lint/duplicate-children-not-hidden`
