memphisify
v1.0.2
Published
Turn backgrounds into geometric patterns
Maintainers
Readme
memphisify
Scatter Memphis-style confetti shapes across any element. Zero dependencies, vanilla JS.
Memphisify fills any DOM element — buttons, headings, hero sections, card backgrounds — with a randomly scattered field of geometric shapes. Configure it declaratively with data-* attributes or drive it from code, and export the result as a crisp SVG or PNG.
<div
data-memphisify
data-colors="#FF3B6B,#FFC23B,#3BD4FF,#7B5CFF,#33D685"
data-background="#15131C"
data-density="9"
data-size="8"
data-overlap="true">
</div>Install
npm install memphisifypnpm add memphisify
yarn add memphisifyOr drop it in from a CDN:
<script src="https://unpkg.com/memphisify"></script>Quick start
Declarative (auto-init)
Tag any element with data-memphisify and Memphisify fills it on page load:
<section
data-memphisify
data-colors="#FF3B6B,#3BD4FF,#7B5CFF"
data-background="#15131C"
data-density="12"
data-size="14">
<h1>Celebrate</h1>
</section>
<script type="module">
import 'memphisify/auto';
</script>memphisify/auto scans the document for [data-memphisify] elements, fills each from its attributes, and re-scatters on resize.
Programmatic
import { memphisify } from 'memphisify';
const el = document.querySelector('#hero');
const instance = memphisify(el, {
colors: ['#FF3B6B', '#FFC23B', '#3BD4FF', '#7B5CFF', '#33D685'],
background: '#15131C',
density: 9,
size: 8,
overlap: true,
});
// Re-scatter (e.g. on click) for a fresh random layout
el.addEventListener('click', () => instance.scatter());
// Tweak any option live
instance.update({ density: 20, size: 12 });
// Tear down — removes generated shapes and listeners
instance.destroy();Options
| Option | Attribute | Type | Default | Description |
|--------------|--------------------|-----------------------|---------------|-------------|
| colors | data-colors | string[] / CSV | 5-color set | Hex colors picked at random per shape. As an attribute, pass a comma-separated list. |
| background | data-background | string (hex) | #15131C | Fill color painted behind the shapes. Use transparent to skip it. |
| density | data-density | number | 9 | Shapes per 10,000 px² of the element's area. The shape count scales with the box, so the texture stays consistent at any size. |
| size | data-size | number (px) | 8 | Base footprint of each shape, in pixels. |
| overlap | data-overlap | boolean | true | true lets shapes overlap freely. false uses rejection sampling so no two shapes sit closer than one footprint apart. |
Each shape is a randomly generated triangle (constrained so it never collapses into a thin sliver), placed at a random position with a random rotation and a subtle opacity variation for a hand-scattered feel.
Note on
overlap: false— when the box is too crowded to fit every shape without collisions, Memphisify places as many as it can and stops, rather than looping forever. Lower thedensityorsizeif you need a guaranteed count.
Export
Render a field to a standalone image without touching the DOM:
import { toSVG, toPNG } from 'memphisify';
// SVG string
const svg = toSVG({
width: 1000,
height: 1000,
colors: ['#FF3B6B', '#3BD4FF', '#7B5CFF'],
background: '#15131C',
density: 9,
size: 8,
transparent: false, // omit the background rect
});
// PNG Blob (browser only)
const blob = await toPNG({ width: 500, height: 500, transparent: true });| Option | Type | Default | Description |
|---------------|-----------|---------|-------------|
| width | number | — | Output width in px (required). |
| height | number | — | Output height in px (required). |
| transparent | boolean | false | Skip the background rect so the shapes sit on transparency. |
All the standard colors / background / density / size / overlap options apply here too.
Recipes
A confetti-filled button
<button data-memphisify data-size="6" data-density="14" data-background="#15131C">
<span>Ship it</span>
</button>Sparse, large shapes on a light canvas
memphisify(card, {
colors: ['#1B1B1F'],
background: '#F4F2EC',
density: 2,
size: 90,
overlap: false,
});Text clipped to a confetti fill — render to SVG, set it as a background-image, and clip it to the glyphs:
.headline {
background-image: var(--memphis-svg);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}Accessibility
Confetti is decorative — keep it from fighting your content:
- Maintain enough contrast between any text and the
background. WCAG asks for at least 4.5:1 for body text and 3:1 for large text and UI shapes. - Where shapes sit behind copy, render text in a contrast-safe color layered above the field, rather than relying on the shapes to stay out of the way.
- Never use color alone to convey meaning.
- Generated shapes are inert (
aria-hiddenby default) so screen readers skip them.
Browser support
Works in all modern browsers. Uses clip-path, CSS custom properties, and the Canvas API (for toPNG). No build step or polyfills required.
License
MIT © Gabriel Ardèvol
