DEV Community

Cover image for Upload the image with a preview using HTML, CSS & JavaScript
Mirza Leka
Mirza Leka

Posted on • Updated on

Upload the image with a preview using HTML, CSS & JavaScript

This guide will teach you how to set up an image uploader and display a preview on the screen using plain HTML, CSS & JavaScript.

Project Setup

Create a directory on your computer (e.g. file-upload) and three files inside:

  • index.html
  • styles.css
  • scripts.js

HTML Template

Starting with HTML, we'll create a base template and link it with two other files:

<!DOCTYPE html>
<html lang="en">
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <!-- Font awesome for fa icons -->
    <script src=""></script>
    <!-- Including styles.css file -->
    <link rel="stylesheet" type="text/css" href="./styles.css" />
    <title>File upload with preview</title>

    <!-- Including scripts.js file -->
    <script src="./scripts.js"></script>

Enter fullscreen mode Exit fullscreen mode

I've also included a script for the Font Awesome icons that we'll use for UI/UX.

Setting up file uploader

Now we add the HTML code for file upload within the two <body></body> tags:

    <div class="profile-picture">
      <h1 class="upload-icon">
        <i class="fa fa-plus fa-2x" aria-hidden="true"></i>
Enter fullscreen mode Exit fullscreen mode
  • The <div class="profile-picture"> is our main container that the user will interact with and it will serve as a display for the uploaded image.
  • The <h1 class="upload-icon"> is a heading for the icon that will appear over the image.

HTML template preview
Looks pretty terrible, but we'll get to it shortly.

Peeking into the input

  • Input type="file" is what tells HTML to change this input from its default behavior (textbox) to a button that can upload a file from your machine.
  • The onchange="upload()" is an onchange event on the element that will trigger when the file is selected and invoke the function upload() that we'll create in the JavaScript file.
  • The accept="image/*" tag tells the app to look exclusively for image-type files when browsing through the files on your machine. Other file types won't appear in the window.

Styling the uploader

The downside of the default HTML <input/> element has limited styling options. To make the file upload button look like the one in the cover picture we'll mask the <input/> with the <div class="profile-picture"> covering it.

The app user will interact with the upload input by clicking on the <div class="profile-picture">. To do that we'll give our container a style of position: relative, while the <h1> tag and the <input/> tag will have a style of position: absolute.

Inside the styles.css file, we'll style each element.

Profile-picture container styles

.profile-picture {
  opacity: 0.75;
  height: 250px;
  width: 250px;
  position: relative;
  overflow: hidden;

  /* default image */
  background: url('');

  background-position: center;
  background-repeat: no-repeat;
  background-size: cover;
  box-shadow: 0 8px 6px -6px black;
Enter fullscreen mode Exit fullscreen mode

File-uploader input styles

.file-uploader {
  /* make it invisible */
  opacity: 0;
  /* make it take the full height and width of the parent container */
  height: 100%;
  width: 100%;
  cursor: pointer;
  /* make it absolute */
  position: absolute;
  top: 0%;
  left: 0%;
Enter fullscreen mode Exit fullscreen mode

Upload-icon heading styles

We'll position the Font Awesome icon in the middle of the container and make it invisible by default.

.upload-icon {
  position: absolute;
  top: 45%;
  left: 50%;
  transform: translate(-50%, -50%);
  /* initial icon state */
  opacity: 0;
  transition: opacity 0.3s ease;
  color: #ccc;
  -webkit-text-stroke-width: 2px;
  -webkit-text-stroke-color: #bbb;
Enter fullscreen mode Exit fullscreen mode

The icon will appear only after the user hovers over the container:

/* toggle icon state */
.profile-picture:hover .upload-icon {
  opacity: 1;
Enter fullscreen mode Exit fullscreen mode

Styled file upload

Looks way better! Now onto adding the functionality.

Scripting the upload

Inside the script.js file, we'll create the upload() function that will be triggered by the <input onchange="upload"> event. Inside we're going to pick up the image from the <input class="file-uploader" element in the HTML:

function upload() {

  const fileUploadInput = document.querySelector('.file-uploader');
Enter fullscreen mode Exit fullscreen mode

We can also validate the input based on the selected file type, file size, etc.

  const fileUploadInput = document.querySelector('.file-uploader');

  // using index [0] to take the first file from the array
  const image = fileUploadInput.files[0];

  // check if the file selected is not an image file
  if (!image.type.includes('image')) {
    return alert('Only images are allowed!');

  // check if size (in bytes) exceeds 10 MB
  if (image.size > 10_000_000) {
    return alert('Maximum upload size is 10MB!');
Enter fullscreen mode Exit fullscreen mode

Lastly, we'll make use of the built-in FileReader class to convert the file we've uploaded (that is in Blob format) to a base64-encoded data URL representing the image.

  const fileReader = new FileReader();
Enter fullscreen mode Exit fullscreen mode

When the fileReader finishes processing the Blob image, it will trigger the onload event on the instance. Inside we'll use the base-64 URL as a background image of our container:

  const fileReader = new FileReader();

  fileReader.onload = (fileReaderEvent) => {
    const profilePicture = document.querySelector('.profile-picture'); = `url(${})`;
Enter fullscreen mode Exit fullscreen mode


Final demo

Photo by Helena Lopes from Pexels

The next logical step is to upload the Blog image to a cloud, like a Cloudinary or an AWS S3 bucket, which is out of the scope of this article.

You can find the full code on the Github.
For more awesome content, be sure to check out my other blog on Medium and follow me on Twitter.

Top comments (0)