A drop-in collection of CSS-based text highlight effects — markers, underlines, scribbles, strikethroughs, and an animated sweep. One CSS file, 24 classes, zero JS.
goboldlyforward.github.io/highlight — every effect on one page, with light + dark previews and a theming section.
Ships one stylesheet. Drop a class on any inline element — <span>, <mark>, <em> — and the highlight applies. Multi-line wraps are handled automatically via box-decoration-break: clone. Color is themable through a single CSS custom property.
npm install @goboldlyforward/highlight.css@import "@goboldlyforward/highlight.css/highlight.css";Or link it straight from a CDN — no build step:
<link rel="stylesheet" href="https://unpkg.com/@goboldlyforward/highlight.css/highlight.css"><p>The quick brown fox jumps over <span class="hl-marker">the lazy dog</span>.</p>
<p>That option is <span class="hl-strike">off the table</span>.</p>
<p>Read the <span class="hl-underline-dotted">fine print</span> first.</p>
<p>Try this <span class="hl-scribble">hand-drawn squiggle</span>.</p>Highlighter-pen style backgrounds. CSS gradients, no images.
| Class | Look |
|---|---|
.hl-marker |
Classic yellow stripe across the lower portion |
.hl-marker-thin |
Thin band hugging the baseline |
.hl-marker-tall |
Covers most of the x-height |
.hl-marker-full |
Full block behind the text |
.hl-marker-pen |
Translucent — lets the page tint through |
.hl-marker-gradient |
Fades horizontally left → transparent |
.hl-marker-double |
Two stripes, top and bottom |
.hl-marker-uneven |
Slanted top edge |
.hl-marker-fade |
Soft bottom edge |
Background-gradient lines and native text-decoration variants.
| Class | Look |
|---|---|
.hl-underline |
Clean thin underline |
.hl-underline-thick |
Heavier underline for stronger emphasis |
.hl-underline-double |
Two parallel lines (native text-decoration: double) |
.hl-underline-wavy |
Spellcheck-style squiggle (native wavy) |
.hl-underline-dashed |
Dashed line for hints / glossary cues |
.hl-underline-dotted |
Dotted line, soft annotation |
Hand-drawn underlines via tileable SVG paths. Dark-mode-aware — stroke swaps from #333 to #ccc when an ancestor has [data-theme="dark"].
| Class | Look |
|---|---|
.hl-scribble |
Soft hand-drawn wavy line |
.hl-scribble-rough |
Bigger amplitude, irregular spacing |
.hl-scribble-zigzag |
Sharp angular zigzag |
.hl-scribble-loose |
Slow, bouncier squiggle |
.hl-scribble-double |
Two overlapping scribbles, offset |
| Class | Look |
|---|---|
.hl-strike |
Standard line-through |
.hl-strike-thick |
Heavier line-through |
.hl-strike-wavy |
Wavy strike, playful tone |
.hl-strike-soft |
Gradient band centered on the line |
| Class | Look |
|---|---|
.hl-sweep |
Marker that sweeps in left → right on :hover or when you add .is-active |
Pair hl-sweep with an IntersectionObserver for scroll-triggered reveals. Respects prefers-reduced-motion automatically.
Two custom properties drive every effect.
:root {
--hl-color: #fff59d; /* highlighter yellow (markers, sweep) */
--hl-stroke: currentColor; /* line color for gradient underlines */
}Override anywhere in the cascade — globally, per-section, or inline.
<!-- Inline tint for one element -->
<span class="hl-marker" style="--hl-color: #ffb3d9">pink note</span>
<!-- Per-section accent -->
<aside style="--hl-color: #c8e6c9">
Everything inside this aside uses mint.
</aside>For scribbles, color is baked into the SVG (since CSS variables can't be substituted into url() data URIs). To retint, override background-image on the element with your own SVG.
Opt in by setting data-theme="dark" on any ancestor (commonly <html>):
<html data-theme="dark">…</html>That swaps --hl-color to a brighter yellow (#fde047) so markers and sweeps pop on dark backgrounds, and switches scribble strokes from #333 to #ccc. No prefers-color-scheme auto-detection — the library stays predictable; the choice is yours.
To follow the system preference automatically, add a tiny inline script before the stylesheet so there's no flash:
<script>
if (matchMedia('(prefers-color-scheme: dark)').matches) {
document.documentElement.setAttribute('data-theme', 'dark');
}
</script>Or wire it to a toggle and persist the choice — see the demo source for a ~20-line example.
Modern evergreen browsers (Chrome, Edge, Firefox, Safari). box-decoration-break: clone and color-mix() are required for full fidelity; falls back gracefully where they're absent.
MIT — see LICENSE.