Error: Attempting to parse an unsupported color function "color"

I'm using html2canvas version 1.4.1. I'm not able to render the canvas properly because of the following error:

Error: Attempting to parse an unsupported color function "color"

Seems like color is not supported, how to fix this?

Solution

There is an open ticket on github to address this issue but still no development has been done.

To fix this, I suggest switching to html2canvas-pro, it's a fork of html2canvas so it has exactly the same api, but it supports all the modern color libraries like color, lab, lch, oklab, oklch.

Alternative #1

I've been dealing with html2canvas color issues, and sometimes switching to a different library isn't an option due to licensing or compatibility concerns. One approach I've found effective is CSS preprocessing to convert modern color functions to supported formats.

Here's a solution using PostCSS with a custom plugin:

// postcss.config.js
module.exports = {
  plugins: [
    require('postcss-color-function'),
    require('postcss-custom-properties'),
    {
      postcssPlugin: 'html2canvas-color-fix',
      Declaration: {
        color: (decl) => {
          if (decl.value.includes('color(')) {
            // Convert color() to rgb() or hex
            decl.value = decl.value.replace(
              /color\(([^)]+)\)/g,
              (match, args) => {
                // Convert to a supported format
                return `rgb(128, 128, 128)`; // Fallback color
              }
            );
          }
        }
      }
    }
  ]
};

Or you can use CSS custom properties with fallbacks:

:root {
  --modern-color: color(display-p3 0.5 0.5 0.5);
  --fallback-color: rgb(128, 128, 128);
}

.element {
  color: var(--fallback-color);
  color: var(--modern-color); /* Modern browsers */
}

This approach maintains modern color support while providing fallbacks for html2canvas.

Alternative #2

Another approach I've used successfully is runtime CSS manipulation before calling html2canvas. This is especially useful when you can't modify your CSS build process.

Here's a solution that temporarily replaces unsupported color functions:

function prepareForHtml2Canvas(element) {
  // Store original styles
  const originalStyles = new Map();
  
  // Find all elements with unsupported color functions
  const elements = element.querySelectorAll('*');
  elements.forEach(el => {
    const computedStyle = window.getComputedStyle(el);
    const color = computedStyle.color;
    const backgroundColor = computedStyle.backgroundColor;
    
    if (color.includes('color(') || backgroundColor.includes('color(')) {
      // Store original
      originalStyles.set(el, {
        color: el.style.color,
        backgroundColor: el.style.backgroundColor
      });
      
      // Replace with supported colors
      if (color.includes('color(')) {
        el.style.color = 'rgb(128, 128, 128)'; // Fallback
      }
      if (backgroundColor.includes('color(')) {
        el.style.backgroundColor = 'rgb(240, 240, 240)'; // Fallback
      }
    }
  });
  
  return originalStyles;
}

function restoreStyles(originalStyles) {
  originalStyles.forEach((styles, element) => {
    if (styles.color) element.style.color = styles.color;
    if (styles.backgroundColor) element.style.backgroundColor = styles.backgroundColor;
  });
}

// Usage
const originalStyles = prepareForHtml2Canvas(document.getElementById('target'));
html2canvas(document.getElementById('target')).then(canvas => {
  restoreStyles(originalStyles);
  // Use canvas
});

This approach is more complex but gives you fine-grained control over color replacement.

Alternative #3

If you're using modern frameworks like React or Vue, you might want to consider alternative screenshot libraries that have better support for modern CSS features.

Here are some alternatives I've used:

dom-to-image (React-friendly):

import domtoimage from 'dom-to-image';

domtoimage.toPng(document.getElementById('target'))
  .then(function (dataUrl) {
    const img = new Image();
    img.src = dataUrl;
    document.body.appendChild(img);
  });

html-to-image (Modern alternative):

import { toPng } from 'html-to-image';

toPng(document.getElementById('target'))
  .then(function (dataUrl) {
    const link = document.createElement('a');
    link.download = 'screenshot.png';
    link.href = dataUrl;
    link.click();
  });

Puppeteer (Server-side rendering):

const puppeteer = require('puppeteer');

async function captureScreenshot(html) {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.setContent(html);
  const screenshot = await page.screenshot();
  await browser.close();
  return screenshot;
}

These alternatives often have better support for modern CSS features and can be more reliable for production use.

Last modified: April 27, 2025
Stay in the loop
Subscribe to our newsletter to get the latest articles delivered to your inbox