1904labs / dom-to-image-more

Generates an image from a DOM node using HTML5 canvas

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Adding extra border when copying default styles using TailwindCSS

AndoniZubimendi opened this issue · comments

Use case: description, code

In the latests versions of the library (version 2.9.5 is the last one working fine) there seems to be a problem when copying the default styles when using Tailwind CSS. It is adding a border to all the divs.

I am guessing that Tailwind CSS is resetting the styles to have no borders, and the library is using the browser default styles.

Expected behavior

This is an image I get from version 2.9.5 of this library

Captura de Pantalla 2023-01-24 a la(s) 11 02 51

Actual behavior (stack traces, console logs etc)

This is an image I get from the latest version (2.14.0) of this library

Captura de Pantalla 2023-01-24 a la(s) 11 02 25

Temporary solution I am using

I am using this patch to be able to disable the copying of default styles. Not being the best solution, this fixes my problem.

--- dom-to-image-more.original/src/dom-to-image-more.js	2023-01-24 10:34:05.000000000 -0300
+++ dom-to-image-more/src/dom-to-image-more.js	2023-01-24 11:00:03.000000000 -0300
@@ -8,6 +8,7 @@

     // Default impl options
     const defaultOptions = {
+        copyDefaultStyles: true,
         // Default is to fail on error, no placeholder
         imagePlaceholder: undefined,
         // Default cache bust is false, it will use the cache
@@ -175,6 +176,12 @@

     function copyOptions(options) {
         // Copy options to impl options for use in impl
+        if (typeof (options.copyDefaultStyles) === 'undefined') {
+            domtoimage.impl.options.copyDefaultStyles = defaultOptions.copyDefaultStyles;
+        } else {
+            domtoimage.impl.options.copyDefaultStyles = options.copyDefaultStyles;
+        }
+
         if (typeof (options.imagePlaceholder) === 'undefined') {
             domtoimage.impl.options.imagePlaceholder = defaultOptions.imagePlaceholder;
         } else {
@@ -936,6 +943,10 @@
     let tagNameDefaultStyles = {};

     function getDefaultStyle(tagName) {
+        if (!domtoimage.impl.options.copyDefaultStyles) {
+            return {};
+        }
+
         if (tagNameDefaultStyles[tagName]) {
             return tagNameDefaultStyles[tagName];
         }

Library version

  • TailwindCSS 3.2
  • dom-to-image-more 2.14.0 (latest)

Browsers

  • Chrome 109.0.+ (MacOS and GNU/Linux)

Hi!

Just tried master (last commit: bbc2b62) and the result is the same. The border is still present.

i have the same problem, and I can not implement the solution you provide, any other alternatives?

Recently a pull request was accepted that includes the option to disable copying the default styles. I think it is currently only on main branch, but will be part of the next 3.x release.

Thanks for you change... I would ALSO like to track down the origin of the bug... do you have an HTML+CSS example I can base a repro test on?

I will try to make a basic example that show the problem. I will provide it here when I have it.

https://github.com/1904labs/dom-to-image-more/pull/114/files Tried this option with 3.0.3-rc.0 and still have the border.

I will try to make a basic example that show the problem. I will provide it here when I have it.

I have started to make a test with minimal HTML / CSS that I think it reproduces the problem.

It is in https://github.com/AndoniZubimendi/dom-to-image-more/tree/default-style-test

I do not know how to generate the expected control-image, so I can't really test. I am in need for help to make the test. Any help or some rosource to read would be helpful.

Looks like the SVG is being cloned perfectly... (e.g. the output of the toSvg call completely matches the input in appearance) so something on the rendering out to the image is broken.
image

Much churn later have tracked down the issue to this block not being applied at the geneation of the PNG from the properly-cloned SVG

*, :after, :before {
    border: 0 solid #e5e7eb;
    box-sizing: border-box
}

Looks identical (and wrong) if you deselect that rule on the Chrome inspector
image

Great, you find the cause of the problem. Would you like to rename the name of the issue to something more specific?

Tell me if I can help with anything.

I changed that wildcard to set border-style: none and it's working fine. Can you change your theme to match?

*, :after, :before {
    border-style: none;
    border-color: #e5e7eb;
    box-sizing: border-box
}

Here's a jsfiddle showing the resolution (and test) against unchanged 3.0.3-rc.0. In the CSS to the right, you can comment out the line following /* works */ and uncomment the block above to reproduce the original bug.

Looks like the issue is that when the border-style: solid is in effect, even with a border-width of 0, the generation of the image from the (properly cloned) SVG causes the image rendering to insert border-width: auto which makes the border appear. I suspect this is a Chrome oddity, but you can work around it by using the snippet shown instead.

I've released 3.0.3-rc.1 which has this test embedded (with the fix noted). Thanks for the report and repro @AndoniZubimendi

Closing this as there's really nothing to fix.

commented

hi @IDisposable this issue is still persistant, and using your solution removes all borders which isn't good