wabi.js

侘寂 – because imperfection is beautiful

wabi.js adds small, organic imperfection to your HTML elements using CSS clip-path polygons.
Adjust the settings below to see the effect in action.

Settings

wabi('.demo', { corners: { x: 5, y: 4 } });

Cards

Imperfect Design

The eye gets tired on perfection.

No rounded corners

Enough with the 2015 aesthetic already!

Clip-Path Performance

Uses CSS clip-path polygon for GPU-accelerated effects.

Buttons

Images

Circles Eco Mampf

Colored Boxes

1
2
3
4
5

How to Use

0. Get wabi.js

Go to the wabi.js GitHub repository and download the latest release.

1. Add the script to your page

Download wabi.min.js from the dist folder and include it in your HTML:

<script src="wabi.min.js"></script>

2. Call wabi() on your elements

Add this script before the closing </body> tag. The effect is applied when the page loads:

<script> window.addEventListener('load', function() {
wabi('.my-cards', { corners: { x: 5, y: 4 } });
//You can apply different settings to different elements by calling wabi() multiple times:
wabi('.buttons', { corners: { x: 2, y: 2 }, animate: true });
</script>

3. That's it!

The library works by applying a CSS clip-path polygon to your elements. No dependencies, no build step required.

Settings reference

  • corners.x / corners.y — Maximum random displacement of corners in each direction (as % of element size).
  • edges.points — Number of additional points to add along each edge between corners.
  • edges.edgeWobble — How far edge points can deviate perpendicular to the edge line.
  • edges.distribution — How edge points are spaced: 'random', 'even', or 'weighted-center'.
  • seed — Fixed seed for reproducible randomness; use null for different results each time.
  • cutCorners — Number of corners (0-4) to randomly cut off, creating angled shapes.
  • cornerChamfer — How far cut corners move inward (0 = no change, 1 = full cut).

Using with ES modules

If you're using a bundler or ES modules:

import wabi from './wabi.esm.js';

wabi('#myElement', { corners: { x: 3, y: 3 } });

Restoring elements

The function returns an object with a restore() method:

<script> window.addEventListener('load', function() {
var result = wabi('.cards', { corners: { x: 5, y: 5 } });

// Later, remove the effect:
result.restore();
}); </script>

Animating elements

Continuously randomize the shape at a given interval:

<script> window.addEventListener('load', function() {
var result = wabi('.cards', { corners: { x: 5, y: 5 } });

// Start animation (default: 100ms interval)
result.animate();
// Or with custom interval
result.animate({ interval: 200 });
// Stop animation
result.stop();
// Check if animating
result.isAnimating; // true or false
}); </script>

You can also auto-start animation via options: wabi('.cards', { animate: true }) or { animate: { interval: 200 } }