Step-by-Step Guide: Create a Custom Drag and Drop File Upload Using HTML, CSS & JavaScript

Categories: Forms
custom drag and drop file uploader

A custom drag and drop file upload is an essential feature for modern websites. Whether your website is a portfolio, project management app, or any platform requiring file uploads, offering an intuitive and responsive upload interface improves the user experience significantly.

In this guide, we’ll walk you through creating a fully custom drag-and-drop file upload component using HTML, CSS, and JavaScript. Users can choose files by clicking or simply dragging them into a specified upload box, while instantly seeing details like file name and size.

By the end of this tutorial, you’ll have a fully functional, responsive, and visually appealing file upload component that you can integrate into any website.

Watch the Video Tutorial: Create a Custom Drag & Drop File Upload

Why Drag & Drop File Upload is Important

In most traditional file upload setups, users have to click a button to browse and select files from their devices. While this works, it’s not very interactive and can feel outdated.

Drag-and-drop upload areas improve the user experience because:

  • Users can drag files directly into the upload zone.
  • Immediate feedback shows file names, sizes, and upload progress.
  • The process is faster and more visually appealing than standard file input fields.

Key Features of Our Custom File Upload

Our example will include:

  1. Click or Drag & Drop: Users can click the area to select files or drag files into it.
  2. Real-Time Feedback: The selected file name and size will display instantly.
  3. Highlighting on Drag: The upload area changes visually when files are dragged over it.
  4. Cancel Button: Users can reset the selection if they change their mind.

For more input handling ideas, check out our Responsive Registration Form in HTML & CSS

HTML Code:

Here’s the layout for the drag-and-drop uploader:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>How to Create Custom Drag and Drop File Upload & Attachment Using HTML, CSS, & JavaScript</title>
    <!-- ------Box Icon--------- -->
    <link href='https://unpkg.com/boxicons@2.1.4/css/boxicons.min.css' rel='stylesheet'>
    <link rel="stylesheet" href="style.css">
</head>

<body>

    <div class="wrapper">
        <form action="" class="dropbox-zone">
            <h2>Upload and attach files</h2>
            <p>Attach files to this project</p>

            <div class="droparea-zone">
                <div class="upload-icon-file">
                    <i class="bx bx-file-blank"></i>
                </div>
                <p>Click to upload or darg and drop</p>
                <input type="file" required id="upload-file" name="upload-file">
                <p class="message">No Files Selected</p>
            </div>

            <div class="dropactions-zone">
                <button type="reset">Cancel</button>
                <button id="submit-button" type="submit">Save</button>
            </div>

        </form>
    </div>


    <script src="script.js"></script>
</body>

</html>

Explanation:

  • dropbox-zone contains the file uploader and action buttons.
  • droparea-zone has an icon and a placeholder message for file details.
  • The file input element is kept invisible yet still functions when clicked, ensuring a smooth user experience.

CSS Code:

/* ==========Font Family===== */
@import url('https://fonts.googleapis.com/css2?family=Work+Sans&display=swap');

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: "Work sans", sans-serif;
    background-color: #483EA8;
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    padding: 16px;
}

.wrapper {
    border-radius: 2rem;
    background-color: #fff;
    max-width: 550px;
    width: 100%;
    display: flex;
    justify-content: center;
    flex-direction: column;
    padding: 2rem;
    box-shadow: rgba(149, 157, 165, 0.2) 0px 8px 24px;
}

.dropbox-zone {
    border-radius: 2rem;
    padding: 2rem;
    box-shadow: rgba(149, 157, 165, 0.2) 0px 8px 24px;
    display: flex;
    justify-content: center;
    flex-direction: column;
    max-width: 550px;
    width: 100%;
    background-color: #fff;
    text-align: center;
}

.dropbox-zone h2 {
    font-size: 25px;
    margin-bottom: 0.5rem;
    color: #483EA8;
}

.droparea-zone {
    padding: 1rem;
    position: relative;
    margin-top: 2rem;
    min-height: 16rem;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    border: 2px dashed #483EA8;
    border-radius: 1rem;
    color: #111926;
    cursor: pointer;
}

.droparea-zone .upload-icon-file i {
    font-size: 65px;
    color: #111926;
}

.droparea-zone [type="file"] {
    position: absolute;
    cursor: pointer;
    opacity: 0;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
}

.dropactions-zone {
    display: flex;
    justify-content: space-between;
    padding-top: 1.5rem;
    margin-top: 1.5rem;
    border-top: 1px solid #D3D3D3;
    gap: 1rem;
    flex-wrap: wrap;
}

.dropactions-zone button {
    flex-grow: 1;
    min-height: 3rem;
    font-size: 1.2rem;
}

.dropactions-zone button[type="reset"] {
    background-color: transparent;
    border: 1px solid #D3D3D3;
    border-radius: 0.5rem;
    padding: 0.5rem 1rem;
    cursor: pointer;
}

.dropactions-zone button[type="submit"] {
    background-color: #483EA8;
    color: #fff;
    border: 1px solid #483EA8;
    border-radius: 0.5rem;
    padding: 0.5rem 1rem;
    cursor: pointer;
}

.dropover-zone {
    border-style: solid;
    background-color: #F8F8FF;
}

.sucess {
    border-color: #598259;
    background-color: #e8ffe870;
}

JavaScript Code:

const dropBoxZone = document.getElementsByClassName("dropbox-zone")[0];
const inputFiles = document.querySelectorAll(".droparea-zone [type='file']");
const inputElement = inputFiles[0];
const dropZoneElement = inputElement.closest(".droparea-zone");

inputElement.addEventListener("change", (e) => {
  if (inputElement.files.length) {
    updateDropzoneFileList(dropZoneElement, inputElement.files[0]);
  }
  dropZoneElement.classList.add("sucess");
});

dropZoneElement.addEventListener("dragover", (e) => {
  e.preventDefault();
  dropZoneElement.classList.add("dropover-zone");
  dropZoneElement.classList.remove("sucess");
});

["dragleave", "dragend"].forEach((type) => {
  dropZoneElement.addEventListener(type, (e) => {
    dropZoneElement.classList.remove("dropover-zone");
  });
});

dropZoneElement.addEventListener("drop", (e) => {
  e.preventDefault();
  if (e.dataTransfer.files.length) {
    inputElement.files = e.dataTransfer.files;
    updateDropzoneFileList(dropZoneElement, e.dataTransfer.files[0]);
  }
  dropZoneElement.classList.remove("dropover-zone");
  dropZoneElement.classList.add("sucess");
});

const updateDropzoneFileList = (dropZoneElement, file) => {
  let dropzoneFileMessage = dropZoneElement.querySelector(".message");
  dropzoneFileMessage.innerHTML = `${file.name}, ${file.size} bytes`;
};

dropBoxZone.addEventListener("reset", (e) => {
  let dropzoneFileMessage = dropZoneElement.querySelector(".message");
  dropzoneFileMessage.innerHTML = `No Files Selected`;
  dropZoneElement.classList.remove("sucess");
});

dropBoxZone.addEventListener("submit", (e) => {
  e.preventDefault();
  const myFiled = document.getElementById("upload-file");
  console.log(myFiled.files[0]);
});

Step-by-Step Workflow

  1. Users open the page.
  2. Files can be clicked to select or dragged into the area.
  3. Selected files immediately show name and size.
  4. The Cancel button clears selection.

Benefits

  • Interactive and modern UX
  • Real-time file feedback
  • Fully responsive design
  • Maintainable and extendable code
  • Easy integration with backend systems

Conclusion

Creating a custom drag-and-drop file uploader with HTML, CSS, and By incorporating JavaScript, we can make the upload process more interactive and responsive for users. It replaces boring file input buttons with a modern, intuitive interface.

You can further improve it by adding:

  1. File type restrictions
  2. Image previews
  3. Upload progress bars
  4. AJAX/Fetch API for real-time uploads

By implementing this, your website looks professional, user-friendly, and modern.

Live Demo