JSFiddle - React, Tailwind, and code Playground
by RAX7
HTML
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 100 100">
<defs>
<mask id="blur-mask"></mask>
<filter id="blur-filter">
<feGaussianBlur in="SourceGraphic" stdDeviation="2"/>
<feComponentTransfer>
<feFuncA type="discrete" tableValues="1 1"/>
</feComponentTransfer>
</filter>
</defs>
<image
xlink:href="https://images.unsplash.com/photo-1484244233201-29892afe6a2c?ixlib=rb-1.2.1&auto=format&fit=crop&w=750&q=80"
preserveAspectRatio="xMidYMid slice"
height="100%" width="100%"/>
<image
xlink:href="https://images.unsplash.com/photo-1484244233201-29892afe6a2c?ixlib=rb-1.2.1&auto=format&fit=crop&w=750&q=80"
preserveAspectRatio="xMidYMid slice"
height="100%" width="100%"
filter="url(#blur-filter)"
mask="url(#blur-mask)"/>
</svg>
JavaScript
function genMask(w, h) {
const NS = 'http://www.w3.org/2000/svg';
const els = [];
for (let wi = 0; wi < w; wi++) {
for (let hi = 0; hi < h; hi++) {
const rect = document.createElementNS(NS, 'rect');
rect.setAttribute('x', wi * (100 / w) + '%');
rect.setAttribute('y', hi * (100 / h) + '%');
rect.setAttribute('width', (100 / w) + '%');
rect.setAttribute('height', (100 / h) + '%');
rect.setAttribute('fill', '#fff');
rect.setAttribute('stroke', '#fff');
rect.setAttribute('stroke-width', '1');
els.push(rect);
}
}
return els;
}
const mask = document.querySelector('#blur-mask');
const maskParts = genMask(20, 20);
maskParts.forEach(part => mask.appendChild(part));
maskParts.sort(() => Math.random() - 0.5);
let partIndex = 0;
function unblur() {
maskParts[partIndex].setAttribute('fill', '#000');
maskParts[partIndex].setAttribute('stroke', '#000');
partIndex++;
if (partIndex < maskParts.length) {
setTimeout(unblur, 100);
}
}
unblur();