Bootstrap 5 file uploadBootstrap 5 file upload

Today we are going to build a Bootstrap 5 file upload with drag and drop zone. The need of file upload input filed is very important. Almost every web-based project does need it most of the time. I recently came to this need where I have to implement my project about image processing in python where I have to upload an image and it will be submitted to the backend python API which process the uploaded image and return that processed image along with the results.

I will be discussing this in my upcoming article. But for today’s article, let’s just focus on the Bootstrap 5 plain HTML CSS and JavaScript which is totally about building the front-end. We will rest the discussion of backend for later articles. This article will also be reused in many of my upcoming articles with various technologies where I do need a file uploading drag and drop zone. So, let’s begin.

1. Create Basic Project to get start

First of all, you need to create your project with directory structure or just for the experiment, you can also create a simple index.html or home.html file whatever you prefer. If you are just using the simple HTML file, you can copy the bootstrap 5 boilerplate code to get started from its official website.

Bootstrap 5 Starter Template

Bootstrap 5 starter template is taken from their official getting started guide. I just omitted the unnecessary js includes and leave with a plain simple nice-looking template to get started with bootstrap 5 framework. Here is our basic starter template.

<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- Bootstrap CSS -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

    <title>fypsolutions.com</title>
  </head>
  <body>
    <h1>Bootstrap 5 File Upload with Drag and Drop</h1>

   
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>

  </body>
</html>
Code language: HTML, XML (xml)

Create and run Vanila Js Project with Vite.js

The second option is to create a vanila js project with vite.js framework. It will help us to host the project with npm. We can simply install the node.js package and npm package manager. Navigate to the command prompt with our desired directory and just hit the npm create vite@latest command and it will ask our project name and after that It will ask us to select from different JavaScript front-end frameworks which includes, React, Vue, Preact, Svelte etc. But we are just creating a vanila js project for the sake of simplicity and rest would be left for upcoming usage.

create vite@latest vanila js project
Create vanilla js Vite project

Next, it will asks us the option to choose from TypeScript or JavaScript and we are just choosing the JavaScript.

vite vanila js project JavaScript Selection
Select JavaScript

Once done, it will explain us to navigate to our project directory and to run our project. Here are what commands it will give at the end.

vanila js project running after project creation using vite.js
Running Vanila js project with Vite@latest

So it basically tell us to navigate to the directory and run npm install and after that just hit npm run dev to run our project.

Once we done with it, it will give us the following url which we can copy to our browser and our project is running.

When we hit that URL in our browser, we will get default vite.js template which will look just like this.

Vite.js vanilla js project output in browser just after creating the new project
Vanila js project running in browser with vite@latest

Now Open this project in Visual Studio Code or any of your favorite IDE. It contains the following file structure.

Vanila js vite project file structure
Vite vanila js Project file Structure

Matching index.html with Bootstrap 5 starter template

So, we have main.js file, which includes the counter.js file which ultimately make a simple button counter which we do not need in this project so we will remove everything which is not required. There is also an index.html file where we are going to add our Bootstrap 5 CDN links along with Bootstrap 5 js file links and pooper.js links to match our above Bootstrap 5 starter template. We also have one style.css file which is also included in our index.html file.

Now remove all unnecessary CSS from style.css and main.js file. Also, to match it with the Bootstrap starter template. Here is our final index.html file

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Bootstrap demo</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
    <link href="/style.css" rel="stylesheet" >
  </head>
  <body>
    <h1>Hello, world!</h1>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>
    <script type="module" src="/main.js"></script>
  </body>
</html>Code language: HTML, XML (xml)

and this is now what our main page looks like.

We can also add the bootstrap to our Which recommends adding Bootstrap to your project with npm package manager. With the help of official Bootstrap Vite setup guide. So, all you have to do is to navigate to the command prompt and hit the following commands to install the Bootstrap and popper to your vite.js based vanilla js project.

2. Create Bootstrap 5 File Upload Input Field

Before jumping into the drag and drop file upload component, let’s start with a basic Bootstrap 5 file upload input field. We can navigate to bootstrap 5 templates for the file upload examples and grab one of basic examples in our use case. This is what our basic file upload input field code looks like.

 <div class="container py-4 px-3 mx-auto">
      <h1>Hello, Bootstrap and Vite!</h1>
      <div class="mb-3">
        <label for="formFileMultiple" class="form-label">Multiple files input example</label>
        <input class="form-control" type="file" id="formFileMultiple" multiple>
      </div>
      <button class="btn btn-primary">Primary button</button>
    </div>

Code language: HTML, XML (xml)

Horizontal and Vertical Align Center Div

Let’s create a center div with file input. Also make the submit button form-control to make it full width. .d-flex class is used to make the mx-auto and my-auto classes which will align the div in center as horizontal and vertically. Bootstrap is using the flex box so we need to mention this class. We also added border border-4 border-primary classes to apply the border. Once everything is done the simple file upload code will be this.

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

<head>
  <meta charset="utf-8">
  <link rel="icon" type="image/svg+xml" href="/vite.svg" />

  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Bootstrap demo</title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet"
    integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
  <link href="/style.css" rel="stylesheet">
</head>

<body class="vh-100 d-flex">
  <div class="border border-4 border-primary p-3 my-auto mx-auto">
    <div class="container py-4 px-3 mx-auto ">
      <h1>Bootstrap 5 File Upload</h1>
      <div class="mb-3">
        <label for="formFileMultiple" class="form-label">Multiple files input example</label>
        <input class="form-control" type="file" id="formFileMultiple" multiple>
      </div>
      <button class="btn btn-primary form-control">Submit</button>
    </div>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"
    integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4"
    crossorigin="anonymous"></script>
  <script type="module" src="/main.js"></script>
</body>

</html>Code language: HTML, XML (xml)

We apply vh-100 to make this view port 100vh to take the full height. Which will enable the vertically center align div in Bootstrap 5. Here is our final look.

Bootstrap 5 file upload

3. Drag and Drop Area Creation

The first step is to give your drag and drop div an ID. In my case, I am calling it an id='drop-area'. I am giving this id to the most outer div which is bordered. So, everything inside this bordered area is considered as Drag and Drop Area. We can apply little CSS for the drop-area id. We can also apply the dashed border for this.

Modify style.css file:

#drop-area {
    border: 2px dashed #ccc; /* Dashed border with a light gray color */
    padding: 20px; /* Add padding for better visibility */
    text-align: center; /* Center text horizontally */
    cursor: pointer; /* Set cursor to pointer to indicate interaction */
  }

  #drop-area.highlight {
    border-color: #007bff; /* Highlighted border color */
    background-color: #f0f8ff; /* Highlighted background color */
  }Code language: CSS (css)

Apply drop-area class to div:

Our drop-area div will look be modified with these attributes.

<div class=" p-3 my-auto mx-auto" id="drop-area">
</div>
Code language: HTML, XML (xml)

Quick Style change summary:

Now the main changes that we did are.

  • Reduced border size to 2px
  • Make border dashed
  • Apply light gray color to the border instead of bootstrap primary blue color.
  • Changed the cursor to pointer when it enters into the drop zone area.
  • Created a new drop-area.heighlight class to apply the highlight color of border and background.

4. HTML Drag and Drop API

Now we are going to focus on Drag and Drop behavior, which we will control through the JavaScript. We need to apply the JavaScript from our <script> tag or from the main.js file which we included inside our index.html file. If you want to know the basics of HTML Drag and Drop API (w3schools.com) This tutorial is very helpful to understand the basics. We will just focus on the JavaScript Behavior overriding here.

In HTML we can make any element to be dragged and any element can accept the drop. We just have to enable the respective attributes of that element. There are some methods which handles this behaviour. For example, <div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>

Here the ondrop event and the ondragover event are making this div accepting some data to be dropped to them. These events are being captured in custom JavaScript functions drop(event) and allowDrop(event) respectively.

5. JavaScript Drag-and-Drop Logic

We need to handle the drag and drop logic in JavaScript. So let’s move to the main.js file. We can manipulate Document Object Model (DOM) to interact with HTML elements using JavaScript. This way, we can easily override the default drag and drop behavior and make it possible to handle file drag and drop to handle file inputs.

Get drop-area Element by ID

First of all we need to get the reference of HTML elements which are handling the drag and drop functionality. Here we are just focusing on the drop-area and file-input. Here is how we can get both of them elements by id in our JavaScript.

 <div  id="drop-area">
      <div class="container py-4 px-3 mx-auto ">
        
        <div class="mb-3">
          <label for="file-input" class="form-label">Multiple files input example</label>
          <input class="form-control" type="file" id="file-input" multiple>
        </div>
       
        <button class="btn btn-primary form-control">Submit</button>
      </div>
    </div>

<script>
document.addEventListener('DOMContentLoaded', function () {
    var dropArea = document.getElementById('drop-area');
    var fileInput = document.getElementById('file-input');
    // ... (We will place other JavaScript logic here later)
  });
</script>
Code language: HTML, XML (xml)

Here we are waiting for DOMContentLoaded event to be fired which will wait until the page is properly rendered and all the elements are present there. After that we are just getting our drop-area and the file-input elements by id. This will give us control to both of these items.

Understand Drag-and-Drop Events

Now we need to focus on the related events which will help us to implement the Drag and Drop functionality in the JavaScript. Let’s enlist the events which are related to drag and drop functionality.

  • dragstart,
  • dragend,
  • dragenter,
  • dragover,
  • dragleave,
  • drop.

These are events which are responsible for the complete drag and drop functionalities. Their name clearly states what they, that’s why we will not focus on the basics here. We will just move on to implement the logic.

Prevent default drag behaviors

First step is to prevent the default Drag behaviors. You can simple do this by calling the preventDefaults method like follows.

['dragenter', 'dragover', 'dragleave', 'drop'].forEach(function (event) {
      dropArea.addEventListener(event, function (e) {
        e.preventDefault();
        e.stopPropagation();
      });
    });Code language: PHP (php)

We are calling the preventDefault() and stopPropagation() methods to override the default drag functionality on the list of events in one go. We are simply creating arrays of dragenter, dragover, dragleave and drop events and iterating that array with forEach. Inside this we are adding these events to the dropArea which we reference in the previous. Apply the events with the addEventListener method. This will apply all that events to the dropArea div in the DOM.

Highlight drop area when a file is dragged over

Next thing we will be doing is to highlight the drag area when someone drag some file over it. We will be doing this by overriding the dragenter and dragover events in similar way we did above.

['dragenter', 'dragover'].forEach(function (event) {
      dropArea.addEventListener(event, function () {
        dropArea.classList.add('highlight');
      });
    });
Code language: JavaScript (javascript)

In that eventListener, we are simply adding highlight class to the classList of the dropArea. Which will apply the following CSS to the dropArea.

  #drop-area.highlight {
    border-color: #007bff; /* Highlighted border color */
    background-color: #f0f8ff; /* Highlighted background color */
  }Code language: CSS (css)

Now if you go to your HTML page running in browser and try to drag some file over the drop-area div you will notice the border color is changed to blue due to the application of highlight class to the drop-area div. Here is how it looks in action.

Bootstrap 5 file upload drag and drop class highlight

Remove highlight on dragLeave and drop

Now that the highlight class is applied, we have to remove that class when the dragging is done which could be in two cases, one is when the drag leave the drag area, second is when drop event happens. We can simple do this in the JavaScript using the following code.

['dragleave', 'drop'].forEach(function (event) {
      dropArea.addEventListener(event, function () {
        dropArea.classList.remove('highlight');
      });
    });Code language: PHP (php)

Handles the dropped files:

Now we will handle the dragged files and will show them in a file input. For that we need to update the drop eventListener. Also, we will have to access the dropped files using e.dataTransfer.files and then update the file-input field accordingly. Here’s how we can extend our code.

// Handle dropped files
  dropArea.addEventListener('drop', function (e) {
    e.preventDefault();
    e.stopPropagation();

    // Access the dropped files
    var files = e.dataTransfer.files;

    // Display the files in the file-input field
    fileInput.files = files;

    // Optionally, you can update the label to show the number of files selected
    var fileInputLabel = document.querySelector('.form-label');
    fileInputLabel.innerText = files.length > 0 ? files.length + ' file(s) selected' : 'Multiple files input example';
  });
Code language: JavaScript (javascript)

The files will be displayed like this.

drop file name updated in label

5.File Upload Handling

Now we have to submit the file to the backend. For that purpose we are getting the submit button reference in the JavaScript and adding the submit logic. You can implement this according to your backend code. For a simple demonstration we are just doing it like this.

var submitButton = document.getElementById('submit-button');
 // Handle submit button click event
  submitButton.addEventListener('click', function () {
    // Get the selected files
    var files = fileInput.files;

    // Create FormData object and append files to it
    var formData = new FormData();
    for (var i = 0; i < files.length; i++) {
      formData.append('files[]', files[i]);
    }

    // Use Fetch API to send files to the server
    fetch('/your-upload-endpoint', {
      method: 'POST',
      body: formData
    })
      .then(response => response.json()) // Assuming the server responds with JSON
      .then(data => {
        console.log('Upload successful:', data);
        // Handle the server response as needed
      })
      .catch(error => {
        console.error('Error uploading files:', error);
        // Handle errors
      });
  });
Code language: JavaScript (javascript)

By Abdul Rehman

My name is Abdul Rehman and I love to do Reasearch in Embedded Systems, Artificial Intelligence, Computer Vision and Engineering related fields. With 10+ years of experience in Research and Development field in Embedded systems I touched lot of technologies including Web development, and Mobile Application development. Now with the help of Social Presence, I like to share my knowledge and to document everything I learned and still learning.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.