JSFiddle - React, Tailwind, and code Playground

HTML

<div id="draggablesInsideMe">
    <span class="draggableThing">Drag me!</span>
</div>
<hr />
<div id="targetsInsideMe">
    <span class="target">Drop on me 1!</span>
    <span class="target">Drop on me 2!</span>
    <span class="target">Drop on me 3!</span>
    <span class="target">Drop on me 4!</span>
    <span class="target">Drop on me 5!</span>
    <span class="target">Drop on me 6!</span>
    <span class="target">Drop on me 7!</span>
    <span class="target">Drop on me 8!</span>
    <span class="target">Drop on me 9!</span>
    <span class="target">Drop on me 10!</span>
    <span class="target">Drop on me 11!</span>
    <span class="target">Drop on me 12!</span>
</div>
Not here!

CSS

div#draggablesInsideMe {
    width: 170px;
    border: 1px black solid;
}
div#targetsInsideMe {
    display: block;
    width: 180px;
    height: 125px;
    border: 1px black solid;
    overflow: auto;
}
span.draggableThing, span.target{
    display: block;
    border: 1px black solid;
    background: gray;
    width: 160px;
    height: 50px;
}

JavaScript

// [email protected]
// MIT Licensed

$(".draggableThing").draggable({
    snap: ".target.inView",
    snapMode: "inner",
    start: function(event, ui) {
                          $(this).css({'overflow-y': visible});  
                        },
                        stop: function(event, ui) {
                           
                        }
});

// TODO: Add a single-entry event queue to this - don't want more than one concurrent execution, but always want to have at an execution start after any event is fired. Shout if you want the reasoning behind this!
var updateVisibleTargets = function() {
    var cont = $("#targetsInsideMe");
    var height = cont.height();
    var scrollPos = cont.scrollTop();

    // Plan is - clear all from being in view, then find the first in view, then mark as active until we find one that's not in view - then drop out.

    // Reset all
    cont.find(".target").removeClass("inView");

    cont.find(".target").each(function (i) {
        var $this = $(this);
        var topOffset = $this.offset().top - $this.height();
        if (topOffset >= 0) {
            console.debug(i+": "+topOffset+" -> "+height);
            if (topOffset > height) {
                return false;
            }
            $this.addClass("inView");
        }
    });
console.debug("------");
    
};
$("#targetsInsideMe").scroll(updateVisibleTargets);
updateVisibleTargets();