Selection and Range
The Selection and Range APIs let you work with selected text and manipulate document ranges programmatically.
The Selection Object
Access the user’s current selection via window.getSelection():
const selection = window.getSelection();
selection.toString() // the selected text (as plain string)
selection.type // "Range", "Caret", or "None"
selection.isCollapsed // true if cursor (no selected text)
selection.rangeCount // number of ranges (usually 0 or 1)
Demo: Reading Selection
HTML
<p id='select-demo'>Select some of this text to see what's selected. Try double-clicking words or dragging to select a range.</p>
<pre id='selection-output' style='background:#f1f5f9;padding:8px;border-radius:4px;'></pre> JavaScript
const out = document.getElementById('selection-output');
document.addEventListener('mouseup', function() {
const sel = window.getSelection();
if (sel.type === 'Range') {
out.textContent =
'Selected:' + sel.toString() + '\\n' +
'length: ' + sel.toString().length + '\\n' +
'isCollapsed: ' + sel.isCollapsed + '\\n' +
'rangeCount: ' + sel.rangeCount;
} else {
out.textContent = 'No text selected (cursor only)';
}
}); Live Output Window
The Range Object
A Range represents a continuous fragment of the document. Get it from a selection:
const range = sel.getRangeAt(0); // first range (usually the only one)
Or create one directly:
const range = document.createRange();
range.setStart(startNode, startOffset);
range.setEnd(endNode, endOffset);
Range Properties
range.startContainer // node where range starts
range.startOffset // offset within start container
range.endContainer // node where range ends
range.endOffset // offset within end container
range.collapsed // true if start === end
range.commonAncestorContainer // deepest common parent of start and end
Range Methods
range.deleteContents() // remove selected content
range.extractContents() // remove and return as DocumentFragment
range.cloneContents() // clone the selected content
range.insertNode(newNode) // insert a node at range start
range.surroundContents(surroundingNode) // wrap range in an element
range.cloneRange() // deep copy
Demo: Working with Range
HTML
<div id='range-demo' style='padding:12px;border:2px solid #6366f1;border-radius:8px;'>
<p id='range-text'>This is a paragraph with <strong>bold</strong> and <em>italic</em> text inside.</p>
</div>
<div style='margin-top:8px;display:flex;gap:8px;flex-wrap:wrap;'>
<button id='highlight-range'>Highlight Selection</button>
<button id='delete-range'>Delete Selection</button>
<button id='wrap-range'>Wrap Selection in <u></button>
</div>
<pre id='range-log' style='background:#f1f5f9;padding:8px;border-radius:4px;'></pre> JavaScript
const log = document.getElementById('range-log');
function getRange() {
const sel = window.getSelection();
if (!sel.rangeCount) {
log.textContent = 'No text selected — select some text first!';
return null;
}
return sel.getRangeAt(0);
}
document.getElementById('highlight-range').onclick = function() {
const range = getRange();
if (!range) return;
const span = document.createElement('span');
span.style.cssText = 'background:#fef9c3;padding:2px 4px;border-radius:3px;';
range.surroundContents(span);
log.textContent = 'Selection highlighted';
};
document.getElementById('delete-range').onclick = function() {
const range = getRange();
if (!range) return;
range.deleteContents();
log.textContent = 'Selection deleted';
};
document.getElementById('wrap-range').onclick = function() {
const range = getRange();
if (!range) return;
const u = document.createElement('u');
range.surroundContents(u);
log.textContent = 'Selection wrapped in underline';
}; Live Output Window
Creating Ranges Programmatically
You don’t need a user selection — create ranges from code:
const p = document.querySelector('p');
const range = document.createRange();
range.setStart(p.firstChild, 0); // start at first char
range.setEnd(p.firstChild, 5); // end at 5th char
range.toString(); // first 5 chars
Demo: Programmatic Range
HTML
<p id='prog-p'>Hello World! This is a paragraph.</p>
<button id='extract-first5'>Extract first 5 chars</button>
<button id='bold-middle'>Bold middle word</button>
<button id='select-programmatic'>Select programmatically</button>
<pre id='prog-log' style='background:#f1f5f9;padding:8px;border-radius:4px;'></pre> JavaScript
const p = document.getElementById('prog-p');
const log = document.getElementById('prog-log');
document.getElementById('extract-first5').onclick = function() {
const range = document.createRange();
range.setStart(p.firstChild, 0);
range.setEnd(p.firstChild, 5);
log.textContent = 'Range text:' + range.toString();
};
document.getElementById('bold-middle').onclick = function() {
const range = document.createRange();
const text = p.firstChild;
const word = 'World';
const start = text.textContent.indexOf(word);
range.setStart(text, start);
range.setEnd(text, start + word.length);
const b = document.createElement('strong');
range.surroundContents(b);
log.textContent = 'Made' + word + 'bold';
};
document.getElementById('select-programmatic').onclick = function() {
const sel = window.getSelection();
sel.removeAllRanges();
const range = document.createRange();
range.selectNodeContents(p);
sel.addRange(range);
log.textContent = 'Selected entire paragraph programmatically';
}; Live Output Window
Selection Events
document.addEventListener('selectionchange', function() {
// fires whenever selection changes
});
Demo: Selection Change Event
HTML
<p id='selection-event-demo'>Select text here and see the event fire. <strong>Try it</strong> with different selections.</p>
<pre id='sel-event-log' style='background:#f1f5f9;padding:8px;border-radius:4px;'></pre> JavaScript
const log = document.getElementById('sel-event-log');
let count = 0;
document.addEventListener('selectionchange', function() {
const sel = window.getSelection();
if (sel.type === 'Range') {
count++;
log.textContent = 'Selection changed #' + count + ':' + sel.toString().substring(0, 50) + (sel.toString().length > 50 ? '...' : '');
}
}); Live Output Window
Range vs Selection
| Concept | What it is |
|---|---|
Selection | What the user has selected (can have multiple ranges) |
Range | A continuous document fragment (building block of selection) |
A selection contains a range. Most of the time there’s one range per selection.
Practical: Highlight Search Terms
Demo: Search Highlight
HTML
<div id='search-demo'>
<input id='search-term' type='text' placeholder='Search term' style='padding:8px;border:1px solid #cbd5e1;border-radius:4px;'>
<button id='search-btn'>Highlight</button>
<button id='clear-highlights'>Clear</button>
<div id='search-text' style='margin-top:8px;padding:12px;background:#f8fafc;border-radius:8px;border:1px solid #e2e8f0;'>
The Document Object Model (DOM) is a programming interface for web documents. It represents the page so that programs can change the document structure, style, and content. The DOM represents the document as nodes and objects.
</div>
<pre id='search-log' style='background:#f1f5f9;padding:8px;border-radius:4px;'></pre>
</div> JavaScript
const searchInput = document.getElementById('search-term');
const container = document.getElementById('search-text');
const log = document.getElementById('search-log');
document.getElementById('search-btn').onclick = function() {
const term = searchInput.value.trim().toLowerCase();
if (!term) return;
// Get original text (remove old highlights first)
const original = container.textContent;
container.innerHTML = '';
// Walk and wrap matches
const parts = original.split(new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\\\]/g, '\\\\$&') + ')', 'gi'));
parts.forEach(part => {
if (part.toLowerCase() === term) {
const mark = document.createElement('mark');
mark.style.cssText = 'background:#fef9c3;padding:2px 4px;border-radius:3px;';
mark.textContent = part;
container.appendChild(mark);
} else {
container.appendChild(document.createTextNode(part));
}
});
log.textContent = 'Found and highlighted ' + Math.floor(parts.length / 2) + ' occurrences of' + term;
};
document.getElementById('clear-highlights').onclick = function() {
container.innerHTML = container.textContent;
log.textContent = 'Highlights cleared';
}; Live Output Window
Key Takeaways
window.getSelection()gets the user’s selection- A
Rangeis a document fragment defined by start and end points setStart(node, offset)andsetEnd(node, offset)define a rangerange.surroundContents(element)wraps the range in an elementrange.deleteContents()andrange.extractContents()remove content- Use
selectionchangeevent ondocumentto track selection changes - Create ranges programmatically to manipulate document sections without user selection