JSFiddle - React, Tailwind, and code Playground
HTML
<form id="upload-images-form" enctype="multipart/form-data" method="post">
<h1>Upload Your Images</h1>
<div id="drop-zone" class="drop-zone flex">
<p class="td text-center">DRAG AND DROP IMAGES HERE</p>
<p class="td text-center" style="margin: 0">Or</p>
<p class="tl text-center select-files text-bold pointer">Select Files</p>
</div>
<input id="standard-upload-files" style="display:none" style="min-width: 100%" type="file" name="standard-upload-files[]" multiple>
<input type="submit" name="submit-images" id="submit-images" value="SUBMIT IMAGES">
<div id="show-selected-images"></div>
</form>
CSS
body {
margin: 0;
display: flex;
justify-content: center;
width: 100%;
}
form {
width: 30%;
}
#drop-zone {
border: 1px dashed;
width: 100%;
padding: 1rem;
margin-bottom: 1rem;
}
.select-files {
text-decoration: underline;
cursor: pointer;
}
/* images that are previewed prior to form submission*/
.drop-zone__thumb {
width: 200px;
height: auto;
display: block;
}
#remove-x {
width: 1rem;
height: 1rem;
}
#submit-images {
margin: 1rem 0;
}
#show-selected-images {
display: flex;
}
JavaScript
const files = []; // an Array to hold our files, accessible to all our functions below
const dropZone = document.getElementById("drop-zone"),
showSelectedImages = document.getElementById("show-selected-images"),
fileUploader = document.getElementById("standard-upload-files");
dropZone.addEventListener("click", (evt) => {
// assigns the dropzone to the hidden input element so when you click 'select files' it brings up a file picker window
fileUploader.click();
});
// Prevent browser default when draging over
dropZone.addEventListener("dragover", (evt) => {
evt.preventDefault();
});
fileUploader.addEventListener("change", (evt) => {
// update the list of files
// you could also make it push() these files instead
// and add a 'remove' button to splice them out`
files.push(...fileUploader.files);
[...fileUploader.files].forEach(updateThumbnail);
});
dropZone.addEventListener("drop", (evt) => {
evt.preventDefault();
const dropped_files = evt.dataTransfer.files;
if (dropped_files.length) {
files.push(...dropped_files);
}
[...dropped_files].forEach(updateThumbnail);
});
// updateThumbnail function that needs to be able to handle multiple files
function updateThumbnail(file) {
if (file.type.startsWith("image/")) {
let uploadImageWrapper = document.createElement("article"),
removeImage = document.createElement("div"),
thumbnailElement = new Image();
// 'x' that deletes the image
removeImage.classList.add("remove-image");
removeImage.innerHTML =
'<svg id="remove-x" viewBox="0 0 150 150"><path fill="#000" d="M147.23,133.89a9.43,9.43,0,1,1-13.33,13.34L75,88.34,16.1,147.23A9.43,9.43,0,1,1,2.76,133.89L61.66,75,2.76,16.09A9.43,9.43,0,0,1,16.1,2.77L75,61.66,133.9,2.77a9.42,9.42,0,1,1,13.33,13.32L88.33,75Z"/></svg>';
// image thumbnail
thumbnailElement.classList.add("drop-zone__thumb");
thumbnailElement.src = URL.createObjectURL(file);
// do not forget to revoke the blob:// URL when the...