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.
Cool idea. I guess it's not too hard if you don't care about performance.
Option 1: Static SVG filters
Thanks to Amaury Hanser.
You can define an svg filter and use it in your css: (see https://stackoverflow.com/a/66625778/6292230)
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)
display: none;to hide the svg as it will break in FirefoxOption 3: Overlay Canvas
Calculation effort: Every DOM change
Without a working example, that's how I would do it:
Render your page to DOM
Render your page to a canvas (see html2canvas: http://html2canvas.hertzen.com or better rasterizeHTML: https://github.com/cburgmer/rasterizeHTML.js)
Overlay the canvas
position: absolute; left: 0; top: 0; width: 100%; z-index: 100;Don't catch clicks on the canvas so the buttons/links on the rendered DOM below will work
pointer-events: none;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.