//- number of polygon vertices and rounding precision
- let n = 7, p = 2;
//- base (central angle) in degres & radians
- let deg = 360/n, rad = 2*Math.PI/n;
//- vertex & gradient array
- let v = [], g = [];
//- create gradient stack for background (mesh gradient emulation)
- for(let i = 0; i < n; i++)
//- current angle in radians
- let ca = i*rad;
//- add to array of vertex coords
- v.push(['cos', 'sin'].map(f => +(50*(1 + Math[f](ca))).toFixed(p)));
// current angle in degrees incl. gradient start offset
- ca = (i*deg + 90)%360;
// add to array of gradient baxkground layers
- g.push(`linear-gradient(${ca}deg, hsl(${ca}, 100%, 0%), hsl(${ca}, 100%, 65%))`);
body(style=`--v: ${v.map(p => p.map(c => `${c}%`).join(' ')).join(',')}; --b: ${g.join(', ')}`)
// contains nothing but filter => functionally same as a style elem
// zero its dimensions and hide it from screen readers
svg(width='0' height='0' aria-hidden='true')
// sRGB is what we normally want (but not default)
filter#grain(color-interpolation-filters='sRGB')
// generate fine noise
feTurbulence(type='fractalNoise' baseFrequency='.713' numOctaves='3')
// use noise as displacement map
feDisplacementMap(in='SourceGraphic' scale='99' xChannelSelector='R')
// place filter input underneath to cover transparent edge pixels
feBlend(in2='SourceGraphic')
// bump up saturation
//feColorMatrix(type='saturate' values='1.125')
// the polygons
.poly
.poly
View Compiled
/* take out of document flow */
svg[height='0'][aria-hidden='true'] { position: fixed }
.poly {
display: inline-block;
width: clamp(8em, 45vw, 50em);
aspect-ratio: 1;
background: var(--b);
background-blend-mode: lighten;
clip-path: polygon(var(--v));
& + & { filter: url(#grain) }
}
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.