Pixelate a whole webpage
Asked Answered
S

3

6

I understand how to zoom a small canvas to make a big canvas with chunky, rather than blurry, pixels.

Is there any way to make a whole webpage display with chunky 2x2 or 3x3 pixels? i.e. magnify it with a nearest neighbour zoom. I want to use normal HTML but pixelate it for a faux-8-bit look.

Strengthen answered 14/3, 2021 at 12:47 Comment(1)
There is this SO post about pixelating images, but not a whole page with the fonts and everything thats probably not possible. See hereStanchion
C
10

Cool idea. I guess it's not too hard if you don't care about performance.

Edit: I spend a whole day on research, did a bunch of tests and wrote own small examples. These are my results:

Option 1: Static SVG filters

Thanks to Amaury Hanser.

You can define an svg filter and use it in your css: (see https://mcmap.net/q/1610598/-pixelate-a-whole-webpage)

This solution is beautiful in every way.

However, Apple does not like you. Some filters or properties are not supported by Safari on macOS and iOS. For example: When used as css filter, Safari ignores x,y,width,height which renders most solutions useless. If you are in control of the environment (e.g. WebView, Electron, ...) this is the best solution.

Option 2: Dynamic SVG filters

Calculation effort: Once per viewport resize / page load

This should work cross-browser. Tested on latest Safari, Chrome and Firefox (macOS). You can use a similar technique as described in Option 1. However, you must render a dot matrix to an offscreen canvas and inject it into an svg filter. You must redo the calculation everytime the viewport size changes (e.g. after resize event).

Working codesandbox example: https://codesandbox.io/s/pixelate-page-demo-dt6w0?file=/src/index.js (click reload button in right iframe if effect is not showing)

  1. Create an empty svg filter inside your body
<body>
    <svg>
      <filter
        id="pixelate"
        x="0"
        y="0"
        width="700"
        height="900"
        filterUnits="userSpaceOnUse"
      ></filter>
    </svg>
</body>
  1. Dynamically create and inject svg filter like below
function pixelate(tileSize = 10, sigmaGauss = 2) {
  tileSize = tileSize < 1 ? 1 : tileSize;
  sigmaGauss = sigmaGauss < 1 ? 1 : sigmaGauss;

  const canvas = document.createElement("canvas");
  const ctx = canvas.getContext("2d");

  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;

  ctx.fillStyle = "black";
  ctx.fillRect(0, 0, canvas.width, canvas.height);

  // only to make the output visible
  // document.body.appendChild(canvas);

  const rows = canvas.height / tileSize;
  const cols = canvas.width / tileSize;
  for (let r = 0; r < rows; r++) {
    for (let c = 0; c < cols; c++) {
      ctx.fillStyle = "white";

      ctx.fillRect(
        c * tileSize - 1 + Math.floor(tileSize / 2),
        r * tileSize - 1 + Math.floor(tileSize / 2),
        1,
        1
      );
    }
  }

  const pixelate = document.getElementById("pixelate");
  pixelate.innerHTML = "";

  const blur = document.createElementNS(
    "http://www.w3.org/2000/svg",
    "feGaussianBlur"
  );
  blur.setAttribute("in", "SourceGraphic");
  blur.setAttribute("stdDeviation", sigmaGauss);
  blur.setAttribute("result", "blurred");

  const hmap = document.createElementNS(
    "http://www.w3.org/2000/svg",
    "feImage"
  );
  const hmapUrl = canvas.toDataURL();
  hmap.setAttribute("href", hmapUrl);
  hmap.setAttribute("result", "hmap");

  const blend = document.createElementNS(
    "http://www.w3.org/2000/svg",
    "feBlend"
  );
  // blend.setAttribute("mode", "lighten");
  blend.setAttribute("mode", "multiply");
  blend.setAttribute("in", "blurred");
  blend.setAttribute("in2", "hmap");

  const morph = document.createElementNS(
    "http://www.w3.org/2000/svg",
    "feMorphology"
  );
  morph.setAttribute("operator", "dilate");
  morph.setAttribute("radius", tileSize / 2);

  pixelate.setAttribute("width", canvas.width);
  pixelate.setAttribute("height", canvas.height);
  pixelate.appendChild(blur);
  pixelate.appendChild(hmap);
  pixelate.appendChild(blend);
  pixelate.appendChild(morph);
}
  1. After page load / viewport resize call
pixelate(5, 1); // 5 = tileSize, 1 = std deviation gaussian blur
  1. Add css. Hint: do not use display: none; to hide the svg as it will break in Firefox
html {
  filter: url(#pixelate);
}

svg {
  position: absolute;
  height: 0;
}

Option 3: Overlay Canvas

Calculation effort: Every DOM change

Without a working example, that's how I would do it:

  1. Render your page to DOM

  2. Render your page to a canvas (see html2canvas: http://html2canvas.hertzen.com or better rasterizeHTML: https://github.com/cburgmer/rasterizeHTML.js)

  3. Overlay the canvas position: absolute; left: 0; top: 0; width: 100%; z-index: 100;

  4. Don't catch clicks on the canvas so the buttons/links on the rendered DOM below will work pointer-events: none;

  5. Scale your canvas without image smoothing (see here: How to pixelate an image with canvas and javascript)

Try to prevent dynamic rerenders for optimal performance.

Option 4: WebGL Shader

Calculation effort: Every frame

The coolest method by far is to render your website via WebGL and use a shader to create the desired effect.

  • You can extend Option 3, render a fullsize canvas (keep in mind to render double size for retina devices), grab the WebGl context and attach a shader
  • Alternatively you could use HTML GL (http://htmlgl.com/). I wouldn't recommend it because it seems to be unmaintained and also does not support retina devices (=> therefore everything will be blurry)
Cramfull answered 14/3, 2021 at 13:5 Comment(3)
That's a lot of info, thanks. Methods 2 seems heavy on the computer, but it's so cool to adjust the two arguments as easy as that! You gave me a lot to read!Hemia
@AmauryHanser In fact, option 2 is more performant than option 3 and 4. The reason why it's fairly performant is, that the "holemap" only has to be calculated once (+ viewport resize) and not for every dom change (option 3) or every frame (option 4).Cramfull
Oh right, I had misread viewport size change. Again, congrats for your research!Hemia
H
6

You can use an svg filter for that.

Please note this solution isn't cross-browser.
As @adroste said, it won't work on Safari (Mac/iOS) or older browsers.

You'll need to tweak it to make it look the way you want, but here is a quick example:

html { filter: url("#pixelate") }
svg { display: block }
h1 { color: red }
h2 { color: blue}
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="0" height="0">
  <defs>
    <filter id="pixelate" x="0" y="0">
      <feFlood x="2" y="2" height="1" width="1"/> 
      <feComposite width="5" height="5"/>
      <feTile result="a"/>
      <feComposite in="SourceGraphic" in2="a" 
                   operator="in"/>
      <feMorphology operator="dilate"
                    radius="2.5"/>
    </filter>
  </defs>
</svg>    
<h1>
  Lorem ipsum, dolor sit amet consectetur adipisicing elit.
</h1>
<h2>
  Lorem ipsum dolor sit amet consectetur adipisicing elit. Reprehenderit, fuga.
</h2>
<p>
  Lorem ipsum, dolor sit amet consectetur adipisicing elit. Doloribus dolorem, maxime recusandae modi adipisci, praesentium qui aliquam consequatur tempore fugiat quasi minus necessitatibus excepturi enim sapiente quibusdam deleniti perferendis quisquam?
</p>

You can probably achieve this effect with different filters.
You can learn more about svf filter on MDN docs.

Hemia answered 14/3, 2021 at 14:41 Comment(8)
Great solution, but does not work in Safari (Mac/iOS) or older browsersCramfull
You're right @adroste, I'll add it to the answer. Do you know exactly what is unsupported? From caniuse, svg filters are supported, so a guess it's something else?Hemia
I don't know. I'll try to find out what breaks. I could try to replace your solution with a convolution + displacement matrix.Cramfull
Seems like flood and composite filter have problems when using the url syntax in safari. Maybe it'll work inline, but it behaves weird outside of svg. Safari is really annoying.Cramfull
I have to admit that I'm no expert in svg filters. If you find a better solution, I'll happily upvote it to gain in traction.Hemia
I tried differente approaches in the last hour and sadly, svg filters don't work reliable in Safari. Safari straight up ignores x,y,width,height when used as css filter. Therefore I wrote a helper that generates a displacement map in the right size of the base dom element and used it in combination with different other filters. However, Safari's rendering is faulty ... I'll update my answerCramfull
I found a solution, but it was hard to achieve. Please have a look at my updated answer.Cramfull
Also doesn't work in FirefoxSessler
A
0

Furthering Amaury Hanser's answer: You can still use an SVG filter to achieve this.

BUT there is mixed support that will probably improve over the years:

image showing pixelation effect

<svg>
  <filter id="pixelateStr4" x="0" y="0" width="100%" height="100%">

    <!-- First layer: Normal pixelation effect-->
    <feflood x="1" y="1" height="1" width="1"></feflood>
    <fecomposite id="composite" in2="SourceGraphic" operator="in" width="16" height="16"></fecomposite>
    <fetile result="tiled"></fetile>
    <fecomposite in="SourceGraphic" in2="tiled" operator="in"></fecomposite>
    <femorphology id="morphology" operator="dilate" radius="8" result="dilatedPixelation"></femorphology>

    <!-- Second layer: Fallback with full-width tiling-->
    <feflood x="1" y="1" height="1" width="1" result="floodFallbackX"></feflood>
    <fecomposite id="compositeX" in2="SourceGraphic" operator="in" width="8" height="16"></fecomposite>
    <fetile result="fullTileX"></fetile>
    <fecomposite in="SourceGraphic" in2="fullTileX" operator="in"></fecomposite>
    <femorphology id="morphologyX" operator="dilate" radius="8" result="dilatedFallbackX"></femorphology>

    <!-- Third layer: Fallback with full-height tiling-->
    <feflood x="1" y="1" height="1" width="1"></feflood>
    <fecomposite id="compositeY" in2="SourceGraphic" operator="in" width="16" height="8"></fecomposite>
    <fetile result="fullTileY"></fetile>
    <fecomposite in="SourceGraphic" in2="fullTileY" operator="in"></fecomposite>
    <femorphology id="morphologyY" operator="dilate" radius="8" result="dilatedFallbackY"></femorphology>

    <!-- Combine all three layers-->
    <femerge>
      <femergenode in="dilatedFallbackX"></femergenode>
      <femergenode in="dilatedFallbackY"></femergenode>
      <femergenode in="dilatedPixelation"></femergenode>
    </femerge>
  </filter>
</svg>

and apply it to an overlay with CSS

.overlay{
    backdrop-filter: url(#pixelateStr3);
}

Below is the full snippet

.imgAni {
  -webkit-animation: pixelAni 5s;
          animation: pixelAni 5s;
}
.img1 {
  -webkit-backdrop-filter: url("#pixelateStr1");
          backdrop-filter: url("#pixelateStr1");
}
.img2 {
  -webkit-backdrop-filter: url("#pixelateStr2");
          backdrop-filter: url("#pixelateStr2");
}
.img3 {
  -webkit-backdrop-filter: url("#pixelateStr3");
          backdrop-filter: url("#pixelateStr3");
}
.img4 {
  -webkit-backdrop-filter: url("#pixelateStr4");
          backdrop-filter: url("#pixelateStr4");
}
.img5 {
  -webkit-backdrop-filter: url("#pixelateStr5");
          backdrop-filter: url("#pixelateStr5");
}
.img6 {
  -webkit-backdrop-filter: url("#pixelateStr6");
          backdrop-filter: url("#pixelateStr6");
}
.img7 {
  -webkit-backdrop-filter: url("#pixelateStr7");
          backdrop-filter: url("#pixelateStr7");
}
.filter {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 3;
  pointer-events: none;
}
.content {
  position: relative;
  width: 25vw;
  height: 50vh;
  float: left;
  background: #ff0;
}
.content h1 {
  font-size: 4.5vw;
  padding: 2vw;
  z-index: 2;
  position: relative;
  color: #00f;
  font-family: monospace;
  margin: 0;
}
.content span {
  background: #f00;
  border-radius: 50%;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 50%;
  height: 50%;
  z-index: 1;
}
@-webkit-keyframes pixelAni {
  99.9% {
    -webkit-backdrop-filter: url("#pixelateAni");
            backdrop-filter: url("#pixelateAni");
  }
}
@keyframes pixelAni {
  99.9% {
    -webkit-backdrop-filter: url("#pixelateAni");
            backdrop-filter: url("#pixelateAni");
  }
}


html,body{padding:0;margin:0;}
<div class="content">
  <div class="filter imgAni"></div>
  <h1 contenteditable="true">HOW Pixel ATED?</h1><span></span>
</div>
<div class="content">
  <div class="filter img1"></div>
  <h1 contenteditable="true">HOW Pixel ATED?</h1><span></span>
</div>
<div class="content">
  <div class="filter img2"></div>
  <h1 contenteditable="true">HOW Pixel ATED?</h1><span></span>
</div>
<div class="content">
  <div class="filter img3"></div>
  <h1 contenteditable="true">HOW Pixel ATED?</h1><span></span>
</div>
<div class="content">
  <div class="filter img4"></div>
  <h1 contenteditable="true">HOW Pixel ATED?</h1><span></span>
</div>
<div class="content">
  <div class="filter img5"></div>
  <h1 contenteditable="true">HOW Pixel ATED?</h1><span></span>
</div>
<div class="content">
  <div class="filter img6"></div>
  <h1 contenteditable="true">HOW Pixel ATED?</h1><span></span>
</div>
<div class="content">
  <div class="filter img7"></div>
  <h1 contenteditable="true">HOW Pixel ATED?</h1><span></span>
</div>
<svg>
  <filter id="pixelateAni" x="0" y="0" width="100%" height="100%">
    <!-- First layer: Normal pixelation effect-->
    <feflood x="1" y="1" height="1" width="1"></feflood>
    <fecomposite id="composite" in2="SourceGraphic" operator="in" width="2" height="2"></fecomposite>
    <fetile result="tiled"></fetile>
    <fecomposite in="SourceGraphic" in2="tiled" operator="in"></fecomposite>
    <femorphology id="morphology" operator="dilate" radius="1" result="dilatedPixelation"></femorphology>
    <!-- Second layer: Fallback with full-width tiling-->
    <feflood x="1" y="1" height="1" width="1" result="floodFallbackX"></feflood>
    <fecomposite id="compositeX" in2="SourceGraphic" operator="in" width="1" height="2"></fecomposite>
    <fetile result="fullTileX"></fetile>
    <fecomposite in="SourceGraphic" in2="fullTileX" operator="in"></fecomposite>
    <femorphology id="morphologyX" operator="dilate" radius="1" result="dilatedFallbackX"></femorphology>
    <!-- Third layer: Fallback with full-height tiling-->
    <feflood x="1" y="1" height="1" width="1"></feflood>
    <fecomposite id="compositeY" in2="SourceGraphic" operator="in" width="2" height="1"></fecomposite>
    <fetile result="fullTileY"></fetile>
    <fecomposite in="SourceGraphic" in2="fullTileY" operator="in"></fecomposite>
    <femorphology id="morphologyY" operator="dilate" radius="1" result="dilatedFallbackY"></femorphology>
    <animate calcmode="discrete" xlink:href="#composite" attributename="width" values="128; 64; 32; 16; 8; 4; 2" dur="5s" fill="freeze" repeatcount="once"></animate>
    <animate calcmode="discrete" xlink:href="#composite" attributename="height" values="128; 64; 32; 16; 8; 4; 2" dur="5s" fill="freeze" repeatcount="once"></animate>
    <animate calcmode="discrete" xlink:href="#morphology" attributename="radius" values="64; 32; 16; 8; 4; 2; 1" dur="5s" fill="freeze" repeatcount="once"></animate>
    <animate calcmode="discrete" xlink:href="#compositeX" attributename="width" values="64; 32; 16; 8; 4; 2; 1" dur="5s" fill="freeze" repeatcount="once"></animate>
    <animate calcmode="discrete" xlink:href="#compositeX" attributename="height" values="128; 64; 32; 16; 8; 4; 2" dur="5s" fill="freeze" repeatcount="once"></animate>
    <animate calcmode="discrete" xlink:href="#morphologyX" attributename="radius" values="64; 32; 16; 8; 4; 2; 1" dur="5s" fill="freeze" repeatcount="once"></animate>
    <animate calcmode="discrete" xlink:href="#compositeY" attributename="width" values="128; 64; 32; 16; 8; 4; 2" dur="5s" fill="freeze" repeatcount="once"></animate>
    <animate calcmode="discrete" xlink:href="#compositeY" attributename="height" values="64; 32; 16; 8; 4; 2; 1" dur="5s" fill="freeze" repeatcount="once"></animate>
    <animate calcmode="discrete" xlink:href="#morphologyY" attributename="radius" values="64; 32; 16; 8; 4; 2; 1" dur="5s" fill="freeze" repeatcount="once"></animate>
    <!-- Combine all three layers-->
    <femerge>
      <femergenode in="dilatedFallbackX"></femergenode>
      <femergenode in="dilatedFallbackY"></femergenode>
      <femergenode in="dilatedPixelation"></femergenode>
    </femerge>
  </filter>
  <filter id="pixelateStr7" x="0" y="0" width="100%" height="100%">
    <!-- First layer: Normal pixelation effect-->
    <feflood x="1" y="1" height="1" width="1"></feflood>
    <fecomposite id="composite" in2="SourceGraphic" operator="in" width="128" height="128"></fecomposite>
    <fetile result="tiled"></fetile>
    <fecomposite in="SourceGraphic" in2="tiled" operator="in"></fecomposite>
    <femorphology id="morphology" operator="dilate" radius="64" result="dilatedPixelation"></femorphology>
    <!-- Second layer: Fallback with full-width tiling-->
    <feflood x="1" y="1" height="1" width="1" result="floodFallbackX"></feflood>
    <fecomposite id="compositeX" in2="SourceGraphic" operator="in" width="64" height="128"></fecomposite>
    <fetile result="fullTileX"></fetile>
    <fecomposite in="SourceGraphic" in2="fullTileX" operator="in"></fecomposite>
    <femorphology id="morphologyX" operator="dilate" radius="64" result="dilatedFallbackX"></femorphology>
    <!-- Third layer: Fallback with full-height tiling-->
    <feflood x="1" y="1" height="1" width="1"></feflood>
    <fecomposite id="compositeY" in2="SourceGraphic" operator="in" width="128" height="64"></fecomposite>
    <fetile result="fullTileY"></fetile>
    <fecomposite in="SourceGraphic" in2="fullTileY" operator="in"></fecomposite>
    <femorphology id="morphologyY" operator="dilate" radius="64" result="dilatedFallbackY"></femorphology>
    <!-- Combine all three layers-->
    <femerge>
      <femergenode in="dilatedFallbackX"></femergenode>
      <femergenode in="dilatedFallbackY"></femergenode>
      <femergenode in="dilatedPixelation"></femergenode>
    </femerge>
  </filter>
  <filter id="pixelateStr6" x="0" y="0" width="100%" height="100%">
    <!-- First layer: Normal pixelation effect-->
    <feflood x="1" y="1" height="1" width="1"></feflood>
    <fecomposite id="composite" in2="SourceGraphic" operator="in" width="64" height="64"></fecomposite>
    <fetile result="tiled"></fetile>
    <fecomposite in="SourceGraphic" in2="tiled" operator="in"></fecomposite>
    <femorphology id="morphology" operator="dilate" radius="32" result="dilatedPixelation"></femorphology>
    <!-- Second layer: Fallback with full-width tiling-->
    <feflood x="1" y="1" height="1" width="1" result="floodFallbackX"></feflood>
    <fecomposite id="compositeX" in2="SourceGraphic" operator="in" width="32" height="64"></fecomposite>
    <fetile result="fullTileX"></fetile>
    <fecomposite in="SourceGraphic" in2="fullTileX" operator="in"></fecomposite>
    <femorphology id="morphologyX" operator="dilate" radius="32" result="dilatedFallbackX"></femorphology>
    <!-- Third layer: Fallback with full-height tiling-->
    <feflood x="1" y="1" height="1" width="1"></feflood>
    <fecomposite id="compositeY" in2="SourceGraphic" operator="in" width="64" height="32"></fecomposite>
    <fetile result="fullTileY"></fetile>
    <fecomposite in="SourceGraphic" in2="fullTileY" operator="in"></fecomposite>
    <femorphology id="morphologyY" operator="dilate" radius="32" result="dilatedFallbackY"></femorphology>
    <!-- Combine all three layers-->
    <femerge>
      <femergenode in="dilatedFallbackX"></femergenode>
      <femergenode in="dilatedFallbackY"></femergenode>
      <femergenode in="dilatedPixelation"></femergenode>
    </femerge>
  </filter>
  <filter id="pixelateStr5" x="0" y="0" width="100%" height="100%">
    <!-- First layer: Normal pixelation effect-->
    <feflood x="1" y="1" height="1" width="1"></feflood>
    <fecomposite id="composite" in2="SourceGraphic" operator="in" width="32" height="32"></fecomposite>
    <fetile result="tiled"></fetile>
    <fecomposite in="SourceGraphic" in2="tiled" operator="in"></fecomposite>
    <femorphology id="morphology" operator="dilate" radius="16" result="dilatedPixelation"></femorphology>
    <!-- Second layer: Fallback with full-width tiling-->
    <feflood x="1" y="1" height="1" width="1" result="floodFallbackX"></feflood>
    <fecomposite id="compositeX" in2="SourceGraphic" operator="in" width="16" height="32"></fecomposite>
    <fetile result="fullTileX"></fetile>
    <fecomposite in="SourceGraphic" in2="fullTileX" operator="in"></fecomposite>
    <femorphology id="morphologyX" operator="dilate" radius="16" result="dilatedFallbackX"></femorphology>
    <!-- Third layer: Fallback with full-height tiling-->
    <feflood x="1" y="1" height="1" width="1"></feflood>
    <fecomposite id="compositeY" in2="SourceGraphic" operator="in" width="32" height="16"></fecomposite>
    <fetile result="fullTileY"></fetile>
    <fecomposite in="SourceGraphic" in2="fullTileY" operator="in"></fecomposite>
    <femorphology id="morphologyY" operator="dilate" radius="16" result="dilatedFallbackY"></femorphology>
    <!-- Combine all three layers-->
    <femerge>
      <femergenode in="dilatedFallbackX"></femergenode>
      <femergenode in="dilatedFallbackY"></femergenode>
      <femergenode in="dilatedPixelation"></femergenode>
    </femerge>
  </filter>
  <filter id="pixelateStr4" x="0" y="0" width="100%" height="100%">
    <!-- First layer: Normal pixelation effect-->
    <feflood x="1" y="1" height="1" width="1"></feflood>
    <fecomposite id="composite" in2="SourceGraphic" operator="in" width="16" height="16"></fecomposite>
    <fetile result="tiled"></fetile>
    <fecomposite in="SourceGraphic" in2="tiled" operator="in"></fecomposite>
    <femorphology id="morphology" operator="dilate" radius="8" result="dilatedPixelation"></femorphology>
    <!-- Second layer: Fallback with full-width tiling-->
    <feflood x="1" y="1" height="1" width="1" result="floodFallbackX"></feflood>
    <fecomposite id="compositeX" in2="SourceGraphic" operator="in" width="8" height="16"></fecomposite>
    <fetile result="fullTileX"></fetile>
    <fecomposite in="SourceGraphic" in2="fullTileX" operator="in"></fecomposite>
    <femorphology id="morphologyX" operator="dilate" radius="8" result="dilatedFallbackX"></femorphology>
    <!-- Third layer: Fallback with full-height tiling-->
    <feflood x="1" y="1" height="1" width="1"></feflood>
    <fecomposite id="compositeY" in2="SourceGraphic" operator="in" width="16" height="8"></fecomposite>
    <fetile result="fullTileY"></fetile>
    <fecomposite in="SourceGraphic" in2="fullTileY" operator="in"></fecomposite>
    <femorphology id="morphologyY" operator="dilate" radius="8" result="dilatedFallbackY"></femorphology>
    <!-- Combine all three layers-->
    <femerge>
      <femergenode in="dilatedFallbackX"></femergenode>
      <femergenode in="dilatedFallbackY"></femergenode>
      <femergenode in="dilatedPixelation"></femergenode>
    </femerge>
  </filter>
  <filter id="pixelateStr3" x="0" y="0" width="100%" height="100%">
    <!-- First layer: Normal pixelation effect-->
    <feflood x="1" y="1" height="1" width="1"></feflood>
    <fecomposite id="composite" in2="SourceGraphic" operator="in" width="8" height="8"></fecomposite>
    <fetile result="tiled"></fetile>
    <fecomposite in="SourceGraphic" in2="tiled" operator="in"></fecomposite>
    <femorphology id="morphology" operator="dilate" radius="4" result="dilatedPixelation"></femorphology>
    <!-- Second layer: Fallback with full-width tiling-->
    <feflood x="1" y="1" height="1" width="1" result="floodFallbackX"></feflood>
    <fecomposite id="compositeX" in2="SourceGraphic" operator="in" width="4" height="8"></fecomposite>
    <fetile result="fullTileX"></fetile>
    <fecomposite in="SourceGraphic" in2="fullTileX" operator="in"></fecomposite>
    <femorphology id="morphologyX" operator="dilate" radius="4" result="dilatedFallbackX"></femorphology>
    <!-- Third layer: Fallback with full-height tiling-->
    <feflood x="1" y="1" height="1" width="1"></feflood>
    <fecomposite id="compositeY" in2="SourceGraphic" operator="in" width="8" height="4"></fecomposite>
    <fetile result="fullTileY"></fetile>
    <fecomposite in="SourceGraphic" in2="fullTileY" operator="in"></fecomposite>
    <femorphology id="morphologyY" operator="dilate" radius="4" result="dilatedFallbackY"></femorphology>
    <!-- Combine all three layers-->
    <femerge>
      <femergenode in="dilatedFallbackX"></femergenode>
      <femergenode in="dilatedFallbackY"></femergenode>
      <femergenode in="dilatedPixelation"></femergenode>
    </femerge>
  </filter>
  <filter id="pixelateStr2" x="0" y="0" width="100%" height="100%">
    <!-- First layer: Normal pixelation effect-->
    <feflood x="1" y="1" height="1" width="1"></feflood>
    <fecomposite id="composite" in2="SourceGraphic" operator="in" width="4" height="4"></fecomposite>
    <fetile result="tiled"></fetile>
    <fecomposite in="SourceGraphic" in2="tiled" operator="in"></fecomposite>
    <femorphology id="morphology" operator="dilate" radius="2" result="dilatedPixelation"></femorphology>
    <!-- Second layer: Fallback with full-width tiling-->
    <feflood x="1" y="1" height="1" width="1" result="floodFallbackX"></feflood>
    <fecomposite id="compositeX" in2="SourceGraphic" operator="in" width="2" height="4"></fecomposite>
    <fetile result="fullTileX"></fetile>
    <fecomposite in="SourceGraphic" in2="fullTileX" operator="in"></fecomposite>
    <femorphology id="morphologyX" operator="dilate" radius="2" result="dilatedFallbackX"></femorphology>
    <!-- Third layer: Fallback with full-height tiling-->
    <feflood x="1" y="1" height="1" width="1"></feflood>
    <fecomposite id="compositeY" in2="SourceGraphic" operator="in" width="4" height="2"></fecomposite>
    <fetile result="fullTileY"></fetile>
    <fecomposite in="SourceGraphic" in2="fullTileY" operator="in"></fecomposite>
    <femorphology id="morphologyY" operator="dilate" radius="2" result="dilatedFallbackY"></femorphology>
    <!-- Combine all three layers-->
    <femerge>
      <femergenode in="dilatedFallbackX"></femergenode>
      <femergenode in="dilatedFallbackY"></femergenode>
      <femergenode in="dilatedPixelation"></femergenode>
    </femerge>
  </filter>
  <filter id="pixelateStr1" x="0" y="0" width="100%" height="100%">
    <!-- First layer: Normal pixelation effect-->
    <feflood x="1" y="1" height="1" width="1"></feflood>
    <fecomposite id="composite" in2="SourceGraphic" operator="in" width="2" height="2"></fecomposite>
    <fetile result="tiled"></fetile>
    <fecomposite in="SourceGraphic" in2="tiled" operator="in"></fecomposite>
    <femorphology id="morphology" operator="dilate" radius="1" result="dilatedPixelation"></femorphology>
    <!-- Second layer: Fallback with full-width tiling-->
    <feflood x="1" y="1" height="1" width="1" result="floodFallbackX"></feflood>
    <fecomposite id="compositeX" in2="SourceGraphic" operator="in" width="1" height="2"></fecomposite>
    <fetile result="fullTileX"></fetile>
    <fecomposite in="SourceGraphic" in2="fullTileX" operator="in"></fecomposite>
    <femorphology id="morphologyX" operator="dilate" radius="1" result="dilatedFallbackX"></femorphology>
    <!-- Third layer: Fallback with full-height tiling-->
    <feflood x="1" y="1" height="1" width="1"></feflood>
    <fecomposite id="compositeY" in2="SourceGraphic" operator="in" width="2" height="1"></fecomposite>
    <fetile result="fullTileY"></fetile>
    <fecomposite in="SourceGraphic" in2="fullTileY" operator="in"></fecomposite>
    <femorphology id="morphologyY" operator="dilate" radius="1" result="dilatedFallbackY"></femorphology>
    <!-- Combine all three layers-->
    <femerge>
      <femergenode in="dilatedFallbackX"></femergenode>
      <femergenode in="dilatedFallbackY"></femergenode>
      <femergenode in="dilatedPixelation"></femergenode>
    </femerge>
  </filter>
</svg>

Here is a codepen showing this in practice (https://codepen.io/QuiteQuinn/pen/KKOVvrN)

Altheaalthee answered 1/10 at 20:23 Comment(5)
Doesn't work in FirefoxSessler
Also please stop spamming the place with repeated answers; if a question is a duplicate, flag it for closure as such.Sessler
@Sessler I've wondered about this. The earlier questions that this is a duplicate of don't have upvotes, which might explain why I couldn't find them when I tried to flag them. I even gave them my upvote to try to change it. In this case, should I flag the earlier questions as duplicates of this question even though this question came after them?Altheaalthee
The best duplicate target is usually based on number/quality of answers, view count, and votes. The idea is to send users to the best answers, so when the question was asked isn't that important. Do keep in mind that mods have automated scripts that check for repeated posting of the same/similar content over a short time and will take action to remove it eventually.Sessler
ok thanks, the more you knowAltheaalthee

© 2022 - 2024 — McMap. All rights reserved.