Skip to content

olgv/tool-highlight-round

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

highlight-round

npm version npm bundle size zero dependencies license

Inline text highlights with true rounded corners — including concave (inverted) radii where line-widths step in or out. Pure vanilla JS + SVG. No dependencies. No build step.

highlight-round example


Install

npm install highlight-round

Or via CDN (no build step):

<script src="https://unpkg.com/highlight-round/highlight-round.js"></script>

Quick start

<!-- 1. Load the library -->
<script src="node_modules/highlight-round/highlight-round.js"></script>

<!-- 2. Mark any inline element -->
<p>
  This sentence has a
  <span data-highlight>highlighted phrase that can wrap across lines</span>
  and then continues normally.
</p>

<!-- 3. Initialise -->
<script>
  document.addEventListener('DOMContentLoaded', () => {
    new HighlightRound({ color: '#3B3BFF' }).init('[data-highlight]');
  });
</script>

Per-element colour

<span data-highlight data-highlight-color="#e8394f">red highlight</span>
<span data-highlight data-highlight-color="#1aaa6e">green highlight</span>
<span data-highlight data-highlight-color="#1a1a1a" data-highlight-text-color="#ffffff">dark highlight</span>
<span data-highlight data-highlight-padding-x="20" data-highlight-padding-y="12">extra roomy</span>

Nesting

Highlights can be nested. Edges on the same visual line are automatically aligned flush — no micro-overlap or pixel gaps.

<span data-highlight data-highlight-color="#3B3BFF">
  Outer highlight with
  <span data-highlight data-highlight-color="#e8394f">an inner one</span>
  continuing after.
</span>

Options

All options with their defaults — copy, tweak, go:

const rh = new HighlightRound({
  radius:        14,        // corner radius, convex & concave
  paddingX:      10,        // horizontal padding per line
  paddingY:      6,         // vertical padding per line
  color:         '#3B3BFF', // default fill colour
  textColor:     '#ffffff', // default text colour
  snapThreshold: 10,        // edges within this px range snap flush
  bevel:         0,         // diagonal slant at step corners (0 = sharp)
  forceColor:    false,     // ignore per-element data-highlight-color
});

rh.init('[data-highlight]');

Any option can also be overridden per element via data-highlight-* attributes:

data-highlight-color="…"       <!-- fill colour -->
data-highlight-text-color="…"  <!-- text colour -->
data-highlight-padding-x="…"   <!-- horizontal padding -->
data-highlight-padding-y="…"   <!-- vertical padding -->

API

const rh = new HighlightRound({ radius: 16, color: '#3B3BFF' });

// Highlight all matching elements and watch for layout changes
rh.init('[data-highlight]');

// Highlight a single element (e.g. after a DOM update)
rh.highlight(someElement);

After a significant DOM change affecting multiple elements, trigger a full redraw:

document.getElementById('rh-overlay').remove();
new HighlightRound({ radius: 16 }).init('[data-highlight]');

CSS note

The library is entirely self-contained. The only CSS that helps in edge cases with stacking contexts is:

[data-highlight] {
  position: relative;
  z-index: 1;
}

Add this to your stylesheet if highlighted text ever appears behind other elements.


How it works

  1. Measure — a TreeWalker collects getClientRects() from each non-whitespace text node inside the element, giving one rect per visual line fragment.
  2. Merge — rects on the same line are unioned into one rect per line.
  3. Cross-snap — before drawing, all elements' rects are compared. Rects on the same visual line across different elements are snapped to the same Y/height and to matching X edges within snapThreshold. This keeps nested highlights flush.
  4. Polygon — line rects are traced clockwise into a polygon, with step vertices inserted wherever lines change width.
  5. Classify corners — the 2D cross product of consecutive edge vectors determines whether each corner is convex (sweep=1) or concave (sweep=0).
  6. Draw — each corner becomes an SVG arc. The result is appended to a fixed-position SVG overlay behind the text.

License

MIT

About

Inline text highlights with true rounded corners — including concave (inverted) radii where line-widths step in or out. Pure vanilla JS + SVG. No dependencies. No build step.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors