niklasvh / html2canvas

Screenshots with JavaScript
https://html2canvas.hertzen.com/
MIT License
30.17k stars 4.75k forks source link

html2canvas captured blank dom(where css style is 'display:-webkit-inline-box') #3070

Open minpuff opened 1 year ago

minpuff commented 1 year ago

Please make sure you are testing with the latest release of html2canvas. Old versions are not supported and issues reported for them will be closed.

Please follow the general troubleshooting steps first:

Bug reports:

html2canvas captured blank dom: where css style is 'display:-webkit-inline-box', when used 'display:inline-flex', is would auto produced by webpack's 'postcss-loader autoprefixed' plugins.

Specifications:

kostetskyroma commented 4 weeks ago

Unfortunately, it seems that the 'flex-inline' property isn't supported by the library, as there's no mention of it in the official documentation (https://html2canvas.hertzen.com/features).

I've managed to do a workaround for handling unsupported styles during html2canvas rendering.

This method replaces certain unsupported CSS styles with supported alternatives to ensure correct rendering. It's used within the html2canvas options to preprocess the document before rendering.

The NOT_SUPPORTED_STYLES map defines CSS properties and their unsupported values along with their corresponding supported alternatives.

const NOT_SUPPORTED_STYLES = new Map([
  ['display', new Map([['inline-flex', 'flex']])],
  ['animation', new Map([['any', 'none 0s ease 0s 1 normal none running']])],
]);
html2canvas(element, {
      width,
      height,
      onclone: (document) => {
        this._replaceUnsupportedStyles(document.body);
        return document;
      },
    })
 private _replaceUnsupportedStyles(element: HTMLElement): void {
    const processUnsupportedStyles = (element: HTMLElement) => {

      Array.from(NOT_SUPPORTED_STYLES.keys()).forEach((property: string) => {
        const unsupportedStyle = NOT_SUPPORTED_STYLES.get(property);
        const originalValue = getComputedStyle(element).getPropertyValue(property);

        if (unsupportedStyle && (unsupportedStyle.has(originalValue) || unsupportedStyle.has('any'))) {
          element.style.setProperty(property, unsupportedStyle.get(originalValue) || unsupportedStyle.get('any') || originalValue);
        }
      });

      Array.from(element.children).forEach((child) => processUnsupportedStyles(child as HTMLElement));
    };

    processUnsupportedStyles(element);
  }