Html2canvas: Returns a blank image for any element when the document body is more than 30,000px tall.

Created on 31 May 2016  ·  16Comments  ·  Source: niklasvh/html2canvas

The library returns an empty image when the body of the document is more than 30,000px. You would try to capture an element of 100 x 100. But you get a blank image of the element is on a tall body.

Here is a fiddle which demonstrate this error.

https://jsfiddle.net/fvo1xh8b/2/

You can change the body size less than 30,000 and it works fine.

Needs More Information

Most helpful comment

@niklasvh This is a tough one but it is in fact due to the limitations of canvas size. I think this needs opened again to discuss how to implement the right behaviors. Definitely a white washed image isn't the correct behavior.

  • Default the max width/height to browser's requirements for canvas
  • Divide and conquer using multiple canvas elements and return an array.
  • Throw an error in the console advising on the canvas limitations and suggest ways to implement it.

In my case I am cloning the entire body and just set the max width/height: html2canvas(el, {height: 3000, width: 3000}).

All 16 comments

I have the exact same issue as you. Have you found any solution to this?

emm,i got the same problem, but finally, i figure out!
in my case, here is my solution:
put an iframe in you body element, like

<html>
  <head>
  #canvas_handler {
   position:absolute;
   left: -10000px;
  }
  </head>
  <body>
  <iframe id="canvas_handler" />
  </body>
</html>

and every element you need to covert to canvas, you can copy and put them in this iframe, and use html2canvas, and then remove it, like this

const copy_ele = origin_ele.cloneNode(true);
canvas_handler.appendChild(copy_ele);
canvas_handler.style.height = origin_ele.scrollHeight;
canvas_handler.style.width = origin_ele.scrollWidth;
html2canvas(copy_ele, {
      useCORS: true,
     }).then((canvas) => {
       // do your things
     });
canvas_handler.removeChild(table_ele);

Is this still an issue with v1.0.0? If so, could you please share an example on jsfiddle.

This issue has been automatically closed because there has been no response to our request for more information from the original author. With only the information that is currently in the issue, we don't have enough information to take action. Please reach out if you have or find the answers we need so that we can investigate further.

hi when i try to screen an iframe with internal ip camera, it return a void image, please can you help me?

@niklasvh This is a tough one but it is in fact due to the limitations of canvas size. I think this needs opened again to discuss how to implement the right behaviors. Definitely a white washed image isn't the correct behavior.

  • Default the max width/height to browser's requirements for canvas
  • Divide and conquer using multiple canvas elements and return an array.
  • Throw an error in the console advising on the canvas limitations and suggest ways to implement it.

In my case I am cloning the entire body and just set the max width/height: html2canvas(el, {height: 3000, width: 3000}).

@toadkicker brother, u save my code/job today hahahahahahahaht thanks a lot

@toadkicker Thanks !

emm,i got the same problem, but finally, i figure out!
in my case, here is my solution:
put an iframe in you body element, like

<html>
  <head>
  #canvas_handler {
   position:absolute;
   left: -10000px;
  }
  </head>
  <body>
  <iframe id="canvas_handler" />
  </body>
</html>

and every element you need to covert to canvas, you can copy and put them in this iframe, and use html2canvas, and then remove it, like this

const copy_ele = origin_ele.cloneNode(true);
canvas_handler.appendChild(copy_ele);
canvas_handler.style.height = origin_ele.scrollHeight;
canvas_handler.style.width = origin_ele.scrollWidth;
html2canvas(copy_ele, {
      useCORS: true,
     }).then((canvas) => {
       // do your things
     });
canvas_handler.removeChild(table_ele);

I tried this method, but not work exactly. In my way, will work with code below:

const copy_ele = origin_ele.cloneNode(true);
canvas_handler.contentDocument.body.appendChild(copy_ele);
canvas_handler.height = origin_ele.scrollHeight;
canvas_handler.width = origin_ele.scrollWidth;
html2canvas(canvas_handler.contentDocument.body, {
  useCORS: true,
}).then((canvas) => {
  // do your things
  canvas_handler.removeChild(copy_ele);
});

And if you want to apply your css style the same as it in current document, you also need to copy style to iframe:

// add style
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = 'your_style_file_url.css';
canvas_handler.contentDocument.head.appendChild(link);

const copy_ele = origin_ele.cloneNode(true);
canvas_handler.contentDocument.body.appendChild(copy_ele);
canvas_handler.height = origin_ele.scrollHeight;
canvas_handler.width = origin_ele.scrollWidth;
html2canvas(canvas_handler.contentDocument.body, {
  useCORS: true,
}).then((canvas) => {
  // do your things
  canvas_handler.removeChild(copy_ele);
});

Again this is a limitation in the browser itself and this library does not handle the error correctly. No coding solution besides limiting the number of pixels captured will change it.

emm,i got the same problem, but finally, i figure out!
in my case, here is my solution:
put an iframe in you body element, like

<html>
  <head>
  #canvas_handler {
   position:absolute;
   left: -10000px;
  }
  </head>
  <body>
  <iframe id="canvas_handler" />
  </body>
</html>

and every element you need to covert to canvas, you can copy and put them in this iframe, and use html2canvas, and then remove it, like this

const copy_ele = origin_ele.cloneNode(true);
canvas_handler.appendChild(copy_ele);
canvas_handler.style.height = origin_ele.scrollHeight;
canvas_handler.style.width = origin_ele.scrollWidth;
html2canvas(copy_ele, {
      useCORS: true,
     }).then((canvas) => {
       // do your things
     });
canvas_handler.removeChild(table_ele);

I tried this method, but not work exactly. In my way, will work with code below:

const copy_ele = origin_ele.cloneNode(true);
canvas_handler.contentDocument.body.appendChild(copy_ele);
canvas_handler.height = origin_ele.scrollHeight;
canvas_handler.width = origin_ele.scrollWidth;
html2canvas(canvas_handler.contentDocument.body, {
  useCORS: true,
}).then((canvas) => {
  // do your things
  canvas_handler.removeChild(copy_ele);
});

And if you want to apply your css style the same as it in current document, you also need to copy style to iframe:

// add style
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = 'your_style_file_url.css';
canvas_handler.contentDocument.head.appendChild(link);

const copy_ele = origin_ele.cloneNode(true);
canvas_handler.contentDocument.body.appendChild(copy_ele);
canvas_handler.height = origin_ele.scrollHeight;
canvas_handler.width = origin_ele.scrollWidth;
html2canvas(canvas_handler.contentDocument.body, {
  useCORS: true,
}).then((canvas) => {
  // do your things
  canvas_handler.removeChild(copy_ele);
});

in my case, all elements are svg or inline style, so i don't need to append stylesheet. but yes, you should add your stylesheet if needed

I've faced the same issue. I needed to make an image from the modal window (with fixed position). I always received a white image. The problem was in the scroll position. This code works for me:

const el = document.getElementById('html-to-canvas-area')
const area = el.getBoundingClientRect()
html2canvas(el, {
  scrollX: 0,
  scrollY: 0,
  width: area.width,
  height: area.height
})

Worked for me like a charm! Thanks for the clever solution!

@invisor lifesaver! That's the only thing that worked for me.

These option might also a solution for scrolling related cases

{
  scrollX: 0,
  scrollY: -window.scrollY
}

Was this page helpful?
0 / 5 - 0 ratings

Related issues

trongdau184 picture trongdau184  ·  64Comments

arindamINT picture arindamINT  ·  37Comments

shauchenka picture shauchenka  ·  56Comments

DanielSBelo picture DanielSBelo  ·  51Comments

Mallander picture Mallander  ·  23Comments