Open demo

CSS code

HTML
<div><span class="lbl">Dots and tiles</span><div class="bp-grid bp-3">
<div class="bp bp-dots bp-tile"><span class="bp-tag">Dots</span></div>
<div class="bp bp-polka bp-tile"><span class="bp-tag">Polka dots</span></div>
<div class="bp bp-checker bp-tile"><span class="bp-tag">Checkerboard</span></div>
</div></div>
<div><span class="lbl">Lines</span><div class="bp-grid bp-3">
<div class="bp bp-grid-lines bp-tile"><span class="bp-tag">Grid</span></div>
<div class="bp bp-stripes bp-tile"><span class="bp-tag">Diagonal stripes</span></div>
<div class="bp bp-zigzag bp-tile"><span class="bp-tag">Zigzag</span></div>
</div></div>
CSS
/* Geometric background patterns in pure CSS gradients. Re-theme with --bp-bg, --bp-color, --bp-size and --bp-opacity. */
/* Base: the pattern is painted on ::before, under the content (isolation:isolate), so --bp-opacity
   fades only the pattern, never the text on top of it. */
.bp{--bp-opacity:1;position:relative;isolation:isolate;overflow:hidden;background:var(--bp-bg)}
.bp::before{content:"";position:absolute;inset:0;z-index:-1;border-radius:inherit;pointer-events:none;opacity:var(--bp-opacity)}
/* Dots: one radial-gradient per tile */
.bp-dots{--bp-bg:#eef2ff;--bp-color:#4f46e5;--bp-size:22px;--bp-dot:2px;--bp-opacity:.55}
.bp-dots::before{background-image:radial-gradient(circle,var(--bp-color) var(--bp-dot),transparent calc(var(--bp-dot) + .5px));background-size:var(--bp-size) var(--bp-size)}
/* Polka dots: two dot layers, the second offset by half a tile */
.bp-polka{--bp-bg:#fdf2f8;--bp-color:#db2777;--bp-size:40px;--bp-dot:5px;--bp-opacity:.4}
.bp-polka::before{background-image:radial-gradient(circle,var(--bp-color) var(--bp-dot),transparent calc(var(--bp-dot) + .5px)),radial-gradient(circle,var(--bp-color) var(--bp-dot),transparent calc(var(--bp-dot) + .5px));background-size:var(--bp-size) var(--bp-size);background-position:0 0,calc(var(--bp-size) / 2) calc(var(--bp-size) / 2)}
/* Checkerboard: a four-quarter conic-gradient */
.bp-checker{--bp-bg:#f0fdfa;--bp-color:#0d9488;--bp-size:36px;--bp-opacity:.16}
.bp-checker::before{background-image:conic-gradient(var(--bp-color) 25%,transparent 0 50%,var(--bp-color) 0 75%,transparent 0);background-size:var(--bp-size) var(--bp-size)}
/* Grid: a horizontal and a vertical hairline per tile */
.bp-grid-lines{--bp-bg:#fff;--bp-color:#0f172a;--bp-size:28px;--bp-line:1px;--bp-opacity:.1}
.bp-grid-lines::before{background-image:linear-gradient(var(--bp-color) var(--bp-line),transparent var(--bp-line)),linear-gradient(90deg,var(--bp-color) var(--bp-line),transparent var(--bp-line));background-size:var(--bp-size) var(--bp-size)}
/* Diagonal stripes: --bp-line is the stripe, --bp-size the repeat */
.bp-stripes{--bp-bg:#fffbeb;--bp-color:#d97706;--bp-size:20px;--bp-line:7px;--bp-opacity:.22}
.bp-stripes::before{background-image:repeating-linear-gradient(45deg,var(--bp-color) 0 var(--bp-line),transparent var(--bp-line) var(--bp-size))}
/* Zigzag: four triangular linear-gradients */
.bp-zigzag{--bp-bg:#f5f3ff;--bp-color:#7c3aed;--bp-size:36px;--bp-opacity:.2}
.bp-zigzag::before{background-image:linear-gradient(135deg,var(--bp-color) 25%,transparent 25%),linear-gradient(225deg,var(--bp-color) 25%,transparent 25%),linear-gradient(315deg,var(--bp-color) 25%,transparent 25%),linear-gradient(45deg,var(--bp-color) 25%,transparent 25%);background-position:calc(var(--bp-size) / -2) 0,calc(var(--bp-size) / -2) 0,0 0,0 0;background-size:var(--bp-size) var(--bp-size)}
/* Demo tile and name chip */
.bp-tile{min-height:var(--bp-tile-h,180px);border-radius:16px;border:1px solid #dee2e6}
/* The name chip is an opaque scrim, so its text keeps 4.5:1 whatever pattern is underneath. */
.bp-tag{position:absolute;left:16px;bottom:16px;padding:4px 8px;border-radius:6px;background:#fff;color:#0f172a;font-size:.875rem;font-weight:600;line-height:1.5;box-shadow:0 2px 4px rgb(0 0 0 / .075)}

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<div><span class="lbl">Dots and tiles</span><div class="row row-cols-1 row-cols-sm-2 row-cols-lg-3 g-3">
<div class="col"><div class="bp bp-dots bp-tile rounded-4 border"><span class="position-absolute start-0 bottom-0 m-3 px-2 py-1 rounded-2 bg-white text-dark small fw-semibold shadow-sm lh-base">Dots</span></div></div>
<div class="col"><div class="bp bp-polka bp-tile rounded-4 border"><span class="position-absolute start-0 bottom-0 m-3 px-2 py-1 rounded-2 bg-white text-dark small fw-semibold shadow-sm lh-base">Polka dots</span></div></div>
<div class="col"><div class="bp bp-checker bp-tile rounded-4 border"><span class="position-absolute start-0 bottom-0 m-3 px-2 py-1 rounded-2 bg-white text-dark small fw-semibold shadow-sm lh-base">Checkerboard</span></div></div>
</div></div>
<div><span class="lbl">Lines</span><div class="row row-cols-1 row-cols-sm-2 row-cols-lg-3 g-3">
<div class="col"><div class="bp bp-grid-lines bp-tile rounded-4 border"><span class="position-absolute start-0 bottom-0 m-3 px-2 py-1 rounded-2 bg-white text-dark small fw-semibold shadow-sm lh-base">Grid</span></div></div>
<div class="col"><div class="bp bp-stripes bp-tile rounded-4 border"><span class="position-absolute start-0 bottom-0 m-3 px-2 py-1 rounded-2 bg-white text-dark small fw-semibold shadow-sm lh-base">Diagonal stripes</span></div></div>
<div class="col"><div class="bp bp-zigzag bp-tile rounded-4 border"><span class="position-absolute start-0 bottom-0 m-3 px-2 py-1 rounded-2 bg-white text-dark small fw-semibold shadow-sm lh-base">Zigzag</span></div></div>
</div></div>
CSS
/* Geometric background patterns in pure CSS gradients. Re-theme with --bp-bg, --bp-color, --bp-size and --bp-opacity. */
/* Base: the pattern is painted on ::before, under the content (isolation:isolate), so --bp-opacity
   fades only the pattern, never the text on top of it. */
.bp{--bp-opacity:1;position:relative;isolation:isolate;overflow:hidden;background:var(--bp-bg)}
.bp::before{content:"";position:absolute;inset:0;z-index:-1;border-radius:inherit;pointer-events:none;opacity:var(--bp-opacity)}
/* Dots: one radial-gradient per tile */
.bp-dots{--bp-bg:#eef2ff;--bp-color:#4f46e5;--bp-size:22px;--bp-dot:2px;--bp-opacity:.55}
.bp-dots::before{background-image:radial-gradient(circle,var(--bp-color) var(--bp-dot),transparent calc(var(--bp-dot) + .5px));background-size:var(--bp-size) var(--bp-size)}
/* Polka dots: two dot layers, the second offset by half a tile */
.bp-polka{--bp-bg:#fdf2f8;--bp-color:#db2777;--bp-size:40px;--bp-dot:5px;--bp-opacity:.4}
.bp-polka::before{background-image:radial-gradient(circle,var(--bp-color) var(--bp-dot),transparent calc(var(--bp-dot) + .5px)),radial-gradient(circle,var(--bp-color) var(--bp-dot),transparent calc(var(--bp-dot) + .5px));background-size:var(--bp-size) var(--bp-size);background-position:0 0,calc(var(--bp-size) / 2) calc(var(--bp-size) / 2)}
/* Checkerboard: a four-quarter conic-gradient */
.bp-checker{--bp-bg:#f0fdfa;--bp-color:#0d9488;--bp-size:36px;--bp-opacity:.16}
.bp-checker::before{background-image:conic-gradient(var(--bp-color) 25%,transparent 0 50%,var(--bp-color) 0 75%,transparent 0);background-size:var(--bp-size) var(--bp-size)}
/* Grid: a horizontal and a vertical hairline per tile */
.bp-grid-lines{--bp-bg:#fff;--bp-color:#0f172a;--bp-size:28px;--bp-line:1px;--bp-opacity:.1}
.bp-grid-lines::before{background-image:linear-gradient(var(--bp-color) var(--bp-line),transparent var(--bp-line)),linear-gradient(90deg,var(--bp-color) var(--bp-line),transparent var(--bp-line));background-size:var(--bp-size) var(--bp-size)}
/* Diagonal stripes: --bp-line is the stripe, --bp-size the repeat */
.bp-stripes{--bp-bg:#fffbeb;--bp-color:#d97706;--bp-size:20px;--bp-line:7px;--bp-opacity:.22}
.bp-stripes::before{background-image:repeating-linear-gradient(45deg,var(--bp-color) 0 var(--bp-line),transparent var(--bp-line) var(--bp-size))}
/* Zigzag: four triangular linear-gradients */
.bp-zigzag{--bp-bg:#f5f3ff;--bp-color:#7c3aed;--bp-size:36px;--bp-opacity:.2}
.bp-zigzag::before{background-image:linear-gradient(135deg,var(--bp-color) 25%,transparent 25%),linear-gradient(225deg,var(--bp-color) 25%,transparent 25%),linear-gradient(315deg,var(--bp-color) 25%,transparent 25%),linear-gradient(45deg,var(--bp-color) 25%,transparent 25%);background-position:calc(var(--bp-size) / -2) 0,calc(var(--bp-size) / -2) 0,0 0,0 0;background-size:var(--bp-size) var(--bp-size)}
/* Demo tile height; corners, border and the name chip use Bootstrap utilities */
.bp-tile{min-height:var(--bp-tile-h,180px)}

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<div><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#5b6477] uppercase">Dots and tiles</span><div class="grid grid-cols-1 gap-4 min-[576px]:grid-cols-2 min-[992px]:grid-cols-3">
<div class="bp-dots relative min-h-[180px] overflow-hidden rounded-2xl border border-[#dee2e6]"><span class="absolute bottom-4 left-4 rounded-md bg-white px-2 py-1 text-sm leading-normal font-semibold text-[#0f172a] shadow-[0_2px_4px_rgb(0_0_0/.075)]">Dots</span></div>
<div class="bp-polka relative min-h-[180px] overflow-hidden rounded-2xl border border-[#dee2e6]"><span class="absolute bottom-4 left-4 rounded-md bg-white px-2 py-1 text-sm leading-normal font-semibold text-[#0f172a] shadow-[0_2px_4px_rgb(0_0_0/.075)]">Polka dots</span></div>
<div class="bp-checker relative min-h-[180px] overflow-hidden rounded-2xl border border-[#dee2e6]"><span class="absolute bottom-4 left-4 rounded-md bg-white px-2 py-1 text-sm leading-normal font-semibold text-[#0f172a] shadow-[0_2px_4px_rgb(0_0_0/.075)]">Checkerboard</span></div>
</div></div>
<div><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#5b6477] uppercase">Lines</span><div class="grid grid-cols-1 gap-4 min-[576px]:grid-cols-2 min-[992px]:grid-cols-3">
<div class="bp-grid-lines relative min-h-[180px] overflow-hidden rounded-2xl border border-[#dee2e6]"><span class="absolute bottom-4 left-4 rounded-md bg-white px-2 py-1 text-sm leading-normal font-semibold text-[#0f172a] shadow-[0_2px_4px_rgb(0_0_0/.075)]">Grid</span></div>
<div class="bp-stripes relative min-h-[180px] overflow-hidden rounded-2xl border border-[#dee2e6]"><span class="absolute bottom-4 left-4 rounded-md bg-white px-2 py-1 text-sm leading-normal font-semibold text-[#0f172a] shadow-[0_2px_4px_rgb(0_0_0/.075)]">Diagonal stripes</span></div>
<div class="bp-zigzag relative min-h-[180px] overflow-hidden rounded-2xl border border-[#dee2e6]"><span class="absolute bottom-4 left-4 rounded-md bg-white px-2 py-1 text-sm leading-normal font-semibold text-[#0f172a] shadow-[0_2px_4px_rgb(0_0_0/.075)]">Zigzag</span></div>
</div></div>
CSS
/* Geometric background patterns in pure CSS gradients. Re-theme with --bp-bg, --bp-color, --bp-size and --bp-opacity. Each pattern is a utility; pass colours and sizes as arbitrary properties, e.g. [--bp-color:#0d9488]. */
/* Dots: one radial-gradient per tile */
@utility bp-dots{
  position:relative;isolation:isolate;overflow:hidden;background:var(--bp-bg,#eef2ff);
  &::before{content:"";position:absolute;inset:0;z-index:-1;border-radius:inherit;pointer-events:none;opacity:var(--bp-opacity,.55);background-image:radial-gradient(circle,var(--bp-color,#4f46e5) var(--bp-dot,2px),transparent calc(var(--bp-dot,2px) + .5px));background-size:var(--bp-size,22px) var(--bp-size,22px)}
}
/* Polka dots: two dot layers, the second offset by half a tile */
@utility bp-polka{
  position:relative;isolation:isolate;overflow:hidden;background:var(--bp-bg,#fdf2f8);
  &::before{content:"";position:absolute;inset:0;z-index:-1;border-radius:inherit;pointer-events:none;opacity:var(--bp-opacity,.4);background-image:radial-gradient(circle,var(--bp-color,#db2777) var(--bp-dot,5px),transparent calc(var(--bp-dot,5px) + .5px)),radial-gradient(circle,var(--bp-color,#db2777) var(--bp-dot,5px),transparent calc(var(--bp-dot,5px) + .5px));background-size:var(--bp-size,40px) var(--bp-size,40px);background-position:0 0,calc(var(--bp-size,40px) / 2) calc(var(--bp-size,40px) / 2)}
}
/* Checkerboard: a four-quarter conic-gradient */
@utility bp-checker{
  position:relative;isolation:isolate;overflow:hidden;background:var(--bp-bg,#f0fdfa);
  &::before{content:"";position:absolute;inset:0;z-index:-1;border-radius:inherit;pointer-events:none;opacity:var(--bp-opacity,.16);background-image:conic-gradient(var(--bp-color,#0d9488) 25%,transparent 0 50%,var(--bp-color,#0d9488) 0 75%,transparent 0);background-size:var(--bp-size,36px) var(--bp-size,36px)}
}
/* Grid: a horizontal and a vertical hairline per tile */
@utility bp-grid-lines{
  position:relative;isolation:isolate;overflow:hidden;background:var(--bp-bg,#fff);
  &::before{content:"";position:absolute;inset:0;z-index:-1;border-radius:inherit;pointer-events:none;opacity:var(--bp-opacity,.1);background-image:linear-gradient(var(--bp-color,#0f172a) var(--bp-line,1px),transparent var(--bp-line,1px)),linear-gradient(90deg,var(--bp-color,#0f172a) var(--bp-line,1px),transparent var(--bp-line,1px));background-size:var(--bp-size,28px) var(--bp-size,28px)}
}
/* Diagonal stripes: --bp-line is the stripe, --bp-size the repeat */
@utility bp-stripes{
  position:relative;isolation:isolate;overflow:hidden;background:var(--bp-bg,#fffbeb);
  &::before{content:"";position:absolute;inset:0;z-index:-1;border-radius:inherit;pointer-events:none;opacity:var(--bp-opacity,.22);background-image:repeating-linear-gradient(45deg,var(--bp-color,#d97706) 0 var(--bp-line,7px),transparent var(--bp-line,7px) var(--bp-size,20px))}
}
/* Zigzag: four triangular linear-gradients */
@utility bp-zigzag{
  position:relative;isolation:isolate;overflow:hidden;background:var(--bp-bg,#f5f3ff);
  &::before{content:"";position:absolute;inset:0;z-index:-1;border-radius:inherit;pointer-events:none;opacity:var(--bp-opacity,.2);background-image:linear-gradient(135deg,var(--bp-color,#7c3aed) 25%,transparent 25%),linear-gradient(225deg,var(--bp-color,#7c3aed) 25%,transparent 25%),linear-gradient(315deg,var(--bp-color,#7c3aed) 25%,transparent 25%),linear-gradient(45deg,var(--bp-color,#7c3aed) 25%,transparent 25%);background-position:calc(var(--bp-size,36px) / -2) 0,calc(var(--bp-size,36px) / -2) 0,0 0,0 0;background-size:var(--bp-size,36px) var(--bp-size,36px)}
}

About this set

Six geometric background patterns drawn entirely with CSS gradients, with no images and no SVG. Dots is a single radial-gradient repeated on a 22 pixel tile. Polka dots stacks two dot layers and offsets the second by half a tile. Checkerboard is one conic-gradient split into four quarters. Grid draws a horizontal and a vertical hairline per tile. Diagonal stripes is a repeating-linear-gradient at 45 degrees, and Zigzag combines four triangular linear-gradients into a chevron band. Use the dots and the grid behind dashboards, editors and empty states, where a pattern should be felt more than seen, and the stripes, checkerboard and zigzag for banners, placeholders and playful sections. Every pattern is painted on a ::before layer behind the content of an element with isolation set, so –bp-opacity fades the pattern without fading any text on top. Colour, ground, tile size, dot or line size and opacity are all custom properties, so one class can be re-themed per section. The Bootstrap version uses the same classes inside a row and col grid, and the Tailwind version turns each pattern into a utility such as bp-dots.

What’s included

  • Six patterns: dots, polka dots, checkerboard, grid, diagonal stripes, zigzag
  • Pure CSS gradients, no image requests
  • Colour, ground, size and opacity set with --bp-* custom properties
  • Pattern sits on ::before, so content on top keeps full opacity
  • Plain CSS, Bootstrap 5 and Tailwind CSS 4 versions of the same design

Accessibility

The patterns are decorative CSS backgrounds, so they need no alt text and are not announced by screen readers. Each name label is an opaque white chip, which keeps its text above 4.5:1 whatever pattern sits underneath. Nothing animates and there are no interactive controls.

Customise it

Set --bp-color, --bp-bg, --bp-size and --bp-opacity on the element (plus --bp-dot or --bp-line where the pattern has them). The Bootstrap version uses the same properties; in Tailwind pass them as arbitrary properties, for example bp-dots [--bp-color:#0d9488] [--bp-size:16px].