Styling
Class names, data attributes, and the edge fade.
Loopem ships structural CSS only: what it needs to work, and nothing that is a look. No colors, fonts, radii or sizes. Those are yours.
What it puts on the DOM
| Hook | Where | Meaning |
|---|---|---|
.loopem | your container | positioning context, clips the track |
.loopem-track | inside it | a zero-sized origin at the center |
.loopem-slot | one per visible item | absolutely positioned, transformed per frame |
.loopem-moving | on the container | present only while in motion |
.loopem-interactive | on the container | present only while it takes input |
data-loopem-key | on each slot | the virtual index |
data-loopem-centered | on one slot | the item at the center |
aria-selected | on each slot | the chosen one, when interactive |
Style your own element inside the slot, not the slot itself. The slot is the library’s; its transform is rewritten every frame.
.thumb {
width: 62px;
height: 82px;
border-radius: 12px;
}
.loopem-slot[data-loopem-centered] .thumb {
box-shadow: 0 0 0 2px #fff;
}
.loopem-slot[aria-selected="true"] .thumb {
box-shadow: 0 0 0 3px var(--accent);
}Positioning the container
The library’s own position: relative and overflow: hidden are written at
zero specificity, so any plain class of yours wins:
.rail {
position: absolute;
inset: 0 auto 0 0;
width: 200px;
}Fading the edges
Two things dissolve a track, and mixing them up is the usual reason an edge still looks cut.
minOpacity and falloff ramp each item by its distance from the center,
so an item fades out whole and is gone before it reaches the container. This is
what makes a track look like it dissolves.
fade masks the container’s edges. It cannot stop overflow: hidden
cutting through an item that reaches the boundary, only make that slice fainter.
Use the ramp for the look, and a small fade for whatever still touches the
edge:
createPicker(el, {
items,
renderItem,
minOpacity: 0,
falloff: 5,
fade: 90,
})fade is a mask rather than an overlay, so it works over any background, and it
runs along the axis: top and bottom on a vertical track. It shows only where the
track actually reaches the container, so a container much wider than the track
fades empty background and appears to do nothing.
Overriding a slot’s opacity
The layout writes its own falloff to --loopem-fade, and the structural CSS
reads opacity: var(--loopem-opacity, var(--loopem-fade, 1)). Set the first one
to hold a slot out of the fade:
.loopem-slot[aria-selected="true"] {
--loopem-opacity: 1;
}Two names rather than one, because inline custom properties beat stylesheet
rules. If the library wrote --loopem-opacity inline, your override would need
!important.
While it is moving
.loopem-moving is on the container only during motion, which is also when
will-change: transform is set and then cleared. Use it for anything that
should switch off while the track moves.
.loopem-moving .thumb {
pointer-events: none;
}