tutorials
How to add a highlighter underline to Shopify headlines (no code)
Three ways to highlight text in Shopify — a Pro tag, hand-rolled CSS with absolute ::after, and an inline span hack. Working code for every 2.0 theme.

A marker-style highlight under one word in your H1 is the cheapest design upgrade in the Shopify catalogue. It directs the eye exactly where you want it, breaks up a wall of grey text, and signals that someone — anyone — thought about the page for more than four minutes. The catch is that most tutorials hand you a background-color: yellow rectangle that looks like a 1998 Word document. This guide walks through three ways to do it properly — animated, brand-coloured, and accessible — and tells you exactly where each one falls over.
TL;DR
- Fastest: install Pulsar and wrap a word in
$h{color: #facc15}word$. Animated SVG draw-on, scroll-triggered, reduced-motion-safe. ~30 seconds. - Free + manual: add a
.markerclass to your theme stylesheet with an absolutely positioned::afterpseudo-element and ascaleXtransition. Works, but you'll fight Shopify's HTML sanitizer and every theme update. - One-off: paste a
<mark>or<span style="background:...">straight into a Rich Text section. Easiest for a single hero headline; hideous if you have more than one.
The three approaches, side by side
| Approach | Time to ship | Animated draw-on | Respects `prefers-reduced-motion` | Survives theme updates | Cost |
|---|---|---|---|---|---|
Pulsar $h{...} tag | ~30 seconds | Yes, scroll-triggered | Yes, built in | Yes | Pulsar Pro |
Custom CSS ::after | 20–30 minutes | Yes, if you write the JS | Only if you add the media query | Often not | Free |
Inline <mark> / span | ~30 seconds | No | N/A (no motion) | Yes, until your theme sanitises it | Free |

Approach 1 — The no-code path (Pulsar $h{...})
Pulsar's highlight tag wraps a word in a <pulsar-highlight> custom element. The runtime injects an SVG marker stroke as an ::after-style overlay, sets its pathLength, and uses an IntersectionObserver to play the draw-on animation once the headline scrolls into view. You don't write any of that — you write $h{color: #facc15}word$.
- Install Pulsar from the Shopify App Store. The highlight tag lives on the Pro plan.
- Enable the Pulsar Inline app embed in your theme editor (one toggle under Theme settings → App embeds).
- Edit any headline that's matched by your configured selectors (default:
h1, h2, p). Wrap a word:$h{color: #facc15; opacity: 0.7}standout$. - Save and reload the storefront. The marker draws in as the headline enters the viewport.
We make $h{color: #facc15; opacity: 0.8}beautiful$ candlesEvery attribute the underlying web component accepts is exposed in the tag. The most common ones:
color— any CSS colour. Hex, named,rgb(...), or a CSS variable from your theme.opacity—0to1. The default (0.4) looks like a faded marker; bump it to0.8for a more confident stroke.data-stroke-width— defaults to20. Lower numbers (8–12) read as a fine-liner; higher numbers (25+) as a chisel marker.is-animated—trueorfalse. Turn the draw-on off for above-the-fold static use.duration— animation length in seconds. Default3.2. Anything under1.0looks twitchy.effect-id— picks which highlight curve to render (1 by default; more shipped over time).

Approach 2 — Custom CSS with an absolute ::after
If you don't want to install an app, you can fake the effect with a pseudo-element that sits behind the text. The trick is to position it absolutely, give it the visual character of a marker stroke (rounded ends, slightly off-axis), and animate transform: scaleX(...) from 0 to 1 so it appears to draw left-to-right. A static background-color won't get you there — it'll look like a hyperlink from 2003.
Step 1 — Add the highlight utility class
.marker {
position: relative;
display: inline-block;
/* Make sure the pseudo-element doesn't push siblings around */
isolation: isolate;
}
.marker::after {
content: "";
position: absolute;
left: -0.05em;
right: -0.05em;
bottom: 0.05em;
/* The marker stroke itself */
height: 0.45em;
background: #facc15;
opacity: 0.7;
border-radius: 0.25em 0.6em 0.2em 0.5em; /* uneven = hand-drawn */
z-index: -1;
/* Draw-on animation */
transform-origin: left center;
transform: scaleX(0);
transition: transform 0.9s cubic-bezier(0.65, 0, 0.35, 1);
}
.marker.is-visible::after {
transform: scaleX(1);
}
@media (prefers-reduced-motion: reduce) {
.marker::after {
transition: none;
transform: scaleX(1);
}
}Step 2 — Wire up the scroll trigger
CSS alone can't tell when a headline enters the viewport. You need a small IntersectionObserver snippet that toggles the is-visible class. Drop this in assets/theme.js (Dawn) or your equivalent global script:
(() => {
const els = document.querySelectorAll(".marker");
if (!els.length) return;
// Respect the OS-level setting. No observer, no animation — just paint it.
const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
if (reduce) {
els.forEach((el) => el.classList.add("is-visible"));
return;
}
const io = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add("is-visible");
io.unobserve(entry.target);
}
});
},
{ threshold: 0.4, rootMargin: "0px 0px -10% 0px" }
);
els.forEach((el) => io.observe(el));
})();Step 3 — Wrap the word in the section template
Find the section template that renders the headline you want to mark. For a homepage banner in Dawn that's sections/image-banner.liquid; for a product title it's sections/main-product.liquid. You can't wrap from the theme editor — the Rich Text field strips custom classes — so the wrapping has to live in Liquid:
<h1>We make <span class="marker">beautiful</span> candles</h1>Approach 3 — Inline <mark> or span hack in Rich Text
For a one-off — a single hero headline you'll never iterate on — you can paste raw HTML into a Rich Text section's <> source view. The native HTML element for this is <mark>, which has the bonus of semantic meaning (it announces "highlighted" to screen readers). Most themes style it as a yellow box by default, which you can override inline:
<h2>We make <mark style="background:#facc15;padding:0.1em 0.2em;border-radius:0.2em">beautiful</mark> candles</h2>Or, if you want the marker-stroke look without the JS, a span with a linear-gradient background tracked to the bottom of the line:
<h2>We make <span style="background:linear-gradient(180deg,transparent 65%,#facc15 65%);padding:0 0.1em">beautiful</span> candles</h2>Picking a highlight colour that doesn't look like a 2017 SaaS deck
The default for marker highlights is school-bus yellow, and there's a reason — it has the highest contrast against white without darkening the text underneath. But it also reads as "generic landing page" if every brand on the internet uses it. A few rules that age better:
- Borrow from your brand palette, then desaturate. If your buttons are emerald
#10b981, your highlight should be a faded emerald (#10b981atopacity: 0.35) — not pure yellow. Visual consistency outperforms novelty every time. - Neon is for premium brands, not budget. Hot pink, electric green, and acid yellow read as expensive only if the rest of the page is restrained. On a busy storefront they read as a sale banner.
- Cool tones for premium, warm for energy. Highlighting in a soft lavender or pale blue signals editorial/luxury. Highlighting in orange or yellow signals urgency.
- Always test at `opacity: 0.6–0.8`. Solid
1.0highlights compete with the text. A slight transparency lets the typography breathe. - Avoid red unless you mean it. A red marker stroke under a word reads as an error or a strike-through, not a highlight. Use amber instead.

Accessibility — what to actually do
A highlight is one of the few text effects that can improve accessibility instead of harming it, but only if you respect a few rules:
- Use `<mark>` semantically where you can. Screen readers announce it as "highlighted [word]" — useful context. The Pulsar
$h{...}tag does not currently emit<mark>, so if you want the announcement, wrap the entire pulsar tag in<mark>:<mark>$h{color: #facc15}word$</mark>. - Test contrast with the highlight removed. Your text must pass WCAG AA contrast against the page background without the highlight present — never against the highlight itself. The highlight is decorative.
- Honour `prefers-reduced-motion`. Pulsar does this automatically; the CSS approach above includes the media query. Some users get motion-sick from draw-on animations.
- Don't rely on highlight as the only signal. If a highlight is conveying critical information ("this is on sale"), pair it with text — "Sale: …". Colour-blind users may not see the highlight at all.
Common bugs and how to fix them
+The highlight covers the text instead of sitting behind it
z-index. Set it to -1 and add isolation: isolate to the parent. If you're using Pulsar and seeing this, your theme has a global position: static rule that's breaking the shadow-DOM positioning — file a bug with your shop URL and we'll patch it.+The draw-on animation plays once and then disappears on a soft reload
IntersectionObserver fires on the first viewport intersection only, by design. If you're loading the page already scrolled past the headline, the observer never triggers. Lower the threshold to 0.01 or remove the unobserve line so it can re-fire.+The marker is visible in the admin preview but missing on the live store
+My highlight extends past the end of the word on long lines
box-decoration-break: clone; -webkit-box-decoration-break: clone; to the highlighted span. Each visual line then gets its own marker fragment instead of one stretched across all of them.+Will Google penalise me for animated text effects?
<h1>We make beautiful candles</h1> — regardless of whether beautiful has a marker overlay. The Core Web Vitals impact of a single <pulsar-highlight> is negligible (one SVG, ~200 bytes, no layout shift if you let the runtime size the parent first).Which approach should you pick?
If you want an animated marker highlight that survives every theme update and never makes you touch CSS — install Pulsar and use $h{...}. If you're a developer shipping a custom theme for a client and the highlight needs to be free forever — Approach 2, knowing you've signed up to maintain the CSS and the IntersectionObserver yourself. If you only need to highlight one word on one page and never again — Approach 3, knowing your theme's sanitiser might delete it on save.
For more on what the rest of the Pulsar syntax can do — gradients, circles, animated draws — see the gradient text guide and the animated circle effect walk-through. The full tag reference lives in the Pulsar syntax cheatsheet.
About the author
The Pulsar team
Shopify text styling
Pulsar is the easiest way to stylize headlines in your Shopify store — colors, gradients, animated highlights and circles, no theme code required.
Install Pulsar — Free


