Build a Placeholder Image Generator with JavaScript 📷 🔥
Tags: javascript, webdev, html, tutorial
Published: 2021-01-11 08:32:03

Everybody love's "vanilla JavaScript" so today we'll be building a Placeholder Image Generator with the help of [HTML Canvas](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API).

## Video Tutorial
As always, if you prefer this tutorial in video format, feel free to watch the tutorial on my YouTube channel, [dcode](https://www.youtube.com/dcode-software):
{% youtube BBM6ElNENds %}

### Adding the HTML
Let's start with the HTML for the user interface and input fields.

```html
<h1>Placeholder Image Generator</h1>
<h3>Dimensions</h3>
<input type="number" class="input" id="inputWidth" value="400">
x
<input type="number" class="input" id="inputHeight" value="300">
<button id="buttonGenerate" type="button">Generate</button>

<h3>Data URL</h3>
<input type="text" class="input" id="inputDataUrl" placeholder="Please generate a placeholder image!" readonly>

<h3>Preview</h3>
<img alt="Preview Image" id="imagePreview" style="display: none">
```

With this code, we've got a couple of important elements:
* both input fields for width and height
* a button to generate the placeholder image
* an input field to store the generated data URL for the image
* an image preview

### Next, styling up our HTML
We can add some very basic CSS to make things look a bit prettier.

```css
body {
    font-family: sans-serif;
}

.input {
    height: 30px;
    box-sizing: border-box;
}

#inputWidth,
#inputHeight {
    width: 100px;
}

#inputDataUrl {
    width: 100%;
    max-width: 600px;
}

#imagePreview {
    width: 100%;
}
```

Note the usage of `box-sizing` for the input fields. This ensures they are `30px` in height no matter if we add any borders or padding. See [box-sizing](https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing) for more info.

Also take note of the properties in `#inputDataUrl` - with these properties, we are saying "let the input field take up 100% width, but don't let it go over 600px". This helps with mobile responsiveness.

### Writing the JavaScript
#### The main function
Now that we're onto the JavaScript, our first object is to write a function which will generate a canvas element which we can size accordingly and add a background, plus text.

```javascript
function createPlaceholderCanvas(width, height) {
    const element = document.createElement("canvas");
    const context = element.getContext("2d");

    element.width = width;
    element.height = height;

    // Fill in the background
    context.fillStyle = "#aaaaaa";
    context.fillRect(0, 0, element.width, element.height);

    // Place the text
    context.font = "bold 90px sans-serif";
    context.fillStyle = "#333333";
    context.textAlign = "center";
    context.textBaseline = "middle";
    context.fillText(`${width}x${height}`, element.width / 2, element.height / 2);

    return element;
}
```

On the first line of this function, we're simply creating a brand new HTML canvas element which we can work on. The second line is grabbing the 2D context which we can then call methods on to add our background and text.

The next two lines are pretty self-explanatory, we're setting the desired width and height for the canvas which will be inputted by the user.

To fill in the background, we're setting a dark grey color as the `fillStyle`. This means the next fill command will use that color.

Speaking of, we are then using `fillRect` to paint the background of the canvas, starting at the top left corner and spanning the entire width and height of our canvas.

The last chunk of our function adds the text to the placeholder image. We set the font on the context, as well as the color and text-alignment options.

Now that we've defined what our font will look like, we add the text using `fillText`, taking advantage of [template strings](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) to generate a string which could look something like this: **400x300**. By passing through a width and height divided by 2, it ensures our text gets drawn in the center.

On the last line, we're simply returning our newly-created HTML canvas element.

#### Making the user interface work
Now that we've written the core of the logic, we can get a reference to each of our important HTML elements:

```javascript
const inputWidth = document.getElementById("inputWidth");
const inputHeight = document.getElementById("inputHeight");
const inputDataUrl = document.getElementById("inputDataUrl");
const imagePreview = document.getElementById("imagePreview");
```

Next, we can react to when the "Generate" button is clicked:

```javascript
document.getElementById("buttonGenerate").addEventListener("click", () => {
    const MIN_SIDE_LENGTH = 200;

    // Validation
    if (
        isNaN(inputWidth.value)
        || isNaN(inputHeight.value)
        || inputWidth.value < MIN_SIDE_LENGTH
        || inputHeight.value < MIN_SIDE_LENGTH
    ) {
        alert(`Please enter a valid image size. The minimum length is ${MIN_SIDE_LENGTH}px`);
        return;
    }

    const canvasElement = createPlaceholderCanvas(inputWidth.value, inputHeight.value);
    const dataUrl = canvasElement.toDataURL();

    inputDataUrl.value = dataUrl;
    imagePreview.src = dataUrl;
    imagePreview.style.display = "block";
    imagePreview.style.maxWidth = `${inputWidth.value}px`;
});
```

As we can see, we're defining a minimum side length on the first line. If the user enters a width or height less than 200, we don't want to proceed with the generation of the placeholder image. You can change this, of course 🙂

Next, we are doing some basic validation. We check if the user has actually given us a valid number for the width and height, and if those numbers are less than the minimum side length.

If our validation fails, we tell the user and stop the execution of the function with an early `return`.

Once validation passes, we create the canvas element using the function defined above, and grab the [data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs) for the image.

The last few lines of the code involve presenting the data URL to the user and displaying the preview image to the user using the `img` tag. We also set a maximum width so a low resolution image doesn't stretch.

**And that's it! Hope you enjoyed this tutorial. If you liked, consider checking out my YouTube channel, [dcode](https://www.youtube.com/dcode-software)** 😁