data-underline

Living Gateways to the World's Most Coveted Escapes.

Add one attribute to any word, link or phrase. Every stroke is generated fresh — its own tilt, pressure and ragged edge — then drawn in like a marker.

Variants

Three ways to mark it

The attribute value picks the style. Leave it empty for the default brush stroke.

A slow morning in the Dolomites

data-underline

Nothing feels quite like it

data-underline="double"

Private villas with ocean views

data-underline="highlight"
Opacity

Always behind the text, at any strength

Ink sits behind every letter in the surrounding text, so a highlight's overshoot never covers the word before it. Set transparency with an 8-digit hex color, or with data-underline-opacity.

An island known for its slow sunsets

style="--underline-color: #ffb38a8c"

Every room opens to the garden

data-underline-opacity="0.45"
Smart defaults

Links draw on hover, phrases follow the line

Links get a hover trigger automatically and wipe away when you leave. Long phrases that wrap get one stroke per line, drawn one after the other as if by hand.

Wake up in a Kyoto ryokan, lunch at a cliffside taverna, and end the day on the deck of a gulet.

Hover or tab to the links.

Some places stay with you. The kind of light that makes you forget to check the time is one of them.

Resize the window — the strokes re-flow with the text.

Dynamic

Add the attribute at runtime

A MutationObserver picks up any element that gains (or loses) data-underline — CMS lists, Finsweet attributes, tabs, whatever renders later. Click words below to toggle the attribute live.

From hidden coves in Mallorca to quiet terraces above Lake Como, we curate stays that feel less like hotels and more like belonging somewhere.

Each click sets or removes data-underline on a <span>.

Usage

Drop-in for Webflow

Paste the CSS block in the page or site <head> and the script before </body>. Then add custom attributes in the Designer.

AttributeValuesNotes
data-underline"" · brush · double · highlightTurns the effect on. Any other value falls back to brush.
data-underline-triggerscroll · load · hover · manualDefault is scroll, or hover on links and buttons.
data-underline-delaymsWait before drawing.
data-underline-durationmsOverride. By default duration scales with stroke length.
data-underline-opacity0–1 or %Per-element opacity. Or put alpha in the color itself: #d9c7ff80.
data-underline-seednumberLock a specific stroke shape.
data-underline-hover(on an ancestor)Hover this parent to draw underlines inside it — e.g. a card.
/* Style per element, per class, or globally */
.footer-link { --underline-color: #ffc8a6; --underline-thickness: .14; }
.tag-mark    { --underline-color: #d9c7ff80; }   /* 8-digit hex = 50% alpha */
.soft        { --underline-opacity: .6; }

// JS API (window.HandUnderline)
HandUnderline.draw(el)      // draw one (works with trigger="manual")
HandUnderline.erase(el)     // wipe it away
HandUnderline.replay()      // replay everything (or pass an element)
HandUnderline.refresh()     // regenerate after changing size/thickness vars