x-obscured
v0.3.0
Published
A shimmer spoiler Web Component that obscures inline text with animated WebGL noise
Maintainers
Readme
<x-obscured>
A "shimmer spoiler" Web Component that obscures inline text with animated WebGL noise.
Works in React, Vue, Angular — you name it — even plain HTML!
- Supports multi-line and text wrapping
- Framework-agnostic, zero dependencies
- Click-to-reveal with programmatic API
- Customizable density, speed, and color
Installing
npm install x-obscuredOr use a CDN:
<script type="module" src="https://unpkg.com/x-obscured"></script>Usage
<script type="module">
import "x-obscured";
</script>
<p>
The winner was <x-obscured>definitely not who you'd expect</x-obscured>
— to everyone's surprise.
</p>Just wrap any inline text. The component preserves layout and renders animated noise over it.
React TLDR
import "x-obscured";
import type { ReactNode } from "react";
import { useEffect, useRef } from "react";
export default function Obscured({
children,
revealed = false,
}: {
children: ReactNode;
revealed?: boolean;
}) {
return (
<x-obscured {...(revealed ? { revealed: "revealed" } : {})}>
{children}
</x-obscured>
);
}Attributes
| Attribute | Type | Default | Description |
| ---------- | ------- | ------- | ----------------------------------------------------------------------------------- |
| revealed | boolean | — | Set to anything to reveal |
| density | number | 1 | Noise density multiplier |
| speed | number | 1 | Animation speed multiplier |
| color | string | — | Override color (inherits from parent) |
| expand | string | .25em | Expands the render area beyond the text bounds by the given amount in any CSS units |
<x-obscured density="2" speed="0.5" color="#e87c5b" expand="4px">secret</x-obscured>JavaScript API
const el = document.querySelector("x-obscured");
el.reveal(); // reveal the content
el.obscure(); // obscure the content
el.toggle(); // toggle between revealed/obscuredEvents
| Event | Fired when |
| -------- | -------------------- |
| reveal | Content becomes visible |
| obscure | Content becomes obscured |
How it works
The text stays in the DOM but is rendered transparent. A <canvas> is overlaid on top, and a GPU shader draws animated particles that obscure the content. The component figures out where each line of text is and only draws noise in those areas. Everything runs on the GPU, so it's fast and smooth.
Tuning
import { XObscured } from "x-obscured";
// Component's layout gets automatically updated on resize, mutation, and font load.
// However, as a failsafe it also forces layout update every 2 seconds.
// This number can be tweaked by setting this constant:
// Default: 2000
XObscured.MEASURE_INTERVAL_MS = 5000;Development
pnpm install
pnpm dev # Vite dev server with demo page
pnpm build # Library build (ESM + IIFE + types)
pnpm test # Vitest
pnpm typecheck # tsc --noEmit
pnpm lint # BiomeBrowser support
Requires WebGL 1.0. Works in all modern browsers (Chrome, Firefox, Safari, Edge).
License
MIT
