Why CSS textures?
A repeating background made of gradients is sharper, lighter, and more flexible than a texture image — it scales to any resolution, recolors with one value, and adds zero network requests. Almost every pattern is just repeating-linear-gradient, radial-gradient, or conic-gradient on background-image with a background-size.
Weightless
No image downloads — just a few CSS values. Faster pages, every time.
Infinitely crisp
Gradients are vector-sharp at any zoom or screen density. No blur, no pixelation.
Recolor instantly
Change one hex value and the whole texture updates. Great with design tokens.
Tile-able
background-size sets the tile; it repeats seamlessly across any area.
Six textures, copy & paste
Every swatch is a single background. Click Copy on any block to grab it.
<!-- a texture is just a class on a normal element --> <div class="grid2"> <div><div class="tx tx-dots"></div><div class="swatch-label">// polka dots</div></div> <div><div class="tx tx-stripes"></div><div class="swatch-label">// diagonal stripes</div></div> <div><div class="tx tx-grid"></div><div class="swatch-label">// grid lines</div></div> <div><div class="tx tx-check"></div><div class="swatch-label">// checkerboard</div></div> <div><div class="tx tx-grain"></div><div class="swatch-label">// noise / grain</div></div> <div><div class="tx tx-graph"></div><div class="swatch-label">// graph paper</div></div> </div>
.grid2 {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 14px;
}
@media (max-width: 560px) { .grid2 { grid-template-columns: 1fr; } }
/* every texture sits in this box */
.tx {
height: 150px;
border-radius: 12px;
border: 1px solid #e5e7eb;
}
.swatch-label {
font-size: .72rem;
color: #6b7280;
font-family: 'SF Mono', Consolas, monospace;
margin-top: 8px;
}
.tx-dots {
background-color: #fff;
background-image: radial-gradient(#5e9ea0 2px, transparent 2px);
background-size: 20px 20px; /* dot spacing */
}
.tx-stripes {
background: repeating-linear-gradient(45deg,
#5e9ea0 0 12px, #e6f3f2 12px 24px); /* color / gap, repeated */
}
.tx-grid {
background-color: #fff;
background-image:
linear-gradient(#cfe6e4 1px, transparent 1px), /* horizontal */
linear-gradient(90deg, #cfe6e4 1px, transparent 1px); /* vertical */
background-size: 24px 24px;
}
.tx-check {
background: conic-gradient(#5e9ea0 90deg, #e6f3f2 0 180deg,
#5e9ea0 0 270deg, #e6f3f2 0);
background-size: 36px 36px; /* one square pair = half the tile */
}
.tx-grain {
position: relative; /* anchors the overlay */
background: #5e9ea0; /* base color */
}
.tx-grain::after {
content: ''; position: absolute; inset: 0;
border-radius: 12px;
opacity: .35; mix-blend-mode: multiply;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
.tx-graph {
background-color: #fff;
background-image:
linear-gradient(#e6f3f2 1px, transparent 1px), /* fine lines */
linear-gradient(90deg, #e6f3f2 1px, transparent 1px),
linear-gradient(#cfe6e4 1px, transparent 1px), /* bold lines */
linear-gradient(90deg, #cfe6e4 1px, transparent 1px);
background-size: 100px 100px, 100px 100px, 20px 20px, 20px 20px;
}
background-position or a slow background-position animation for movement. Keep contrast gentle so the texture sits behind content, never fights it.Characteristics & components
The signals of a CSS-texture approach:
Texture created with CSS No image backgrounds
The techniques
A gradient, a noise overlay, a pattern, and a layered shadow — live first, then the code.
<div class="techniques"> <div class="grad"></div> <div class="noise"></div> <div class="dots"></div> <div class="shadow"></div> </div>
.techniques {
display: flex;
flex-wrap: wrap;
gap: 16px;
align-items: center;
}
/* every box is the same size */
.techniques > div {
width: 120px;
height: 90px;
border-radius: 12px;
}
/* 1 — Gradient */
.grad { background: radial-gradient(circle at 30% 30%, #7bd8c0, #5e9ea0); }
/* 2 — Noise overlay (inline SVG feTurbulence) */
.noise {
position: relative; /* anchors the overlay */
background: #5e9ea0;
overflow: hidden;
}
.noise::after {
content: ''; position: absolute; inset: 0;
opacity: .4; mix-blend-mode: multiply;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
/* 3 — Pattern (repeating dots) */
.dots {
background-color: #fff;
background-image: radial-gradient(#5e9ea0 2px, transparent 2px);
background-size: 18px 18px;
}
/* 4 — Layered shadow for depth */
.shadow {
background: #fff;
box-shadow: 0 2px 4px rgba(0,0,0,.1),
0 8px 16px rgba(0,0,0,.1),
0 20px 40px rgba(94,158,160,.3);
}
The takeaway
Most surface textures are one background away: radial-gradient for dots,
repeating-linear-gradient for stripes, stacked linear-gradients for grids
and graph paper, conic-gradient for checks, and a tiny SVG feTurbulence for
grain. Vector-crisp, weightless, and recolorable — use them to add depth without a single image. See
also CSS Recipes.