stickies: The DOM Utility That Refuses to Lose Its Target

Aiden Bai’s library treats anchors as identities it can re-find, not nodes it can trust forever.

8 min read • View on GitHub • More from aidenybai

A long document page is being cut apart and rearranged while one annotation stays tethered to the same paragraph. The scene explains stickies' core promise: the relationship survives even when the DOM layout does not.
Stickies is built for pages that move under your feet.

Two years ago, I started ✦ Million.js as a small experiment to make the Virtual DOM faster.

Aiden Bai, Creator of Million.js · Sponsor @aidenybai
Key Takeaways

Most overlay tools assume a target node will stay put. In a real app, that is the first lie the DOM tells you.

Stickies is interesting because it does not just chase coordinates. It tries to keep a sticker attached to the same content even after re-renders, layout shifts, and node replacement.

Why this is harder than it looks

Pinned comments, tooltips, and annotations look simple until the page starts changing. A flex row reorders, React swaps a node, a resize shifts everything, and the old reference is suddenly stale.

Absolute positioning and CSS sticky both solve part of the problem, but neither one preserves the semantic relationship between an overlay and the thing it points to. They know where something was. They do not know how to find it again.

The anchor is not a node. It is an identity.

That is the trick stickies is really built around. The anchor is not treated like a fragile DOM pointer. It is treated like a bundle of clues that can be used to re-identify the target after the tree changes.

The repo research points to three clues working together: CSS selectors, React-aware lookup, and ancestor similarity. If the exact node disappears, stickies can search for the closest structural match instead of giving up.

const anchor = {
  selector: "[data-note='42']",
  reactSelector: 'CommentCard > Paragraph',
  ancestors: ['article', 'section', 'p']
}

const resolved =
  querySelector(anchor.selector) ??
  queryReactTree(anchor.reactSelector) ??
  bestAncestorMatch(anchor.ancestors)

Stickies survives churn by re-acquiring the relationship, not the original node.

That matters because modern UIs rarely move a node in place. They replace it. A library that only caches a reference is one rerender away from being wrong.

How the library keeps the illusion alive

The recovery logic would not matter if the sticker updated sluggishly. Stickies pairs it with observers and a frame-synced render loop so changes land when the browser is ready to paint.

The state is designed to serialize cleanly too, which matters if you want a refresh not to erase the user's attachment work. A UI note should survive more than one paint cycle.

That is the difference between a responsive overlay and a janky one. The library waits for signals, then does the minimum work needed to reconcile position, visibility, and attachments.

When should the sticker hide or flip?

A sticker peeks from behind a clipped frame and then flips its attachment to the other side. The image explains that visibility and available space are part of the placement decision, not just afterthoughts.
Useful overlays know when to get out of the way.

Occlusion detection is the quiet tell. Stickies does not just ask whether the anchor exists, it asks whether it is actually visible and whether the attachment still fits in the viewport. When space runs out, the UI can hide or flip instead of hanging awkwardly off the edge.

What this beats, and what it does not

Stickies is not a replacement for layout primitives. It solves a narrower problem: keeping a floating relationship stable while the DOM stays in motion.

ApproachWhat it handles wellWhat breaksWhy stickies differs
Absolute positioningSimple overlays on static pagesScroll, resize, mutation, and reflow change the mathRe-finds the anchor and reconciles against a live target
CSS stickyPinning inside normal flowIt cannot follow a semantic anchor through re-renderingKeeps an explicit attachment to a chosen node
Manual scroll handlersFull control over placementEdge cases pile up fastUses observers and frame batching instead of constant polling
General overlay libsPlacement and collision handlingAnchor identity disappears after rerenderAdds structural re-acquisition and visibility logic

That is why the library feels more like infrastructure than UI sugar. If your product only needs a badge to sit in one place, simple CSS wins. If your product lets users annotate content that React may replace under them, anchor persistence becomes the feature.

Why Aiden Bai keeps building tools like this

The maintainer through-line is not hard to see. Aiden Bai is known for Million.js, and the same taste for pushing on abstraction boundaries shows up here: take a familiar browser problem and solve it at the layer where it actually breaks.

Hedcut portrait of Aiden Bai on a white background.

That quote is about Million.js, not stickies, but it captures the same instinct. The interest is in system-level leverage, not cosmetic polish.

Bottom line

Stickies is a browser utility with a memory problem, and it solves it by treating anchors as identities that can be lost and recovered. That is a small idea with a big practical payoff: overlays that stay honest even when the DOM does not.