JSFiddle - React, Tailwind, and code Playground

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/rangy/1.2.3/rangy-core.js"></script>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse imperdiet egestas ornare. In et ultricies magna. Curabitur viverra felis nibh, nec dictum felis vulputate id. Proin tincidunt dolor et tempor fringilla. Curabitur sodales auctor neque, ut imperdiet mauris mattis et. Phasellus vestibulum volutpat sem. Quisque non pretium arcu. Sed et condimentum velit, sit amet auctor nibh. Curabitur blandit, quam et cursus hendrerit, ante erat volutpat eros, in maximus libero odio vel neque. Vivamus convallis pellentesque viverra. Duis diam nulla, varius nec elementum aliquet, dignissim sit amet eros. Mauris sit amet porttitor urna. Nullam iaculis leo volutpat dolor fermentum, dignissim placerat nisi luctus. Nunc at mattis diam.

CSS

.marker {
    width: 2px;
    height: 1em;
    background-color: #F01B00;
    position: absolute;
    cursor: pointer;
}

.handle {
    position: absolute;
    width: 10px;
    height: 10px;
    background-color: #F01B00;
}

.handle-start {
    right: -8px;
    top: -10px;
    box-shadow: #555 1px 1px 1px;
}

.handle-end {
    left: -8px;
    bottom: -10px;
    box-shadow: #555 -1px -1px 1px;
}

JavaScript

(function (document, $) {
// We create 2 markers to reuse throughout.
var marker1 = createMarker(true);
var marker2 = createMarker(false);


// Inserts a marker into the document based on the current selection.
// isBefore: true if this is the start marker, otherwise false.
// Inspired by https://stackoverflow.com/a/8288313/604687
// Inspired by https://stackoverflow.com/a/1589912/604687
function insertMarker (isBefore) {
    var range;
    
    if (window.getSelection) {
        // IE9+ and non-IE
        var sel = window.getSelection();
        
        alert(sel);
        
        if (sel.getRangeAt) {
            range = window.getSelection().getRangeAt(0);
            range.collapse(isBefore);
        }
    } else if (document.selection && document.selection.createRange) {
        // IE < 9
        range = document.selection.createRange();
        range.collapse(isBefore);
    }
    
    // Create the marker element and insert it into the DOM.
    if (range) {
        range.insertNode(createMarker(isBefore));
    }
}


// Returns a new marker DOM object.
// isBefore: true if this is the start marker, otherwise false.
function createMarker (isBefore) {
    var marker = document.createElement('span');
    marker.className = 'marker';
    marker.id = (isBefore ? 'marker1' : 'marker2');
    
    var handle = document.createElement('div');
    handle.className = 'handle';
    marker.appendChild(handle);
    
    if (isBefore) {
        handle.className += ' handle-start';
        marker1 = marker;
    }
    else {
        handle.className += ' handle-end';
        marker2 = marker;
    }
    
    return (isBefore ? marker1 : marker2);
}


// Returns a specific marker DOM object.
// isBefore: true if this is the start marker, otherwise false.
function getMarker (isBefore) {
    return (isBefore ? marker1 : marker2);
}


// Returns the currently selected text.
// From https://stackoverflow.com/a/5379408/604687
function getSelectionText () {
    var text = '';
    
...