Add Text to Images Online Using JavaScript and CSS: A Step-by-Step Guide

← PrevNext →

Last edited: 12th August 2024

Learn how to overlay text on an image using HTML and CSS in just a few simple steps. This tutorial shows you how to create a container element (like a <div>) that holds both the image, via a <canvas> or <img> tag and the text inside another <div>. By applying CSS positioning techniques such as position: relative and position: absolute, you can precisely place text over any image. Follow this guide to not only overlay text seamlessly but also save the final image to your computer for use in your web projects.
See this demo

I have used the Canvas element in this example and I have explained why.

Example:

<!DOCTYPE html>
<html lang="en">
<head>
  <title>Text over image example</title>

  <link href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/themes/smoothness/jquery-ui.css" rel="stylesheet" type="text/css"/>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"></script>

  <style>
    .mainContainer {
      position: relative;
      padding: 0;
      min-width: 250px;
      min-height: 250px;
      display: inline-block;
      margin: 0 auto;
    }

    img {
      border: none;
      max-width: 100%;
    }

    #textArea {
      display: block;
      padding: 10px;
    }

    #theText {
      position: absolute;
      top: 90px;
      left: 0;
      background: rgba(0, 0, 0, 0.1);
      color: #fff;
      width: auto;
      padding: 5px;
      text-align: left;
      border: dashed 2px #ff7f27;
      font: 15px Calibri;
      display: block;
      cursor: move;
    }

    canvas {
      max-width: 100%;
    }
  </style>
</head>
<body>
    <!-- File upload -->
    <p>
        <input type="submit" id="btChooseImage" onclick="chooseImage()" value="Select an image" />
    </p>

    <input type="file" id="file" onchange="showImage(this)" style="display: none; visibility: hidden; width: 1px;" />

    <!-- Textarea to enter some texts -->
    <p>
        <textarea onkeyup="writeText(this)" id="textArea" placeholder="Enter some value for text" rows="2" cols="50"></textarea>
    </p>

    <div>
        <!-- The parent container: image and container for text -->
        <div class="mainContainer" id="mainContainer">
            <!-- THE DEFAULT IMAGE. You can select a different image. -->
            <img src="https://www.encodedna.com/images/theme/easy-image-resizer.jpg" id="myimage" alt="" />

            <!-- The text, which is also draggable -->
            <div id="theText" onmousedown="this.style.border = 'dashed 2px #FF7F27';">sample text</div>
        </div>

        <!-- Button to save the image with the text -->
        <p><input type="button" onclick="saveImageWithText();" id="bt" value="Save the Image" /></p>
    </div>
<script>
    // Make the text element draggable.
    $(document).ready(function() {
        $('#theText').draggable({
            containment: 'parent' // set draggable area.
        });
    });

    // Select image and show it
    function chooseImage() {
        document.getElementById('file').click();
    }

    function showImage(fl) {
        if (fl.files.length > 0) {
            let reader = new FileReader();

            reader.onload = function(e) {
                let img = new Image();

                img.onload = function() {
                    if (this.width > screen.width || this.height > screen.height) {
                        alert('Please select a small image. The image width and height should be less than the screen width and height.');

                        document.getElementById('theText').style.display = 'none';
                        document.getElementById('bt').style.display = 'none';
                        document.getElementById('textArea').style.display = 'none';
                        document.getElementById('myimage').src = '';
                    } else {
                        document.getElementById('theText').style.display = 'block';
                        document.getElementById('bt').style.display = 'block';
                        document.getElementById('textArea').style.display = 'block';
                    }
                }

                img.src = e.target.result; // actual image
                document.getElementById('myimage').src = reader.result; // Add the image on the form
            };
            reader.readAsDataURL(fl.files[0]);
        }
    }

    let textContainer;
    let t = 'sample text';

    // Get the values that you have entered in the textarea and write it in the DIV over the image
    function writeText(ele) {
        t = ele.value;
        document.getElementById('theText').innerHTML = t.replace(/\n\r?/g, '<br />');
    }

    // Finally, save the image with text over it
    function saveImageWithText() {
        textContainer = document.getElementById('theText'); // The element with the text

        // Create an image object
        let img = new Image();
        img.src = document.getElementById('myimage').src;

        // Create a canvas object
        let canvas = document.createElement("canvas");

        // Wait till the image is loaded
        img.onload = function() {
            drawImage();
            downloadImage(img.src.replace(/^.*[\\\/]/, '')); // Download the processed image
        }

        // Draw the image on the canvas
        function drawImage() {
            let ctx = canvas.getContext("2d"); // Create canvas context

            // Assign width and height
            canvas.width = img.width;
            canvas.height = img.height;

            // Draw the image
            ctx.drawImage(img, 0, 0);

            textContainer.style.border = 0;

            // Get the padding etc.
            let left = parseInt(window.getComputedStyle(textContainer).left);
            let right = textContainer.getBoundingClientRect().right;
            let top = parseInt(window.getComputedStyle(textContainer).top, 0);
            let center = textContainer.getBoundingClientRect().width / 2;

            let paddingTop = window.getComputedStyle(textContainer).paddingTop.replace('px', '');
            let paddingLeft = window.getComputedStyle(textContainer).paddingLeft.replace('px', '');
            let paddingRight = window.getComputedStyle(textContainer).paddingRight.replace('px', '');

            // Get text alignment, color, and font of the text
            let txtAlign = window.getComputedStyle(textContainer).textAlign;
            let color = window.getComputedStyle(textContainer).color;
            let fnt = window.getComputedStyle(textContainer).font;

            // Assign text properties to the context
            ctx.font = fnt;
            ctx.fillStyle = color;
            ctx.textAlign = txtAlign;

            // Now, we need the coordinates of the text
            let x; // coordinate
            if (txtAlign === 'right') {
                x = right + parseInt(paddingRight) - 11;
            }
            if (txtAlign === 'left') {
                x = left + parseInt(paddingLeft);
            }
            if (txtAlign === 'center') {
                x = center + left;
            }

            // Get the text (it can be a word or a sentence) to write over the image
            let str = t.replace(/\n\r?/g, '<br />').split('<br />');

            // Finally, draw the text using Canvas fillText() method
            str.forEach((line, i) => {
                ctx.fillText(
                    line.replace('</div>', '').replace('<br>', '').replace(';', ''), 
                    x, 
                    parseInt(paddingTop, 10) + parseInt(top, 10) + 10 + (i * 15)
                );
        });
    }

    // Download the processed image
    function downloadImage(img_name) {
        let a = document.createElement('a');
        a.href = canvas.toDataURL("image/png");
        a.download = img_name;
        document.body.appendChild(a);
        a.click();
    }
}
</script>
</body>
</html>
See this demo

Note: This is intended purely as an example and may not include all features or edge cases.

How this works?

In the markup section, I have added a <div> element that serves as a container, an image (<img>) inside the parent <div> element and another <div>, which has the text (you can drag this element anywhere on the image). Using CSS, I am placing the text over the image.

Using jQuery UI

I am using jQuery UI to make the text moveable (so I can drag and place the text anywhere on the image). I have added jQuery CDNs in the script section (above).

I have also set a draggable area limit , so the text (the <div> element) stays over the image and doesn’t go outside the image. See this code inside the script.

$(document).ready(function() {
    $(function() { 
        $('#theText').draggable({
            containment: 'parent'      // set (or limit) the draggable area.
        }); 
    });
});

The CSS Style

There are five elements. So, I had to style them accordingly. The CSS for ".mainContainer" and "#theText" is important here.

The main container or the parent container has a "relative" position and the text element (which is a DIV), has an absolute position. Child elements or "absolute elements are positioned relative" to the parent element.

Explaining the Script

This example includes a few methods, with the most important one being let saveImageWithText = () => { }. This is the function where the actual text is drawn onto the image using the Canvas API. To achieve this, I recreated the image on a <canvas> element and used its rendering context to overlay the desired text.

In this step, I extract all relevant properties of the text element, such as padding, font, color, alignment, and coordinates to accurately position the text over the image using the Canvas API before saving it.

Conclusion

This example is a simplified demonstration and not a complete project, so certain features may be missing. Feel free to enhance it by adding functionality, like a toolbox that allows users to customize text color, choose different fonts, adjust font sizes, and more.

🚀 Edit: I have designed a tool to add text to a picture using the above example, with some advanced features. If you like it, please don't forget to share it.

← PreviousNext →