To restore a text highlight after a reload, save a serializable locator for the selected text, then use it to find that text in the Vue-rendered document and create a fresh browser range. The CSS Custom Highlight API can style that range without adding wrapper elements, but it does not store annotations or restore them for you. Treat selection capture, persistence, and rendering as separate steps.
How persistent highlighting works
A browser Range refers to text nodes in the current document. It is useful for rendering a highlight now, but it is not a durable record of where a passage belongs after a page reload. Instead, persist a serializable locator—such as the selected text plus surrounding context and a content-specific location—and resolve it against the page when the content is available. The web-highlighter project documents this general serialize, store, retrieve, and restore workflow, including for pages built with Vue. It does not establish one canonical locator format or guarantee correct recovery after arbitrary edits.
As an Amazon Associate I earn from qualifying purchases.
- Capture: read the user’s current selection and derive a locator for the relevant content.
- Persist: store the locator in the application’s chosen storage or backend, not the live Range object as if it were durable data.
- Restore: wait until Vue has rendered the relevant content, resolve the locator to current text nodes, and create new ranges.
- Render: register those ranges with the browser’s highlight system, or use a wrapper-based approach if that better fits the application.
Capture the user’s selection
The browser exposes the current selection through window.getSelection(). For reactive Vue UI, VueUse’s useTextSelection tracks selection state and exposes selected text, ranges, rectangles, and the selection itself. It can support a save button or annotation panel, but it does not provide durable storage, locator resolution, or highlight rendering.
Before saving, decide which content the selection belongs to and validate that it is inside that content. A selection can cross element boundaries or include text outside the intended article. Store enough identifying context for your restoration policy; selected text alone can be ambiguous when the same phrase appears more than once.
#1 Best Overall
Render restored ranges without changing the DOM
The CSS Custom Highlight API styles JavaScript-created ranges without inserting span elements into the rendered content. Create a Range for each restored annotation, add the ranges to a Highlight, register it in CSS.highlights under a name, and define the corresponding ::highlight() CSS rule. MDN’s CSS Custom Highlight API documentation describes this mechanism.
const ranges = restoredAnnotations.map(resolveAnnotationToRange);
const highlight = new Highlight(...ranges);
CSS.highlights.set('saved-annotations', highlight);
::highlight(saved-annotations) {
background-color: #ffe66d;
color: inherit;
}
resolveAnnotationToRange represents application-specific work: it must locate the saved passage in the current DOM and return a fresh range. The browser API does not define your saved locator format or decide what to do when content no longer matches.
Coordinate registration and cleanup with Vue
Register highlights only after the relevant Vue content exists. When content or annotation state changes, rebuild or update the ranges deliberately; when the component no longer owns those annotations, remove its named highlight from CSS.highlights. If multiple components share the same name, coordinate ownership so one component does not inadvertently remove another’s highlight. The W3C CSS Custom Highlight API specification explains range behavior and the effects of DOM changes.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Choose how ranges behave when the DOM changes
A live Range has endpoints that browsers adjust as the DOM changes. That can be useful when nodes are modified, but it does not ensure that an annotation still refers to the intended passage; endpoint adjustments can follow changed content. The W3C specification also notes potential performance costs from live updating.
A StaticRange does not update when the DOM changes. If you use one, detect relevant content changes and discard or rebuild stale ranges yourself. Whichever type you choose, treat the persisted locator—not the in-memory range—as the source for restoring an annotation after a reload or a substantial rerender.
Choose between native highlights and wrapper elements
| Consideration | CSS Custom Highlight API | Wrapper-based highlighting |
|---|---|---|
| DOM behavior | Styles ranges without inserting wrapper elements. | Wraps selected text in elements, changing the DOM structure. |
| Vue lifecycle | Still requires registration, updates, and cleanup coordinated with rendered content. | Must account for Vue’s ownership of rendered nodes; the vue-custom-highlight project notes that dynamic framework rendering needs additional lifecycle work. |
| Persistence and changed content | Requires an application-defined locator and restoration policy. | Also requires a restoration policy; wrapping text does not by itself make an annotation durable. |
| Browser support | MDN labels the API Baseline 2025, available across the latest browser and device versions since June 2025; older versions may lack support. | Depends on the library and browser features it uses; verify the chosen implementation for your target browsers. |
| Comparative performance or accessibility winner | Not established by the cited sources. | Not established by the cited sources. |
Choose based on how your application manages rendered content, its required browser matrix, and the behavior you need when text changes. The available documentation does not establish a universal performance or accessibility winner.
Rank #4
Check browser support and plan a fallback
MDN classifies the CSS Custom Highlight API as Baseline 2025, with support across the latest device and browser versions since June 2025. That status is not a promise for every older or embedded browser. Check the browsers your users actually need, and feature-detect the API before registering highlights. If it is unavailable, use a separately selected fallback or show the text without native highlighting; VueUse’s selection composable is not a rendering fallback.
Quick Recap
Best Value
Implementation checks before shipping
- Confirm the saved selection belongs to the intended article or content block.
- Test repeated phrases, missing text, and content edited since the annotation was saved; define how ambiguous or unmatched locators are handled.
- Restore only after Vue has rendered the content used for locator resolution.
- Update or discard ranges after relevant rerenders, and remove registered highlights when their owning annotations or component are removed.
- Test the actual target browser matrix, including the fallback path if older browsers are required.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




