Our website is made possible by displaying online advertisements to our visitors. Please consider supporting us by disabling your ad blocker.

Generate Images from HTML with Gulp and Puppeteer

TwitterFacebookRedditLinkedInHacker News

Have you ever needed to generate an image from your HTML? Whether it be for design purposes or for marketing purposes with social media, knowing how to get a screenshot of your HTML design without manually taking the screenshot can be a great thing.

A use-case I was interested in was around feature graphics for each of my blog posts. Sure I could open a graphic design tool like Affinity Photo, or use the same feature graphic for every tutorial, but what if I wanted to automatically generate them based on certain criteria?

In this tutorial we’re going to see how to use Puppeteer to take screenshots of our HTML through a headless Gulp task.

To get an idea of what we want to accomplish, take the following as an example:

Example Feature Screenshot

The above image was created entirely with HTML and could satisfy my use case of being a feature image for a tutorial on the blog. In fact, I got the idea after seeing similar feature graphics on DEV.to articles. While I don’t know what their strategy is, I thought I’d invent my own.

Designing an HTML Component or Page for Capture

Before we dive into the process of taking screenshots, we should come up with some HTML to capture. To be clear, any HTML elements would work, but let’s focus on being creative, matching the example I presented earlier.

Create a project with an index.html file, a style.css file, and a few image files. For this particular example, we’ll being using a lot of Flexbox.

Open the project’s style.css file and include the following code:

html, body {
    height: 100vh;
    margin: 0;
    display: flex;
    width: 100vw;
}
#container {
    flex: 1;
    display: flex; 
    flex-direction: column; 
    border: 10px solid black; 
    background-color: #931c22;
    padding: 25px;
    color: #FFFFFF;
}
#body {
    flex-grow: 1; 
    font-size: 4rem; 
    display: flex;
    align-items: center;
    text-transform: uppercase;
    font-weight: bold;
    line-height: 6rem;
}
#footer {
    display: flex; 
    flex-grow: 0; 
    flex-direction: row; 
    align-items: center; 
}
#author {
    flex-grow: 1;
    display: flex;
    flex-direction: row;
    align-items: center;
}
#author-img {
    width: 75px; 
    height: 75px; 
    margin-right: 25px;
    border: 2px solid #FFFFFF;
}
#author-name {
    font-size: 2.5rem;
    margin-right: 10px;
    text-transform: uppercase;
}
#brand-icon {
    width: 75px;
    height: 75px;
    border: 2px solid #FFFFFF;
}

I am by no means a CSS or design expert, so the CSS above may be able to be optimized. However, everything worked as expected when combined with my HTML.

With the CSS in place, open the project’s index.html file and include the following markup:

<!DOCTYPE html>
<html>
    <head>
        <link rel="stylesheet" href="style.css" />
    </head>
    <body>
        <div id="container">
            <div id="body">
                Execute HTTP Requests in JavaScript Applications
            </div>
            <div id="footer">
                <div id="author">
                    <img id="author-img" src="nraboy.jpg">
                    <div id="author-name">
                        Nic Raboy
                    </div>
                </div>
                <img id="brand-icon" src="icon.png">
            </div>
        </div>
    </body>
</html>

In my example, I’ve already downloaded an nraboy.jpg image and an icon.png image. However, feel free to change the CSS, HTML, and images to meet your needs.

Generating Screenshots with Puppeteer and Gulp

Now that we have some HTML in place, we can focus on generating a screenshot of it. To do this we’ll be using Puppeteer, which is a headless Chrome Node.js API.

Within the project, we’ll need to install a few dependencies, which will require Node.js. From the command line, execute the following:

npm install puppeteer gulp gulp-tap --save-dev

While Puppeteer will be doing most of the work, we’ll be using Gulp to manage the task. Since we’ll be using a Gulp file pipeline, we need to be able to tap into the pipeline and gather various information about the files being processed, hence the extra package.

Now that the dependencies are in place, create a gulpfile.js file with the following JavaScript code:

const gulp = require("gulp");
const puppeteer = require("puppeteer");
const tap = require("gulp-tap");
const path = require("path");

gulp.task("build", function () {
    return gulp.src(["**/*.html", "!node_modules/**/*"])
        .pipe(tap(async (file) => {
            const browser = await puppeteer.launch({ headless: true });
            const page = await browser.newPage();
            await page.setViewport({
                width: 1200,
                height: 600,
                deviceScaleFactor: 1,
            });
            await page.goto("file://" + file.path);
            await page.screenshot({ path: path.basename(file.basename, ".html") + ".png" });
            await browser.close();
        }));
});

This particular Gulp configuration has a single task for building the images. The task looks for all HTML files in the directory and excludes anything in the node_modules directory.

For every file in the pipeline, a headless browser is created with the specified viewport configuration. The filename and path is extracted and used for rendering the HTML, then saving the render to an image.

Conclusion

You just saw how to use Puppeteer to capture a screenshot of an HTML render without using browser based JavaScript, meaning completely headless.

There are plenty of use-cases for this, but for me, using HTML as a template for marketing images is great. These images can be generated automatically without having to open a common multimedia editing application.

Nic Raboy

Nic Raboy

Nic Raboy is an advocate of modern web and mobile development technologies. He has experience in C#, JavaScript, Golang and a variety of frameworks such as Angular, NativeScript, and Unity. Nic writes about his development experiences related to making web and mobile development easier to understand.