Layout stable hover via inset shadow
Skill kjuhwa/skills-hub/skills/design/layout-stable-hover-via-inset-shadow
Replace transform-based hover effects (translate, scale) with inset box-shadow to avoid layout shifts and horizontal-scrollbar flickerFrom its SKILL.md
npx -y skills add kjuhwa/skills-hub --skill layout-stable-hover-via-inset-shadowAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
2.9 KB, 620 tokens by cl100k_base, as published. Nobody here has run it
Layout-Stable Hover via Inset Shadow
Transform-based hover effects like transform: translateX(2px) look tasteful on a single button but break lists inside scrollable containers. Each item's hover overflows its parent horizontally, the browser flashes a horizontal scrollbar, which shifts the vertical scrollbar, which moves the hovered item out from under the cursor — flicker loop.
The anti-pattern
.list-item {
transition: all .2s;
}
.list-item:hover {
transform: translateX(2px); /* ← overflows parent */
box-shadow: 0 0 0 1px var(--accent);
}
Inside a container with bounded width, every hover triggers:
- Item moves 2px right
- Right edge overflows parent
- Browser adds horizontal scrollbar
- Vertical scrollbar narrows/moves
- Item under cursor is no longer hovered
- Scrollbar disappears
- Repeat — visible flicker
The fix
Use an effect that doesn't change layout:
.list-item {
min-width: 0; /* allow text ellipsis */
transition: background .2s, box-shadow .2s; /* explicit, not 'all' */
}
.list-item:hover {
background: var(--hover-bg);
box-shadow: inset 2px 0 0 var(--accent); /* painted inside, no overflow */
}
.list-item-name {
min-width: 0;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.list-container {
overflow-x: hidden; /* defense in depth */
}
Key changes:
box-shadow: insetpaints inside the element's box, so it doesn't add to scroll width.- Explicit transition properties (
background, box-shadow) instead ofall— prevents re-triggering on any unrelated property. overflow-x: hiddenon container — defense in depth against future hover changes that forget this rule.min-width: 0on flex children — required to lettext-overflow: ellipsisactually truncate inside a flex layout.
When transforms are still fine
Transform-based hovers are fine when:
- The item has room to grow (e.g. padding or margin buffers on all sides ≥ transform distance)
- The container has
overflow: visibleand doesn't scroll - The transform is a
scale()at origin center (no edge overflow)
They're only bad inside tight scrollable containers.
Related pitfalls
transition: allre-fires on any computed property change — scope transitions explicitly.:activeusingtransform: scale(.98)is usually fine because it's brief and mouse is already held.- Animated
margin-left/rightalso causes reflow; stick to inset shadows or absolutely-positioned overlays for decoration.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.