
css-doodle is a JavaScript Web Component for creating generative CSS art, geometric patterns, and animated backgrounds.
It uses CSS-like rules to style a grid of cells, with random values, math functions, SVG, and custom shapes to control the artwork.
The <css-doodle> element works in a plain HTML page. Patterns can be reproduced with a seed, updated through JavaScript, or exported as images.
Features
- Grid-based CSS patterns with configurable dimensions and cell spacing.
- Random colors, shapes, sizes, and positions with repeatable seeds.
- CSS animations and time-based effects.
- SVG artwork, filters, gradients, and polygon shapes.
- Procedural tiling, including Voronoi, lattice, and sliced patterns.
- Pointer-aware effects and WebGL shader rendering.
- JavaScript controls for updates, animation playback, and image export.
- Reusable doodle rules through CSS custom properties.
How To Use It
Installation
Load the css-doodle library from a CDN:
<script defer src="https://cdn.jsdelivr.net/npm/[email protected]/css-doodle.min.js"></script>
npm Installation
Or install the package with NPM and import it in your JavaScript entry file.
npm install css-doodle
import 'css-doodle';
Basic Usage
Place CSS-like rules inside <css-doodle>. The @grid directive sets the number of cells, the artwork dimensions, and the background of the component. Other declarations apply to the cells.
<css-doodle> @grid: 8 / 320px / #152238; background: @p(#f9c74f, #f9844a, #90be6d, #577590); border-radius: @p(15%, 50%); scale: @r(.35, .9); rotate: @r(-30deg, 30deg); margin: 3px; </css-doodle>
Reproduce a Pattern with a Seed
A fixed seed keeps random choices consistent across renders. Use the seed attribute when a background or illustration must keep the same appearance between page loads.
<css-doodle seed="brand-pattern-42"> @grid: 12 / 360px / #101820; background: @p(#f2aa4c, #f5f0e6); border-radius: @p(0, 50%); scale: @r(.4, 1); </css-doodle>
Refresh a Pattern with JavaScript
Call update() on the custom element to regenerate its styles. Remove a fixed seed when each update should produce a different arrangement. For built-in interaction, click:update updates the element when clicked, and auto:update="1.5s" changes it periodically.
<button id="shuffle-pattern" type="button">Shuffle pattern</button>
<script>
document.querySelector('#shuffle-pattern').addEventListener('click', () => {
document.querySelector('css-doodle').update();
});
</script>
Export Artwork as an Image
The export() method resolves to an object containing SVG markup and image dimensions. Set download: true to save a PNG, or detail: true to request the generated PNG blob and its source.
const doodle = document.querySelector('css-doodle');
const image = await doodle.export({
scale: 2,
download: true,
name: 'geometric-pattern'
});
console.log(image.width, image.height);
Create SVG Artwork
@svg() accepts XML or a CSS-like SVG language. Place its result in background to use it as an image, or in @content for inline SVG markup.
<css-doodle>
@grid: 1 / 320px;
background: @svg(
viewBox: 0 0 100 100;
circle {
cx, cy: 50;
r: 38;
fill: #f9844a;
}
circle {
cx, cy: 50;
r: 22;
fill: #152238;
}
);
</css-doodle>
Use css-doodle in React
Import css-doodle once, then place the rules inside a JSX template literal. JSX otherwise interprets braces in the doodle syntax as JavaScript expressions.
import 'css-doodle';
export function ArtPattern() {
return (
<css-doodle>{`
@grid: 7 / 300px / #222;
border-radius: @pn(100% 0, 0 100%);
background: #fff;
`}</css-doodle>
);
}
Configuration and Reference
HTML Attributes for element
| Attribute | Purpose |
|---|---|
grid | Sets columns, rows, and optional depth (5, 5x7, or 1x1x8). |
seed | Sets the seed for deterministic random functions; accepts text or numeric strings. |
use | Passes doodle rules directly or loads rules through CSS custom properties. |
click:update | Regenerates the doodle when the element is clicked. |
auto:update | Regenerates the doodle on an interval, for example 1.5s. |
experimental | Increases the allowable grid dimensions. |
ignore-reduced-motion | Overrides the automatic pause applied for a reduced-motion preference. |
Doodle Properties
Properties beginning with @ are interpreted by css-doodle. Ordinary CSS properties continue to work on the individual cells.
| Property | Description |
|---|---|
@grid | Sets grid dimensions and optional size, fill, gap, transform, border, and layout modifiers. |
@size | Sets width and height or a size preset such as a4, poster, or postcard. |
@place | Positions a cell at a point outside its regular grid placement. |
@gap | Sets row and column gaps, optionally with a drawn rule. |
@content | Inserts text, generated SVG, nested doodles, or shader content into cells. |
@shape | Applies a preset or custom polygon shape to a cell. |
@seed | Sets a seed inside the doodle code, taking precedence over the HTML attribute. |
@use | Reuses rules from CSS custom properties. |
`@grid` Modifiers
The @grid directive accepts a dimensions expression followed by optional modifiers.
| Syntax | Effect |
|---|---|
5x7 | Five columns and seven rows; a single number produces a square grid. |
/ 60vmin | Sets the component’s width and height. |
/ #222 | Sets the background after the size modifier. |
_ 4px | Sets the gap between cells. |
+ 1.2 | Scales the grid container. |
* 15deg | Rotates the grid container. |
*h 45deg | Rotates the host’s colors with hue-rotate(). |
~ 20% 0 | Translates the container. |
^ 1.2 | Enlarges the container’s dimensions. |
∆ 200px | Sets perspective for the component. |
ß 2px solid #000 | Sets the host’s border. |
| blur(3px) | Applies a backdrop filter above the cells. |
row, col | Switches to horizontal or vertical flex layout. |
p3d | Enables preserve-3d for transforms. |
noclip | Lets cells extend beyond the component boundary. |
Cell Selectors
Use these selectors as blocks in the doodle language. They select a specific position, conditional group, or generated element.
| Selector | Description |
|---|---|
:doodle | Styles the <css-doodle> host element. |
:container | Styles the internal grid container. |
@nth() | Selects cells by index. |
@at() | Selects a column-and-row position. |
@row() / @y() | Selects rows. |
@col() / @x() | Selects columns. |
@depth() / @z() | Selects depth levels in nested grids. |
@even | Selects alternating checkerboard cells with odd coordinate sums. |
@odd | Selects alternating checkerboard cells with even coordinate sums. |
@random() | Selects cells using a probability or count. |
@match() | Selects cells for which a condition evaluates true. |
@cell() | Selects cells through combined index, condition, and random rules. |
| Nested and pseudo selectors | Supports :hover, ::before, ::after, descendants, and & in selector blocks. |
| CSS at-rules | Supports rules such as @keyframes, @media, and @font-face. |
Functions: Cell Coordinates and Geometry
Cell functions use one-based indices for rows, columns, and the overall cell number.
| Function | Description |
|---|---|
@i, @I | Current cell index and total number of cells. |
@id | Identifier of the current cell. |
@x, @X | Current column and number of columns. |
@y, @Y | Current row and number of rows. |
@z, @Z | Current depth and number of depth levels. |
@iI, @Ii | Forward and reverse normalized index ratios. |
@xX, @Xx | Forward and reverse normalized column ratios. |
@yY, @Yy | Forward and reverse normalized row ratios. |
@dx, @dy, @dr, @dc, @dm, @da, @db | Cell offsets, distances, and angle relative to the grid center or edge. |
Functions: Sequences
Sequence functions generate repeated values. Step functions work inside sequence expressions.
| Function | Description |
|---|---|
@m, @M, @rep | Repeats values, with different joining behavior for generated CSS or SVG. |
@n, @N, @nx, @ny | Step number, step count, and step coordinates. |
@nd | Offset from the midpoint of a sequence. |
@nN, @Nn | Forward and reverse normalized step ratios, with easing. |
Functions: Random Values and Picks
Random outputs follow the active seed. Some pick functions process a list in sequence and others shuffle it.
| Function | Description |
|---|---|
@r, @ri | Random range value; @ri produces an integer. |
@R | Spatially related values from noise; @R.t() varies noise along a shape outline. |
@p, @P | Random list selection; @P avoids repeating the preceding choice at that call. |
@pn, @pnr | Picks in forward or reverse order. |
@pd | Picks in a shuffled sequence. |
@PN, @PNR, @PD | Sequence-step versions of the ordered and shuffled picks. |
@lp, @lr | Reuses the previous picked or random value. |
Functions: Expressions and Values
Use these functions inside CSS declarations or other doodle functions.
| Function | Description |
|---|---|
$() and unit forms such as $px() | Evaluates arithmetic and comparison expressions. |
@code() | Converts UTF-16 code units into characters. |
@cycle() | Produces rotations of a list for pick functions. |
@google-font() | Loads a Google font by family name. |
@hex() | Returns a number in hexadecimal. |
@match() | Selects a value based on a condition. |
@<Math>() | Calls JavaScript Math functions or constants, including @sin(), @cos(), and @PI. |
@mirror(), @Mirror() | Creates forward-and-reverse value sequences. |
@once() | Evaluates a value once and shares it across the cells. |
@palette() | Generates a seeded palette along an OKLCH color curve. |
@raw() | Passes its text through unchanged. |
@reverse() | Reverses a list or SVG path. |
@stripe() | Creates hard transitions between colors for gradients. |
@var() | Preserves a native CSS var() expression. |
Functions: SVG and Filters
The SVG family generates SVG markup, paths, and images from doodle expressions.
| Function | Description |
|---|---|
@svg() | Creates SVG from XML or CSS-like SVG rules. |
@svg-filter() | Creates SVG filters for filter or backdrop-filter, including noise displacement. |
@svg-pattern() | Creates a repeating SVG pattern tile. |
@svg-polygon() | Creates SVG artwork from polygon and shape commands. |
@linearGradient(), @radialGradient() | Builds SVG gradients for use inside SVG definitions. |
@arc() | Generates arc path data and joins consecutive arc segments. |
@flip(), @flipH(), @flipV() | Mirrors SVG path coordinates. |
@invert() | Exchanges SVG path axes. |
Functions: Shapes and Tiling
@shape() and @tile() are useful when artwork needs custom outlines, clipped geometry, or repeated pieces.
| Function | Description |
|---|---|
@shape() | Creates a polygon() from presets or coordinate and polar expressions. |
@plot(), @Plot() | Generates point positions for shapes; .scatter distributes them within an outline. |
@tile() | Generates shape tiles; supports different tiling modes and per-cell clipping. |
Tiling and Shape Controls
The following public controls belong to shape and tiling expressions. Their availability depends on the selected generator or tile mode.
| Control | Purpose |
|---|---|
aspect | Accounts for nonsquare dimensions in @tile and @plot.scatter. |
stretch | Changes Voronoi tile proportions. |
crack | Introduces cracks between Voronoi tiles. |
relax | Smooths the distribution of Voronoi tiles. |
round | Rounds tile corners. |
turn, slide | Pairs tiling edges for Escher-style patterns. |
size | Adjusts circle packing. |
jitter | Varies lattice tiles. |
density | Controls the density of sliced tiles. |
round:, edge: | Controls rounded outlines and edge details in shape commands. |
Custom Shape Commands
@shape() and @plot() accept shape expressions. Coordinates can use the angle t, the point index i, or custom variables defined inside the expression.
| Command | Purpose |
|---|---|
points | Number of generated vertices; from 3 to 3600, with a default of 3. |
r | Radius expression in polar coordinates. Default: 1. |
x, y | Coordinate equations as an alternative to r. |
rotate | Rotation angle in degrees. |
scale | One or two scale factors. |
move | Horizontal and vertical offset. |
frame | Thickness of a shape outline. |
turn | Number of revolutions around the shape. Default: 1. |
dir | Direction setting, such as auto, reverse, or an angle. |
fill | evenodd or nonzero polygon fill rule. |
round | Corner rounding in shape outlines. |
edge | Controls the outline edge profile. |
| Custom variable | Any additional property name can define a value used in the shape equations. |
Functions: Nested Artwork and Shaders
| Function | Description |
|---|---|
@doodle() | Generates a doodle as an image or embeds it through @content. |
@pattern() | Converts a grid-based pattern language into a GPU shader. |
@shaders() | Renders GLSL fragment shaders through WebGL. |
`@pattern()` Commands
@pattern() generates a GPU-backed pattern from its own compact syntax. Its match expressions select fills for virtual cells.
| Command | Purpose |
|---|---|
grid | Specifies the virtual pattern grid dimensions. |
fill | Sets a CSS color, gray value, or GLSL vector color. |
shape | Chooses square, circle, diamond, none, or a custom distance expression. |
size | Sets the relative size of a shape within its virtual cell. |
match(condition) | Applies declarations only when an expression matches; can be paired with else. |
repeat(count as index) | Repeats a shader expression block with an index. |
| Custom variable | Defines a value available to subsequent shader expressions. |
Functions: Time and Pointer Uniforms
| Function | Description |
|---|---|
@t, @ts, @T, @TS | Relative time or local-time values in milliseconds and seconds. |
@ux, @uy | Pointer position within the component. |
@uw, @uh | Component width and height in pixels. |
@udx, @udy | Distance from the pointer to the cell’s center on each axis. |
JavaScript Element API
All element methods operate on an existing <css-doodle> node. The export() method is asynchronous. grid, seed, use, and diagnostics are JavaScript properties, not constructor options.
| Method or Property | Description |
|---|---|
update([code]) | Regenerates the doodle, optionally replacing its code with a string. |
export([options]) | Exports SVG markup and optionally generates or downloads a PNG. Returns a Promise. |
pause() | Pauses CSS, SVG, and shader-driven animation. |
resume() | Resumes animation after a pause. |
autoUpdate([interval]) | Starts or restarts an update timer; accepts an optional interval. |
cancelAutoUpdate() | Stops the update timer and removes timer-related attributes. |
grid | Gets grid dimensions or sets the grid attribute. |
seed | Gets the active seed or sets the seed attribute. |
use | Gets or sets the use attribute. |
diagnostics | Reads warnings from the last render. |
`export()` Options
These are the options accepted by doodle.export({ ... }). The returned object always contains width, height, and svg; PNG-related fields (blob, source) are included when a PNG is generated.
| Option | Type and Behavior |
|---|---|
scale | Number; scales the exported dimensions. Default: 1. |
name | String; output file name when downloading. Defaults to a timestamp-based name. |
download | Boolean; generates and downloads a PNG. Default: false. |
detail | Boolean; generates PNG data and returns additional output details. Default: false. |
Package Exports
The npm package exposes modules for the element, generators, parsers, and metadata. The parser exports return internal syntax trees, whose structure is not a stable integration contract.
| Module or Export | Description |
|---|---|
css-doodle | Registers the <css-doodle> custom element. |
css-doodle/component: CSSDoodle | Exposes the element class. |
css-doodle/component: define(name, element) | Registers a custom-element class under a tag name. |
css-doodle/component: create(code) | Creates a doodle element from code. |
css-doodle/generator: svg(code) | Returns generated SVG markup as a string. |
css-doodle/generator: shape(commands) | Returns a CSS polygon() string. |
css-doodle/generator: prerender() | Produces prerendered HTML for a doodle with declarative Shadow DOM. |
css-doodle/parser | Exposes the language parsers and tokenizer for development tooling. |
css-doodle/meta: functions, mathFunctions | Function metadata and supported math names. |
css-doodle/meta: selectors, properties, calcOperators | Selector, property, and expression-operator metadata. |
Parser Exports
css-doodle/parser also exports individual syntax parsers for editor integrations. Their returned AST is an internal representation and can change in another release.
| Export | Parses |
|---|---|
parseCss | Doodle CSS-like statements. |
parseSvg | CSS-like SVG syntax. |
parseShapeCommands | Shape expressions. |
parseGrid | Grid dimensions and modifiers. |
parseValueGroup | Grouped values. |
parsePattern | Pattern DSL expressions. |
parseShaders | Shader expressions. |
parseSvgPath | SVG path syntax. |
parseVar | Variable syntax. |
parseDirection | Direction expressions. |
parseCompoundValue | Compound values. |
tokenizer | Raw syntax tokens. |
Custom Events
Listen for these events on the <css-doodle> element. click:cell supplies the x, y, and z coordinates, the clicked cell element, and the original browser event through event.detail. A warn event can be canceled to suppress its console message.
| Event | When It Fires |
|---|---|
render | Initial render and subsequent completed renders. |
beforeUpdate | Immediately before an update begins. |
update | After an update completes. |
click:cell | A generated cell is clicked. |
warn | The parser or generator reports a problem with the doodle code. |
const doodle = document.querySelector('css-doodle');
doodle.addEventListener('click:cell', (event) => {
const { x, y, z } = event.detail;
console.log('Clicked cell:', x, y, z);
});
doodle.addEventListener('warn', (event) => {
console.warn(event.detail.message);
});
Styling and Customization
Regular CSS controls the component’s position and layout on the page. The public Shadow DOM parts grid and cell are also available through ::part() for external styling. To change generated cell patterns individually, write rules inside the doodle itself.
css-doodle {
display: block;
max-width: 100%;
}
css-doodle::part(cell) {
transition: transform .3s ease;
}
Alternatives & Related Resources
- Create Fluid Gradient Animations With JavaScript – NeatGradients.js
- Create Dynamic Abstract Web Backgrounds With color4bg.js
- Modern Geometric Shapes Generator With JavaScript and SVG
- Random SVG Background Generator In JavaScript – rbgen.js






