Skip to main content

CSS Pattern Generator

Create repeating CSS background patterns with visual presets.

Reviewed by · Last reviewed

20px
100%
CSS
background: repeating-linear-gradient(
  45deg,
  #3b82f6 0px,
  #3b82f6 20px,
  #ffffff 20px,
  #ffffff 40px
);
opacity: 1;

Creating a Pattern

  1. Pick a pattern preset from the dropdown - stripes, dots, grid, checkerboard, zigzag, diamonds, triangles. Each preset is a pure-CSS recipe built from repeating gradients, no images.
  2. Set primary and secondary colors. Primary is the motif color (the dot, stripe, or shape); secondary is the background field behind it.
  3. Adjust scale to change tile size. This maps to the background-size value in the output - smaller values give a denser pattern, larger values give bolder geometric blocks.
  4. Tune opacity to soften the motif. Internally this becomes an alpha channel on the primary color rather than a separate opacity declaration, so the secondary field stays fully opaque.
  5. Copy CSS to pull the full background-image plus background-size (and sometimes background-position) into your stylesheet.

The gradient trick that makes patterns work

Every pattern in this generator is a composition of linear-gradient(), radial-gradient(), or repeating-linear-gradient() from CSS Images Module Level 3, layered via comma-separated background-image values and tiled with a fixed background-size. Stripes are a two-stop repeating-linear-gradient. Dots are a radial-gradient with a transparent fall-off, tiled. Grid lines are two orthogonal repeating gradients stacked. Checkerboard is a pair of 45-degree gradients offset by half a tile, or a CSS background-image built from four linear gradients.

Because everything is synthesized at paint time, patterns scale to any container size without pixelation, theme instantly via CSS custom properties, and weigh zero bytes over the wire. The browser rasterizes a single tile once into an internal cache and then repeats it across the element, so the runtime cost is a single-tile paint plus cheap GPU tiling - effectively free compared to a tiled PNG that has to go through network + decode + paint. The one caveat: very complex multi-layer patterns on huge elements can create large backing-store textures. Chrome\'s compositor limit is around 8192 pixels on a side on most GPUs, which is rarely a practical issue.

When a CSS pattern beats an image

  • Themed backgrounds that follow the user\'s light/dark preference without shipping two PNGs.
  • Hero decorations that need to stretch across any viewport width without repetition seams.
  • Print-friendly backgrounds that don\'t need a separate @media print asset.
  • Loading placeholders combined with animation for a barber-pole or shimmer effect.
  • Low-data scenarios - patterns use ~100 bytes of CSS versus 10-100KB of PNG.
  • Rapid iteration during design exploration, where regenerating a pattern asset would mean a round trip through Figma or Illustrator.

Edge cases you should know

  • Seam alignment on tiled backgrounds. When a pattern needs to tile seamlessly, the tile dimensions (background-size) must match the gradient\'s repeat period exactly. A 20px checkerboard with a 19.5px tile will produce visible seams every tile. Use whole-pixel dimensions and test at multiple zoom levels.
  • Subpixel banding at certain zoom levels. On browsers using fractional pixel rendering, angled stripes at integer pixel widths can shimmer at 90%, 110%, and 125% zoom. Widen the stripe or desaturate the colors to hide it.
  • Performance on scrolling backgrounds. A full-viewport pattern with background-attachment: fixed forces the browser to repaint the pattern on every scroll frame. Use background-attachment: scroll (the default) or promote the element to its own compositor layer with will-change: transform.
  • Alpha over white vs over dark. A 20%-alpha pattern looks very different on a white background versus a dark one. Pick your opacity after you know the underlying surface color.
  • Pattern stacking order. Comma-separated background-image values stack with the first image on top - the opposite of typical z-index intuition. If your dots disappear under the stripes, swap the order.

A note on the spec

CSS background patterns rely on background-image, background-size, background-position, and background-repeat from the CSS Backgrounds and Borders Module Level 3, plus the gradient functions from CSS Images Module Level 3. Multiple background layers were standardized in CSS3 and supported by every browser since IE9, 2011. Gradient support is equally universal today - no prefixes needed, per caniuse.com/css-gradients. For modern color control, CSS Color Module Level 4 adds oklch and wide-gamut color space interpolation inside gradients, useful when you need perceptually uniform stripes from, say, blue to pink. If you need true texture noise (film grain, paper fiber, fabric weave) rather than geometric repeats, CSS alone can\'t generate it - you\'ll need an SVG filter with <feTurbulence> or a pre-generated noise PNG.

When to reach for something else

Pure-CSS patterns win for geometric repeats - grids, dots, stripes, checkerboards, diamonds. Where they lose: organic textures, non-repeating compositions, and anything that needs randomness. For those, pre-generated SVG patterns (export from Figma or use a resource like Hero Patterns) are lightweight and stay vector-crisp. For photographic textures (wood grain, concrete, paper) a WebP or AVIF image is the right call - usually under 20KB at 1x and perceptually indistinguishable from the CSS-synthesized alternative. Compared to Tailwind\'s utility-class patterns (which essentially inline the CSS you\'re generating here), hand-written CSS gives you arbitrary control and doesn\'t bloat your class list. For animated patterns - barber poles, shifting grids, Mondrian-style grids that reflow - CSS patterns combined with @keyframes on background-position are extremely cheap, often cheaper than any JavaScript or Canvas approach.

Frequently Asked Questions

How do pattern scale and opacity change the output CSS?

Scale maps directly to the <code>background-size</code> value - increasing scale from 20px to 40px doubles the tile size of the entire repeat. Opacity, despite the name, does not become a CSS <code>opacity</code> rule; it becomes an alpha channel on the primary color using <code>rgba()</code> or <code>oklch(... / a)</code>. That distinction matters: a real <code>opacity</code> rule would fade the whole element, including the secondary field, while the alpha trick keeps the field fully opaque and only softens the motif.

Why are dotted and grid patterns cheaper than an image?

Because the browser rasterizes a single tile of the pattern into its cache the first time it paints, and then tiles that cached bitmap across the element by repeated GPU blits. A PNG-backed pattern has to be downloaded over HTTP, decoded into memory, uploaded to the GPU, and then tiled - each step a few milliseconds on mobile. A CSS pattern skips the HTTP and decode steps entirely. For typical 20-100px tiles the paint cost is under a millisecond; you effectively get free patterning.

Can I use CSS variables inside the generated pattern?

Yes, and it's the recommended approach for themeable patterns. After copying the CSS, replace the literal color values with <code>var(--pattern-primary)</code> and <code>var(--pattern-secondary)</code>. Because <code>background-image</code> is resolved at paint time, flipping the variables (for example through a dark-mode class) triggers an immediate repaint without rebuilding the gradient string. You can even animate variables via <code>@property</code> for smooth color transitions between themes.

Does this tool send my pattern choices anywhere?

No. The pattern preset, colors, scale, and opacity live entirely in Preact component state in your browser. The CSS string is assembled from a local template literal; the preview is applied via an inline <code>style</code> attribute on a preview div. There is no <code>fetch</code>, no WebSocket, and no analytics event carrying your color choices.

Can I animate a CSS pattern?

Yes, and it's one of the cheapest animation styles available. Animate <code>background-position</code> with a <code>@keyframes</code> rule to get sliding stripes (barber pole), scrolling grids, or rotating dots. Because the browser only has to recomposite a pre-cached tile, you stay at 60fps even on low-end hardware. For color shifts within the pattern, wrap the motif color in a CSS custom property and transition that instead.

How does browser support look for these patterns?

All the underlying properties - <code>background-image</code> with multiple layers, <code>background-size</code>, <code>linear-gradient</code>, <code>radial-gradient</code>, <code>repeating-linear-gradient</code> - have had universal, unprefixed support since roughly 2012. caniuse.com/css-gradients reports 98%+ coverage globally. The newer color-space interpolation syntax (<code>in oklch</code>) has narrower support (Chrome 111+, Safari 16.2+), but the generator uses plain sRGB by default.

Can patterns be accessible?

Patterns are decorative by nature and screen readers ignore them, so the main accessibility concern is visual contrast for the content placed above the pattern. Run the foreground text against the darkest and lightest points of the pattern through a WCAG contrast checker - both combinations need to pass 4.5:1 (normal) or 3:1 (large). Avoid fine high-contrast patterns behind body copy.

What is the difference between repeating-linear-gradient and regular linear-gradient for stripes?

<code>linear-gradient()</code> fills the whole element with a single ramp. <code>repeating-linear-gradient()</code> tiles the ramp from the first to the last color stop across the element, repeating the same pattern indefinitely. For stripes, <code>repeating-linear-gradient(45deg, red 0 10px, white 10px 20px)</code> produces a clean repeat; the equivalent <code>linear-gradient</code> would only show one stripe pair no matter how large the element grew. Always use the repeating variant for tiled motifs.

More CSS & Design