📄 SKILL.md

← Vault

name: lovable-html2canvas-svg-fix

description: Fix SVG elements (QR codes) missing in html2canvas PNG exports on Lovable apps when components remount after state changes

triggers:

- QR code missing in downloaded PNG but visible in preview

- html2canvas capturing blank areas where SVG should be

- layout/theme changes breaking SVG capture in exports


Lovable html2canvas SVG Capture Fix

Problem

In Lovable (or any React app using html2canvas), SVG elements (commonly QR codes) fail to appear in exported PNGs when the parent component has been remounted due to state changes (layout switches, theme toggles, etc.).

Root Cause: html2canvas captures the DOM state, but SVG elements may render differently after React reconciliation, especially when components remount with new keys.

Solution

Convert the SVG to a data URL image BEFORE calling html2canvas. Inject this JavaScript into the page before export:

`javascript

async function fixSVGForCapture(selector) {

const container = document.querySelector(selector);

if (!container) return;

const svg = container.querySelector('svg');

if (!svg) return;

// Get SVG dimensions

const width = parseInt(svg.getAttribute('width')) || 110;

const height = parseInt(svg.getAttribute('height')) || 110;

// Create canvas

const canvas = document.createElement('canvas');

canvas.width = width * 2; // 2x for quality

canvas.height = height * 2;

const ctx = canvas.getContext('2d');

ctx.fillStyle = '#ffffff';

ctx.fillRect(0, 0, canvas.width, canvas.height);

// Serialize SVG and convert to image

const svgData = new XMLSerializer().serializeToString(svg);

const blob = new Blob([svgData], {type: 'image/svg+xml'});

const url = URL.createObjectURL(blob);

await new Promise((resolve, reject) => {

const img = new Image();

img.onload = () => {

ctx.drawImage(img, 0, 0, canvas.width, canvas.height);

URL.revokeObjectURL(url);

resolve();

};

img.onerror = reject;

img.src = url;

});

// Replace SVG with img

const imgEl = document.createElement('img');

imgEl.src = canvas.toDataURL('image/png');

imgEl.style.cssText = 'width:100%;height:100%;display:block;';

container.innerHTML = '';

container.appendChild(imgEl);

}

// Usage before html2canvas:

await fixSVGForCapture('[data-qr-target="true"]');

// Now call html2canvas...

`

When to Use