Html2canvas: Only renders what's in view

Created on 25 Jun 2015  ·  22Comments  ·  Source: niklasvh/html2canvas

It would appear the resulting image size is as big as all of the window content including what's overflowed but what's actually visible limited only to the viewport.

This is with me taking overflow off of everything that I could possible take it off of. So there is no css interfering with this. Is it possible to get a content that is outside of the viewport included in the image? I've noticed that even if i scroll the page down and then try it again the result won't even pick up what's in the scrolled viewport but instead still contains what's in the viewport at scrollheight 0.

campaignperformance 30

Needs More Information

Most helpful comment

Strangely, it only renders from the currently visible top boundary of the given element.

Try https://jsfiddle.net/bianjp/bpc3nq69/1/. Scroll to "Print Screen" and click it. The generated image won't include top lines that are not visible when clicked.
Using version 0.5.0.beta4.

Solution is to call $('html, body').scrollTop(0) (or any other way to make the top of the element to render visible) before calling html2canvas.

All 22 comments

Somehow on your examples on the homepage it shows everything in the body even what's not in view... how did you do that?

So ,I want to know how can capture an specifed element? do anyone has solution?

@justein Try this

<div id="test-case">Test-me</div>
html2canvas(document.getElementById("test-case")).then(function(canvas) {
    document.body.appendChild(canvas);
});

I can confirm this behavior with the latest version. It will render the correct size of the object asked for, but will not actually render to the canvas anything that is off-screen of the current viewport. So if the

<div id="test-case">Test-me</div>

is currently visible in the browser, it will render. If it's off-screen, the canvas is blank (but the right size). Partially visible: Partially rendered. Mine doesn't act like scrollHeight = 0, it renders whatever is visible when the code is executed. (My button is at the bottom).

Like btm's comment, I would like to know how it's done on the example site. Could it be relying on something in Angular or Bootstrap to get the off screen resources?

@cchubb I do not understand what Angle and Bootstrap has to do with this. The problem of John, seems to me a matter of rendering a specific element.

If you want render which is outside the view-port, just use

html2canvas(document.body).then(function (canvas) {});

If you want to render elements "overflow" remove the "overflow" at runtime and add again after the process using javascript for add className, like this:

.no-scroll {
     overflow: visible !important;
}

#main {
     overflow: auto;
     height: 200px;
}

<div id="main">
test<br> test<br> test<br> test<br> test<br> test<br> test<br> test<br> 
test<br> test<br> test<br> test<br> test<br> test<br> test<br> test<br> 
test<br> test<br> test<br> test<br> test<br> test<br> test<br> test<br> 
</div>

document.getElementById("main").className = "no-scroll";
html2canvas(document.body).then(function (canvas) {
      document.getElementById("main").className = "";
});

Or just point the html2canvas to render the element within the element with "overflow", like this:

#parent {
     overflow: auto;
     height: 200px;
}

#child {
background-color: #fc0;
height: 600px;
}
<div id="parent">
<div id="main">
test<br> test<br> test<br> test<br> test<br> test<br> test<br> test<br> 
test<br> test<br> test<br> test<br> test<br> test<br> test<br> test<br> 
test<br> test<br> test<br> test<br> test<br> test<br> test<br> test<br> 
</div>
</div>

html2canvas(document.getElementById("main")).then(function (canvas) {});

Really has many suggestions for features that are unnecessary from my point of view, simply target the correct DOM elements and use the "CSS" to their favor.

I figured it out. You fixed it in 0.5.0-alpha2. If I use the 0.5.0-alpha1 version it clips, but the alpha2 version does not. I didn't even notice that alpha2 was available because the releases page was focusing on alpha1.

Here is a fiddle that demonstrates it working now with alpha2. https://jsfiddle.net/cchubb/fy7tw7ek/1/ if you change the external resource back to alpha1, it will clip when the bottom link is clicked. (You need to save the download file as .png to view it, fiddles won't let me change the output window href to data.)

@btm1, try upgrading to Alpha2.

@cchubb I'll give this a shot.

@cchubb the underlying issue is fixed in alpha 2 and you're right it's well hidden I didn't even notice there was an alpha 2.

Hmm, for me even in alpha2 still only the part of the element which is "visible" in the viewport is rendereded. See http://jsfiddle.net/NPC42/ykvL6a17/ for a demonstration—html2canvas exports only those rows that are scrolled into viewport (regardless of whether they are visible in scrolled container div or not).

Am I calling html2canvas wrong somehow? When I test it on my actual code (not the JSFiddle one, which I created just for the demo), this suggestion helps render the whole element: https://github.com/niklasvh/html2canvas/issues/650, but I hope to avoid hacking the library.

@NPC It won't just render what's not in view without you doing anything you have to change it to overflow visible --->export really quickly ---> then change it back to scroll again or it won't work. Not ideal IMO i think there should be an option to just have it work but at least it does.

@btm1, yes, I assume that's not the intention, since I pass in the element that is within the scrolled one, the element itself doesn't have any overflow trimming.

For now in my app I found that I need to reattach my whole element to body, forcing specific width/height on it (since is contains absolutely positioned elements), in the meantime covering all this kitchen by a full-screen "Preparing export, please wait" overlay, because html2canvas takes 10+ seconds to render it all. After render is done—I attach it back to original location (inside a scrolled container), unsetting width/height.

Cumbersome, but it works.

Strangely, it only renders from the currently visible top boundary of the given element.

Try https://jsfiddle.net/bianjp/bpc3nq69/1/. Scroll to "Print Screen" and click it. The generated image won't include top lines that are not visible when clicked.
Using version 0.5.0.beta4.

Solution is to call $('html, body').scrollTop(0) (or any other way to make the top of the element to render visible) before calling html2canvas.

thanks @bianjp for proposed fix.

Strangely, it only renders from the currently visible top boundary of the given element.

Is that a normal behavior ... It appears very strange to me !

+1

This S.O. answer worked for me.

Before calling html2canvas, scroll the element you want to render into viewport.

const el = document.querySelector('#test')
el.scrollIntoView()
setTimeout(function () {
  html2canvas(el, {
    onrendered: function (canvas) {
      document.body.appendChild(canvas)
    },
    useCORS: true
  })
}, 10)

It works for me.
Using version is 0.5.0-beta4.

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.

Hey, @niklashvh

I was also facing the issue for taking snapshot only visible to the DOM. I have version 0.5.0-beta4
So, I am agree with @ziyoung solution. I did the same like he suggest.

           `$('html,body').scrollTop(0);

     html2canvas( $("#rectangular_div"), {
         useCORS: true,
         dpi: 200,

          onrendered:function(canvas) {

              var str = canvas.toDataURL("image/png");
              var contentType = 'image/png';
              console.log(str);
              b64Data =str;
              imgFrameSave();
          }
        })`

So, I set the div position at top 0 to the body and then call html2canvas . So as per my experience, I recommended to use version 0.5.0-beta4 by @eKoopmans so that you can avoid the image pix-elation issue as well as capturing full image from DOM.

That work on desktop but it doesn't work on mobile

What I did is window.scrolTo(0,0)before call htmltocanvas(), if you are on top of screen the div is printed complete

Was this page helpful?
0 / 5 - 0 ratings

Related issues

anthonymejia picture anthonymejia  ·  4Comments

deepender87 picture deepender87  ·  4Comments

Loki180 picture Loki180  ·  4Comments

bishwapoudel picture bishwapoudel  ·  4Comments

ABHIKSINGHH picture ABHIKSINGHH  ·  3Comments