Styling hooks
CSS variables, data attributes, shadow parts and the default styles.
vidscroll ships no stylesheet to import. It adds a few default rules, all
wrapped in :where() so they have zero specificity: any rule you write wins,
without !important.
CSS variables
| Variable | Set on | Value |
|---|---|---|
–video-progress | The ScrollVideo or ScrollFrames block, the <vid-scroll> element, the core container | Smoothed progress through the whole video, 0 to 1, four decimals. Set once the video starts. |
–progress | Each section | Progress through the section’s range: 0 before, 1 after. |
–loader-progress | The <vid-scroll> element | Loading progress, 0 to 1, while loading. Removed when done. |
All three are inherited by everything inside.
Data attributes
| Selector | Element |
|---|---|
[data-vidscroll] | The outer block. Its height is length plus one screen. |
[data-vidscroll-stage] | The pinned, screen-sized stage |
[data-vidscroll-overlay] | The layer over the video that holds your content |
[data-vidscroll-media] | The video, or the canvas in ScrollFrames. [data-fit] holds cover or contain. |
[data-vidscroll-preview] | The first-frame video shown while loading |
[data-vidscroll-next] | The optimized copy while it’s being swapped in, behind the current video |
[data-vidscroll-section=“id”] | A section; [data-active] while active |
[data-vidscroll-loader] | The loading overlay; [data-phase] holds the phase, [data-background] marks the corner badge |
In <vid-scroll>, the stage, media and loader are inside the element’s shadow
root, so style them with the parts below instead. The element itself carries
data-phase and data-background while loading.
Shadow parts
For <vid-scroll> only:
| Selector | Element |
|---|---|
vid-scroll::part(stage) | The pinned stage |
vid-scroll::part(video) | The video |
vid-scroll::part(overlay) | The layer holding your content |
vid-scroll::part(loader) | The loading overlay and corner badge |
Default styles
These are the rules vidscroll adds (the element applies the same ones inside its shadow root):
:where([data-vidscroll]) { position: relative; }
:where([data-vidscroll-stage]) { position: sticky; top: 0; height: 100vh; height: 100svh; overflow: hidden; background: #000; }
:where([data-vidscroll-media]) { display: block; width: 100%; height: 100%; object-fit: cover; }
:where([data-vidscroll-media][data-fit="contain"]) { object-fit: contain; }
:where([data-vidscroll-preview]) { position: absolute; inset: 0; }
:where([data-vidscroll-next]) { position: absolute; inset: 0; z-index: -1; }
:where([data-vidscroll-overlay]) { position: absolute; inset: 0; pointer-events: none; }
:where([data-vidscroll-section]) { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; opacity: 0; visibility: hidden; transition: opacity 0.4s ease, visibility 0s linear 0.4s; }
:where([data-vidscroll-section][data-active]) { opacity: 1; visibility: visible; transition: opacity 0.4s ease; }
:where([data-vidscroll-section][data-active] > *) { pointer-events: auto; }
:where([data-vidscroll-loader]) { position: absolute; inset: 0; z-index: 1; display: grid; place-items: center; background: rgb(0 0 0 / 0.55); color: #fff; font-family: system-ui, sans-serif; }
:where([data-vidscroll-loader][data-background]) { inset: auto 16px 16px auto; padding: 8px 14px; border-radius: 999px; pointer-events: none; }React renders them in a <style> element next to each component. The core
and the element add them to the page’s <head> once, as
<style data-vidscroll-styles>, and they’re exported as the styles string
from vidscroll/core.
Related
- Scroll-driven CSS: effects from the variables.
- Custom loaders: restyling the loading overlay.