Track element within viewport
An example of tracking an element within the viewport using Motion for React's useScroll hook.
Source code
"use client"
import { motion, useScroll } from "motion/react"
import { useRef } from "react"
function Item() {
const ref = useRef(null)
const { scrollYProgress } = useScroll({
target: ref,
offset: ["end end", "start start"],
})
return (
<section style={itemContainer}>
<div ref={ref} style={item}>
<figure style={progressIconContainer}>
<svg
style={progressIcon}
width="75"
height="75"
viewBox="0 0 100 100"
>
<circle
style={progressIconBg}
cx="50"
cy="50"
r="30"
pathLength="1"
className="bg"
/>
<motion.circle
cx="50"
cy="50"
r="30"
pathLength="1"
style={{
...progressIconIndicator,
pathLength: scrollYProgress,
}}
/>
</svg>
</figure>
</div>
</section>
)
}
export default function TrackElementWithinViewport() {
return (
<>
<Item />
<Item />
<Item />
<Item />
<Item />
<Item />
<Item />
<Item />
<Item />
<Item />
<Item />
<Item />
</>
)
}
/**
* ============== Styles ================
*/
const itemContainer: React.CSSProperties = {
height: "100vh",
maxHeight: "400px",
display: "flex",
justifyContent: "center",
alignItems: "center",
}
const progressIconContainer: React.CSSProperties = {
position: "sticky",
top: 0,
width: 80,
height: 80,
margin: 0,
padding: 0,
}
const processCircle: React.CSSProperties = {
strokeDashoffset: 0,
strokeWidth: 5,
fill: "none",
}
const progressIcon: React.CSSProperties = {
...processCircle,
transform: "translateX(-100px) rotate(-90deg)",
stroke: "var(--hue-1)",
}
const progressIconIndicator: React.CSSProperties = {
...processCircle,
strokeDashoffset: 0,
strokeWidth: 5,
fill: "none",
}
const progressIconBg: React.CSSProperties = {
opacity: 0.2,
}
const item: React.CSSProperties = {
width: 200,
height: 250,
border: "2px dotted var(--hue-1)",
position: "relative",
}Related examples
Latest in React
Motion+
Unlock all 400+ examples
- Source code for every Plus example.
- Provide examples direct to your agent via Motion's MCP.
- Lifetime access to new examples and APIs.








