If you look at the SSCCE below you'll see that when files are dragged from outside my drop-zone, the CSS attribute --fade-time is modified and the target begins to pulsate so the user knows it's time to drop their bundle. The problem is that it doesn't seem to be 100% reliable with the dragEnter event not always firing.
I can try deferring the event till the "container" element and then checking target.id="div1". Or maybe a "Once only" event dragOver to do what dragEnter used to do?
Any ideas on how to make the behaviour deterministic would be great.
document.addEventListener("DOMContentLoaded", (e) => { document.addEventListener('drop', function(e) { e.preventDefault() }) document.addEventListener('dragenter', function(e) { e.preventDefault(); e.dataTransfer.dropEffect = "none" }) document.addEventListener('dragover', function(e) { e.preventDefault(); e.dataTransfer.dropEffect = "none" }) const dropZone = document.getElementById("container") dropZone.addEventListener("dragenter", (e) => { console.log("In enter " + dropZone) e.dataTransfer.dropEffect = "copy" e.preventDefault() e.stopPropagation() document.getElementById("div2").style.setProperty("--fade-time", "2.0s") }) dropZone.addEventListener("dragover", (e) => { console.log("In over " + dropZone) e.dataTransfer.dropEffect = "copy" e.preventDefault() e.stopPropagation() }) dropZone.addEventListener("dragleave", (e) => { console.log("In leave") e.dataTransfer.dropEffect = "none" e.preventDefault(); document.getElementById("div2").style.removeProperty("--fade-time") }) dropZone.addEventListener("drop", catchFiles) }) function catchFiles(e) { e.preventDefault(); document.getElementById("div2").style.removeProperty("--fade-time") console.log("File(s) dropped"); let fileHolder = new FormData() let fileCount = 0 if (e.dataTransfer.items) { // Use DataTransferItemList interface to access the file(s) [...e.dataTransfer.items].forEach((item, i) => { // If dropped items aren't files, reject them if (item.kind === "file") { const file = item.getAsFile() console.log(`… file[${i}].name = ${file.name}`) fileHolder.append("file" + i, file, file.name) fileCount++ } }); } else { // Use DataTransfer interface to access the file(s) [...e.dataTransfer.files].forEach((file, i) => { console.log(`… file[${i}].name = ${file.name}`); fileHolder.append("file" + i, file, file.name) fileCount++ }); } if (fileCount == 0) { alert("Zero files received") return } alert("got " + fileCount + " files") return const abortControl = new AbortController(); const signal = abortControl.signal; const fetchOpts = { signal: signal, method: 'POST', body: fileHolder, cache: "no-cache" }; const response = fetch("https://localhost:7196/upload/PostFormData", fetchOpts).catch( err => { console.log("Upload failed: " + err.message); return }); if (signal.aborted) { alert("Cancelled") return } } #container { position: relative; display: flex; width: 120px; height: 120px; padding: 10px; border: 1px solid black; } #div1 { position: absolute; top: 0; left: 0; display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; background-color: lightblue; cursor: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 300 300'><path fill='%23FFF' stroke='%23E50024' stroke-width='50' d='M150 25 a125 125 0 1 0 2 0z m 2 100 a25 25 0 1 1-2 0z'/></svg>"), auto; } #div2 { --fade-time: 0; position: absolute; top: 0; left: 0; width: 100%; height: 100%; opacity: 0%; background-repeat: no-repeat; background-position: center; background-size: cover; background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 300 300'><path fill='%23FFF' stroke='%23E50024' stroke-width='50' d='M150 25 a125 125 0 1 0 2 0z m 2 100 a25 25 0 1 1-2 0z'/></svg>"); animation: pulseImage var(--fade-time) infinite; } body>p { color: red; } div>p { font-weight: bold; } @keyframes pulseImage { from { opacity: 0; } to { opacity: 0.7; } } <h1>File Drop Upload Example</h1> <p>Drag your file(s) into the Drop Zone</p> <div id="container"> <div id="div1"> <p>File Drop Zone</p> </div> <div id="div2"></div> </div>