JSFiddle - React, Tailwind, and code Playground

by Graham Dixon

HTML

<div class="container" role="main">

  <h1><a href="/article-url"></a></h1>

  <nav role="navigation">
    <a href="https://css-tricks.com/examples/DragAndDropFileUploading/" class="is-selected">Auto Submit</a>
    <a href="https://css-tricks.com/examples/DragAndDropFileUploading/?submit-on-demand">Submit On Demand</a>
  </nav>

  <form method="post" action="https://css-tricks.com/examples/DragAndDropFileUploading//?" enctype="multipart/form-data" novalidate class="box">


    <div class="box__input">
      <svg class="box__icon" xmlns="http://www.w3.org/2000/svg" width="50" height="43" viewBox="0 0 50 43"><path d="M48.4 26.5c-.9 0-1.7.7-1.7 1.7v11.6h-43.3v-11.6c0-.9-.7-1.7-1.7-1.7s-1.7.7-1.7 1.7v13.2c0 .9.7 1.7 1.7 1.7h46.7c.9 0 1.7-.7 1.7-1.7v-13.2c0-1-.7-1.7-1.7-1.7zm-24.5 6.1c.3.3.8.5 1.2.5.4 0 .9-.2 1.2-.5l10-11.6c.7-.7.7-1.7 0-2.4s-1.7-.7-2.4 0l-7.1 8.3v-25.3c0-.9-.7-1.7-1.7-1.7s-1.7.7-1.7 1.7v25.3l-7.1-8.3c-.7-.7-1.7-.7-2.4 0s-.7 1.7 0 2.4l10 11.6z"/></svg>
      <input type="file" name="files[]" id="file" class="box__file" data-multiple-caption="{count} files selected" multiple />
      <label for="file"><strong>Choose a file</strong><span class="box__dragndrop"> or drag it here</span>.</label>
      <button type="submit" class="box__button">Upload</button>
    </div>


    <div class="box__uploading">Uploading&hellip;</div>
    <div class="box__success">Done! <a href="https://css-tricks.com/examples/DragAndDropFileUploading//?" class="box__restart" role="button">Upload more?</a></div>
    <div class="box__error">Error! <span></span>. <a href="https://css-tricks.com/examples/DragAndDropFileUploading//?" class="box__restart" role="button">Try again!</a></div>
  </form>



  <footer>
    <p><strong>Be sure to try the demo on a browser (e.g. IE 9 and below) that does not support drag&amp;drop file upload. You can also try with a JavaScript support disabled.</strong></p>
    <p>The icon was borrowed from <a href="http://www.flaticon.com/free-icon/outbox_3686"...

CSS

html {}

		body {
		  font-family: Roboto, sans-serif;
		  color: #0f3c4b;
		  background-color: #e5edf1;
		  padding: 5rem 1.25rem;
		  /* 80 20 */
		}

		.container {
		  width: 100%;
		  max-width: 680px;
		  /* 800 */
		  text-align: center;
		  margin: 0 auto;
		}

		.container h1 {
		  font-size: 42px;
		  font-weight: 300;
		  color: #0f3c4b;
		  margin-bottom: 40px;
		}

		.container h1 a:hover,
		.container h1 a:focus {
		  color: #39bfd3;
		}

		.container nav {
		  margin-bottom: 40px;
		}

		.container nav a {
		  border-bottom: 2px solid #c8dadf;
		  display: inline-block;
		  padding: 4px 8px;
		  margin: 0 5px;
		}

		.container nav a.is-selected {
		  font-weight: 700;
		  color: #39bfd3;
		  border-bottom-color: currentColor;
		}

		.container nav a:not( .is-selected):hover,
		.container nav a:not( .is-selected):focus {
		  border-bottom-color: #0f3c4b;
		}

		.container footer {
		  color: #92b0b3;
		  margin-top: 40px;
		}

		.container footer p+p {
		  margin-top: 1em;
		}

		.container footer a:hover,
		.container footer a:focus {
		  color: #39bfd3;
		}

		.box {
		  font-size: 1.25rem;
		  /* 20 */
		  background-color: #c8dadf;
		  position: relative;
		  padding: 100px 20px;
		}

		.box.has-advanced-upload {
		  outline: 2px dashed #92b0b3;
		  outline-offset: -10px;
		  -webkit-transition: outline-offset .15s ease-in-out, background-color .15s linear;
		  transition: outline-offset .15s ease-in-out, background-color .15s linear;
		}

		.box.is-dragover {
		  outline-offset: -20px;
		  outline-color: #c8dadf;
		  background-color: #fff;
		}

		.box__dragndrop,
		.box__icon {
		  display: none;
		}

		.box.has-advanced-upload .box__dragndrop {
		  display: inline;
		}

		.box.has-advanced-upload .box__icon {
		  width: 100%;
		  height: 80px;
		  fill: #92b0b3;
		  display: block;
		  margin-bottom: 40px;
		}

		.box.is-uploading .box__input,
		.box.is-success .box__input,
		.box.is-error .box__input {
		  visibility:...

JavaScript

'use strict';

;
(function(document, window, index) {
  // feature detection for drag&drop upload
  var isAdvancedUpload = function() {
    var div = document.createElement('div');
    return (('draggable' in div) || ('ondragstart' in div && 'ondrop' in div)) && 'FormData' in window && 'FileReader' in window;
  }();


  // applying the effect for every form
  var forms = document.querySelectorAll('.box');
  Array.prototype.forEach.call(forms, function(form) {
    var input = form.querySelector('input[type="file"]'),
      label = form.querySelector('label'),
      errorMsg = form.querySelector('.box__error span'),
      restart = form.querySelectorAll('.box__restart'),
      droppedFiles = false,
      showFiles = function(files) {
        label.textContent = files.length > 1 ? (input.getAttribute('data-multiple-caption') || '').replace('{count}', files.length) : files[0].name;
      },
      triggerFormSubmit = function() {
        var event = document.createEvent('HTMLEvents');
        event.initEvent('submit', true, false);
        form.dispatchEvent(event);
      };

    // letting the server side to know we are going to make an Ajax request
    var ajaxFlag = document.createElement('input');
    ajaxFlag.setAttribute('type', 'hidden');
    ajaxFlag.setAttribute('name', 'ajax');
    ajaxFlag.setAttribute('value', 1);
    form.appendChild(ajaxFlag);

    // automatically submit the form on file select
    input.addEventListener('change', function(e) {
      showFiles(e.target.files);


      //triggerFormSubmit();


    });

    // drag&drop files if the feature is available
    if (isAdvancedUpload) {
      form.classList.add('has-advanced-upload'); // letting the CSS part to know drag&drop is supported by the browser

      ['drag', 'dragstart', 'dragend', 'dragover', 'dragenter', 'dragleave', 'drop'].forEach(function(event) {
        form.addEventListener(event, function(e) {
          // preventing the unwanted behaviours
          e.preventDefault();
    ...