DEV Community

Cover image for Generate images from HTML in Node.js

Generate images from HTML in Node.js

🦁 Yvonnick FRIN on December 18, 2019

As developers, we don't have great skills with image manipulation softwares, but we still need it. In my case I had to generate Twitter cards for s...
Collapse
 
helleworld_ profile image
DesirΓ© πŸ‘©β€πŸŽ“πŸ‘©β€πŸ«

Β‘Amazing!

Just tried it out, loving it! Just one question. If I use px to set the width of my elements, the image looks good:

But if I use % to set the width, then:

Why could this happen?

However, amazing project, thank you!

Collapse
 
yvonnickfrin profile image
🦁 Yvonnick FRIN

Thank you DesirΓ©!

Basically the module takes a screenshot of the body tag's content. So you need to fix the size of you image on this tag using CSS then you can use percent on body's children.

Maybe I should add this in the documentation?

Collapse
 
helleworld_ profile image
DesirΓ© πŸ‘©β€πŸŽ“πŸ‘©β€πŸ« • Edited

Not sure, my code is as follows:

<body>
    <div class="card">
       [ ... ] (lots of subdivs)
    </div>
</body>

and my css:

        .card{
            width: 20%; /** if it's % then the image's width doesn't display properly **/
            box-shadow: 1px 3px 15px lightgray;
            height: 250px;
        }

I guess if it's a % then it won't work properly and you must set a fixed width for your elements before taking the screenshot!

I think it would be useful to add this as a sidenote, in case someone is setting all the components with %!

Also, it works perfectly fine with rem and em too.

EDIT: I'm using the CLI version just in case that matters!

Thread Thread
 
yvonnickfrin profile image
🦁 Yvonnick FRIN • Edited

Percentage are relative to your parent dimensions So it will be 20 percent of body. If you don't fix body size it will be relative to the browser's viewport I guess. I don't set any viewport. So I recommend fixing body size to the resolution you want for the output file.

In the example below I fix the size to A4 format in high resolution. The output file resolution will be 2480x3508. So the card size will be 20% of 2480px. You see what I mean?

<html>
  <head>
    <style>
       body {
         width: 2480px;
         height: 3508px;
       }
       .card{
         width: 20%; /** if it's % then the image's width doesn't display properly **/
         box-shadow: 1px 3px 15px lightgray;
         height: 250px;
        }
    </style>
  </head>
  <body>
    <div class="card">
       [ ... ] (lots of subdivs)
    </div>
  </body>
</html>
Thread Thread
 
helleworld_ profile image
DesirΓ© πŸ‘©β€πŸŽ“πŸ‘©β€πŸ«

Sure! I usually never set any size for the body, it should be nice to have it in mind so the image looks good, thank you!

Thread Thread
 
yvonnickfrin profile image
🦁 Yvonnick FRIN

DΓ©sirΓ© I added a section about this in the documentation. What do you think of it?

Thread Thread
 
helleworld_ profile image
DesirΓ© πŸ‘©β€πŸŽ“πŸ‘©β€πŸ«

Clear as a sunny day, I think there can't be any risk now! Thank you!

Collapse
 
inatnat profile image
Nathaniel-kw Cheung

Super cool stuff

Is there any way to use custom font? I got a HTML like this but the output image is not using the font specified (it's good to show in browser)



<br>
body {<br>
width: 1000px;<br>
height: 500px;<br>
}</p>
<div class="highlight"><pre class="highlight plaintext"><code> @font-face {
font-family: JuneBug;
src: url('JUNEBUG.TTF');
}
h1 {
    font-family: JuneBug
}

&lt;/style&gt;
</code></pre></div>
<p></head></p>

<p><body>Hello world!<br>
<h1>Hey, June</h1><br>
</body></p>

<p></html></p>

Collapse
 
yvonnickfrin profile image
🦁 Yvonnick FRIN

Hi Nathaniel,

TTF format is made for Safari, Android and iOS. The image is generated in a chromium browser. So you can only use WOFF format.

Collapse
 
wlun001 profile image
Wei Lun • Edited

This won't work on Docker, need to install anything other that npm install?

Collapse
 
quedicesebas profile image
SebastiΓ‘n Rojas Ricaurte

You have to follow this for Docker github.com/puppeteer/puppeteer/blo... (tehere is specifict instructiosn for alpine also) and send this in puppeteerArgs when you call nodeHtmlToImage:

puppeteerArgs: {
headless: true,
args: [
"--no-sandbox",
"--remote-debugging-address=0.0.0.0",
"--remote-debugging-port=9222",
],
}

Collapse
 
quedicesebas profile image
SebastiΓ‘n Rojas Ricaurte

ΒΏAnyone?

Collapse
 
napoleon039 profile image
Nihar Raote

Looks so cool! It's interesting that I can use HTML and CSS to generate an image.

Collapse
 
yvonnickfrin profile image
🦁 Yvonnick FRIN

Thank you Nihar! Sure, as a developper I'm used to HTML and CSS which are great tools to make nice graphical stuff πŸ™Œ

Collapse
 
dschep profile image
Daniel Schep

Is it possible to generate a GIF from animated HTML?

Collapse
 
yvonnickfrin profile image
🦁 Yvonnick FRIN

node-html-to-images don't handle this use case. It is an awesome idea!

Collapse
 
daniel13rady profile image
Daniel Brady

Nice work. πŸ‘

Collapse
 
yvonnickfrin profile image
🦁 Yvonnick FRIN

Thank you Daniel ❀️

Collapse
 
kaushan profile image
Kaushan

That’s really great ! I used to make it via screenshot inside headless browsers. This solution is much more elegant

Collapse
 
majiyd profile image
majiyd

Wow, Thank you for this great work!

I have a question though, Does it work with react Native? Thank you.

Collapse
 
peacefullatom profile image
Yuriy Markov

Awesomeness! πŸ‘

Collapse
 
yvonnickfrin profile image
🦁 Yvonnick FRIN

Glad you like it β™₯️

Collapse
 
tejesh002 profile image
tejesh002

This Package output only 800X600 dimension, but expecting dimension is greater then this.