Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Firefox foreignObject background-image canvas rendering bug
<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta http-equiv="Cache-Control" content="no-cache">
<title>Firefox foreignObject background-image canvas rendering bug</title>
td { border: 1px darkblue solid; }
<button id="reproduce">reproduce</button>
<td><img id="src"></td>
<td><canvas id="dst"></canvas></td>
document.body.onload = async () => {
try {
await main();
} catch (e) {
async function main() {
const N = +(^\?/, '')||'0');
document.querySelector('#reproduce').onclick = () => {
window.location = window.location.href.replace(/(\?\d*)?$/, `?${N+1}`);
const image = document.querySelector('#image'),
{width, height} = image.dataset;
let imageUrl = image.innerText.trim();
// Add three dummy zero bytes to the end of png N times to confuse cache.
imageUrl = imageUrl.replace(/=*$/, 'AAAA'.repeat(N) + '$&');
const svg = `
<svg xmlns="" width="${width}" height="${height}">
<foreignObject width="100%" height="100%">
<div xmlns="" style="position: relative;">
<div style="background: url(${imageUrl}); width: ${width}px; height: ${height}px;"></div>
const svgUrl = URL.createObjectURL(new Blob([svg], { type: 'image/svg+xml' }));
const src = document.querySelector('#src');
src.width = width;
src.height = height;
await new Promise((resolve, reject) => {
src.onload = resolve;
src.onerror = reject;
src.src = svgUrl;
const ctx = document.querySelector('#dst').getContext('2d');
ctx.canvas.width = width;
ctx.canvas.height = height;
ctx.drawImage(src, 0, 0);
<script id="image" type="text/plain" data-width="32" data-height="32">
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment