Open demo

CSS code

HTML
<div><span class="lbl">Paper and grain</span><div class="bp-grid bp-3">
<div class="bp bp-svg bp-paper bp-tile"><span class="bp-tag">Paper</span></div>
<div class="bp bp-svg bp-noise bp-tile"><span class="bp-tag">Noise</span></div>
<div class="bp bp-svg bp-grain bp-tile"><span class="bp-tag">Grain on gradient</span></div>
</div></div>
<div><span class="lbl">Ruled and squared</span><div class="bp-grid bp-3">
<div class="bp bp-notebook bp-tile"><span class="bp-tag">Lined notebook</span></div>
<div class="bp bp-graph bp-tile"><span class="bp-tag">Graph paper</span></div>
<div class="bp bp-blueprint bp-tile"><span class="bp-tag">Blueprint</span></div>
</div></div>
CSS
/* Subtle UI backgrounds: paper, SVG feTurbulence noise, ruled and squared grids. Re-theme with the --bp-* properties. */
/* 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)}
/* SVG patterns: the drawing is used as a mask, so --bp-color paints it and --bp-size sets the tile width. */
.bp-svg::before{background-color:var(--bp-color);-webkit-mask:var(--bp-svg) 0 0/var(--bp-size) repeat;mask:var(--bp-svg) 0 0/var(--bp-size) repeat}
/* Paper: warm ground, soft edge and a feTurbulence grain tinted by --bp-color */
.bp-paper{--bp-bg:radial-gradient(130% 100% at 50% 0%,#fdfaf3 50%,#efe4cf);--bp-color:#6b4f1d;--bp-size:160px;--bp-opacity:.32;--bp-svg:url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .6 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>")}
/* Noise: fine grain on a flat colour */
.bp-noise{--bp-bg:#f1f5f9;--bp-color:#0f172a;--bp-size:140px;--bp-opacity:.22;--bp-svg:url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .7 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>")}
/* Grain on gradient: noise breaks up gradient banding */
.bp-grain{--bp-bg:linear-gradient(135deg,#c7d2fe,#fbcfe8 55%,#fde68a);--bp-color:#1e1b4b;--bp-size:120px;--bp-opacity:.3;--bp-svg:url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.95' numOctaves='3' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .7 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>")}
/* Lined notebook: ruled lines plus a margin rule at --bp-margin */
.bp-notebook{--bp-bg:#fff;--bp-color:#93c5fd;--bp-accent:#f87171;--bp-size:28px;--bp-margin:44px;--bp-opacity:1}
.bp-notebook::before{background-image:linear-gradient(90deg,transparent var(--bp-margin),var(--bp-accent) var(--bp-margin) calc(var(--bp-margin) + 1px),transparent 0),repeating-linear-gradient(transparent 0 calc(var(--bp-size) - 1px),var(--bp-color) 0 var(--bp-size))}
/* Graph paper: minor squares of --bp-size with a major line every five */
.bp-graph{--bp-bg:#fff;--bp-major:rgb(14 165 233 / .45);--bp-minor:rgb(14 165 233 / .16);--bp-size:12px;--bp-opacity:1}
.bp-graph::before{background-image:linear-gradient(var(--bp-major) 1px,transparent 1px),linear-gradient(90deg,var(--bp-major) 1px,transparent 1px),linear-gradient(var(--bp-minor) 1px,transparent 1px),linear-gradient(90deg,var(--bp-minor) 1px,transparent 1px);background-size:calc(var(--bp-size) * 5) calc(var(--bp-size) * 5),calc(var(--bp-size) * 5) calc(var(--bp-size) * 5),var(--bp-size) var(--bp-size),var(--bp-size) var(--bp-size)}
/* Blueprint: the graph-paper grid in white on deep blue */
.bp-blueprint{--bp-bg:radial-gradient(120% 100% at 50% 0%,#1d4ed8,#1e3a8a);--bp-major:rgb(255 255 255 / .32);--bp-minor:rgb(255 255 255 / .1);--bp-size:16px;--bp-opacity:1}
.bp-blueprint::before{background-image:linear-gradient(var(--bp-major) 1px,transparent 1px),linear-gradient(90deg,var(--bp-major) 1px,transparent 1px),linear-gradient(var(--bp-minor) 1px,transparent 1px),linear-gradient(90deg,var(--bp-minor) 1px,transparent 1px);background-size:calc(var(--bp-size) * 5) calc(var(--bp-size) * 5),calc(var(--bp-size) * 5) calc(var(--bp-size) * 5),var(--bp-size) var(--bp-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">Paper and grain</span><div class="row row-cols-1 row-cols-sm-2 row-cols-lg-3 g-3">
<div class="col"><div class="bp bp-svg bp-paper 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">Paper</span></div></div>
<div class="col"><div class="bp bp-svg bp-noise 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">Noise</span></div></div>
<div class="col"><div class="bp bp-svg bp-grain 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">Grain on gradient</span></div></div>
</div></div>
<div><span class="lbl">Ruled and squared</span><div class="row row-cols-1 row-cols-sm-2 row-cols-lg-3 g-3">
<div class="col"><div class="bp bp-notebook 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">Lined notebook</span></div></div>
<div class="col"><div class="bp bp-graph 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">Graph paper</span></div></div>
<div class="col"><div class="bp bp-blueprint 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">Blueprint</span></div></div>
</div></div>
CSS
/* Subtle UI backgrounds: paper, SVG feTurbulence noise, ruled and squared grids. Re-theme with the --bp-* properties. */
/* 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)}
/* SVG patterns: the drawing is used as a mask, so --bp-color paints it and --bp-size sets the tile width. */
.bp-svg::before{background-color:var(--bp-color);-webkit-mask:var(--bp-svg) 0 0/var(--bp-size) repeat;mask:var(--bp-svg) 0 0/var(--bp-size) repeat}
/* Paper: warm ground, soft edge and a feTurbulence grain tinted by --bp-color */
.bp-paper{--bp-bg:radial-gradient(130% 100% at 50% 0%,#fdfaf3 50%,#efe4cf);--bp-color:#6b4f1d;--bp-size:160px;--bp-opacity:.32;--bp-svg:url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .6 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>")}
/* Noise: fine grain on a flat colour */
.bp-noise{--bp-bg:#f1f5f9;--bp-color:#0f172a;--bp-size:140px;--bp-opacity:.22;--bp-svg:url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .7 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>")}
/* Grain on gradient: noise breaks up gradient banding */
.bp-grain{--bp-bg:linear-gradient(135deg,#c7d2fe,#fbcfe8 55%,#fde68a);--bp-color:#1e1b4b;--bp-size:120px;--bp-opacity:.3;--bp-svg:url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.95' numOctaves='3' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .7 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>")}
/* Lined notebook: ruled lines plus a margin rule at --bp-margin */
.bp-notebook{--bp-bg:#fff;--bp-color:#93c5fd;--bp-accent:#f87171;--bp-size:28px;--bp-margin:44px;--bp-opacity:1}
.bp-notebook::before{background-image:linear-gradient(90deg,transparent var(--bp-margin),var(--bp-accent) var(--bp-margin) calc(var(--bp-margin) + 1px),transparent 0),repeating-linear-gradient(transparent 0 calc(var(--bp-size) - 1px),var(--bp-color) 0 var(--bp-size))}
/* Graph paper: minor squares of --bp-size with a major line every five */
.bp-graph{--bp-bg:#fff;--bp-major:rgb(14 165 233 / .45);--bp-minor:rgb(14 165 233 / .16);--bp-size:12px;--bp-opacity:1}
.bp-graph::before{background-image:linear-gradient(var(--bp-major) 1px,transparent 1px),linear-gradient(90deg,var(--bp-major) 1px,transparent 1px),linear-gradient(var(--bp-minor) 1px,transparent 1px),linear-gradient(90deg,var(--bp-minor) 1px,transparent 1px);background-size:calc(var(--bp-size) * 5) calc(var(--bp-size) * 5),calc(var(--bp-size) * 5) calc(var(--bp-size) * 5),var(--bp-size) var(--bp-size),var(--bp-size) var(--bp-size)}
/* Blueprint: the graph-paper grid in white on deep blue */
.bp-blueprint{--bp-bg:radial-gradient(120% 100% at 50% 0%,#1d4ed8,#1e3a8a);--bp-major:rgb(255 255 255 / .32);--bp-minor:rgb(255 255 255 / .1);--bp-size:16px;--bp-opacity:1}
.bp-blueprint::before{background-image:linear-gradient(var(--bp-major) 1px,transparent 1px),linear-gradient(90deg,var(--bp-major) 1px,transparent 1px),linear-gradient(var(--bp-minor) 1px,transparent 1px),linear-gradient(90deg,var(--bp-minor) 1px,transparent 1px);background-size:calc(var(--bp-size) * 5) calc(var(--bp-size) * 5),calc(var(--bp-size) * 5) calc(var(--bp-size) * 5),var(--bp-size) var(--bp-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">Paper and grain</span><div class="grid grid-cols-1 gap-4 min-[576px]:grid-cols-2 min-[992px]:grid-cols-3">
<div class="bp-paper 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)]">Paper</span></div>
<div class="bp-noise 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)]">Noise</span></div>
<div class="bp-grain 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)]">Grain on gradient</span></div>
</div></div>
<div><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#5b6477] uppercase">Ruled and squared</span><div class="grid grid-cols-1 gap-4 min-[576px]:grid-cols-2 min-[992px]:grid-cols-3">
<div class="bp-notebook 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)]">Lined notebook</span></div>
<div class="bp-graph 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)]">Graph paper</span></div>
<div class="bp-blueprint 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)]">Blueprint</span></div>
</div></div>
CSS
/* Subtle UI backgrounds: paper, SVG feTurbulence noise, ruled and squared grids. Re-theme with the --bp-* properties. Each pattern is a utility; pass colours and sizes as arbitrary properties, e.g. [--bp-color:#0d9488]. */
/* Paper: warm ground, soft edge and a feTurbulence grain tinted by --bp-color */
@utility bp-paper{
  position:relative;isolation:isolate;overflow:hidden;background:var(--bp-bg,radial-gradient(130% 100% at 50% 0%,#fdfaf3 50%,#efe4cf));--bp-svg:url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .6 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
  &::before{content:"";position:absolute;inset:0;z-index:-1;border-radius:inherit;pointer-events:none;opacity:var(--bp-opacity,.32);background-color:var(--bp-color,#6b4f1d);-webkit-mask:var(--bp-svg) 0 0/var(--bp-size,160px) repeat;mask:var(--bp-svg) 0 0/var(--bp-size,160px) repeat}
}
/* Noise: fine grain on a flat colour */
@utility bp-noise{
  position:relative;isolation:isolate;overflow:hidden;background:var(--bp-bg,#f1f5f9);--bp-svg:url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .7 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
  &::before{content:"";position:absolute;inset:0;z-index:-1;border-radius:inherit;pointer-events:none;opacity:var(--bp-opacity,.22);background-color:var(--bp-color,#0f172a);-webkit-mask:var(--bp-svg) 0 0/var(--bp-size,140px) repeat;mask:var(--bp-svg) 0 0/var(--bp-size,140px) repeat}
}
/* Grain on gradient: noise breaks up gradient banding */
@utility bp-grain{
  position:relative;isolation:isolate;overflow:hidden;background:var(--bp-bg,linear-gradient(135deg,#c7d2fe,#fbcfe8 55%,#fde68a));--bp-svg:url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.95' numOctaves='3' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .7 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
  &::before{content:"";position:absolute;inset:0;z-index:-1;border-radius:inherit;pointer-events:none;opacity:var(--bp-opacity,.3);background-color:var(--bp-color,#1e1b4b);-webkit-mask:var(--bp-svg) 0 0/var(--bp-size,120px) repeat;mask:var(--bp-svg) 0 0/var(--bp-size,120px) repeat}
}
/* Lined notebook: ruled lines plus a margin rule at --bp-margin */
@utility bp-notebook{
  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(90deg,transparent var(--bp-margin,44px),var(--bp-accent,#f87171) var(--bp-margin,44px) calc(var(--bp-margin,44px) + 1px),transparent 0),repeating-linear-gradient(transparent 0 calc(var(--bp-size,28px) - 1px),var(--bp-color,#93c5fd) 0 var(--bp-size,28px))}
}
/* Graph paper: minor squares of --bp-size with a major line every five */
@utility bp-graph{
  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-major,rgb(14 165 233 / .45)) 1px,transparent 1px),linear-gradient(90deg,var(--bp-major,rgb(14 165 233 / .45)) 1px,transparent 1px),linear-gradient(var(--bp-minor,rgb(14 165 233 / .16)) 1px,transparent 1px),linear-gradient(90deg,var(--bp-minor,rgb(14 165 233 / .16)) 1px,transparent 1px);background-size:calc(var(--bp-size,12px) * 5) calc(var(--bp-size,12px) * 5),calc(var(--bp-size,12px) * 5) calc(var(--bp-size,12px) * 5),var(--bp-size,12px) var(--bp-size,12px),var(--bp-size,12px) var(--bp-size,12px)}
}
/* Blueprint: the graph-paper grid in white on deep blue */
@utility bp-blueprint{
  position:relative;isolation:isolate;overflow:hidden;background:var(--bp-bg,radial-gradient(120% 100% at 50% 0%,#1d4ed8,#1e3a8a));
  &::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-major,rgb(255 255 255 / .32)) 1px,transparent 1px),linear-gradient(90deg,var(--bp-major,rgb(255 255 255 / .32)) 1px,transparent 1px),linear-gradient(var(--bp-minor,rgb(255 255 255 / .1)) 1px,transparent 1px),linear-gradient(90deg,var(--bp-minor,rgb(255 255 255 / .1)) 1px,transparent 1px);background-size:calc(var(--bp-size,16px) * 5) calc(var(--bp-size,16px) * 5),calc(var(--bp-size,16px) * 5) calc(var(--bp-size,16px) * 5),var(--bp-size,16px) var(--bp-size,16px),var(--bp-size,16px) var(--bp-size,16px)}
}

About this set

Six quiet textures for app shells, landing pages and editors. Paper puts a warm, slightly darker edge on a cream ground and adds a brown grain. Noise is a fine grey grain on a flat slate colour. Grain on gradient lays the same kind of noise over an indigo, pink and amber gradient, which also hides gradient banding. Lined notebook draws ruled blue lines and a red margin rule, Graph paper draws minor squares with a stronger line every five, and Blueprint is that grid in white on deep blue. The grain is an SVG feTurbulence filter inlined as a data URI. Instead of using it as a background image, the set uses it as a mask on a ::before layer filled with –bp-color, so the grain can be any colour and its strength is just –bp-opacity. The ruled and squared grids are layered linear-gradients sized from one –bp-size value, so the major lines always land on every fifth minor line. Use the grain textures behind hero sections and cards, and the grids behind note-taking, planning and technical pages.

What’s included

  • Paper, noise, grain on gradient, lined notebook, graph paper, blueprint
  • SVG feTurbulence noise inlined as a data URI, no image files
  • Grain colour comes from --bp-color because the noise is a mask
  • Graph and blueprint grids derive the major lines from one --bp-size
  • Plain CSS, Bootstrap 5 and Tailwind CSS 4 versions of the same design

Accessibility

The textures are decorative backgrounds, so they need no alt text and are not read by screen readers. Name labels are opaque chips with text above 4.5:1 on every texture. Nothing moves and there are no interactive controls.

Customise it

Change --bp-bg (which can be a gradient), --bp-color, --bp-size and --bp-opacity; the notebook adds --bp-accent and --bp-margin, and the grids use --bp-major and --bp-minor. In Tailwind pass the same properties as arbitrary properties on the bp-paper, bp-noise or bp-graph utilities.