Sticky allows an element to become fixed in its parent container when it reaches a top, left, bottom, or right threshold.
<div className="bg-muted-100 h-48 w-96 overflow-auto rounded-lg p-4"> <section> <Sticky className="top-0"> <h2 className="bg-muted-100 float-right -mt-4 p-4">A</h2> </Sticky> <ul> <li>Aaron Cooper</li> <li>Abigail Evans</li> <li>Adam Smith</li> <li>Alice Johnson</li> <li>Amelia Thomas</li> </ul> </section> <section> <Sticky className="top-0"> <h2 className="bg-muted-100 float-right -mt-4 p-4">B</h2> </Sticky> <ul> <li>Bella Morgan</li> <li>Benjamin Lee</li> <li>Benjamin Nguyen</li> <li>Brandon Carter</li> </ul> </section> <section> <Sticky className="top-0"> <h2 className="bg-muted-100 float-right -mt-4 p-4">C</h2> </Sticky> <ul> <li>Cameron Reed</li> <li>Charlotte Evans</li> <li>Chloe Brown</li> <li>Chloe Martinez</li> </ul> </section> <section> <Sticky className="top-0"> <h2 className="bg-muted-100 float-right -mt-4 p-4">D</h2> </Sticky> <ul> <li>Daniel Brown</li> <li>Daniel Jackson</li> <li>David Martinez</li> <li>Dylan Baker</li> </ul> </section> <section> <Sticky className="top-0"> <h2 className="bg-muted-100 float-right -mt-4 p-4">E</h2> </Sticky> <ul> <li>Elena Torres</li> <li>Emily Garcia</li> <li>Emily White</li> <li>Emma Nguyen</li> </ul> </section> <section> <Sticky className="top-0"> <h2 className="bg-muted-100 float-right -mt-4 p-4">F</h2> </Sticky> <ul> <li>Finn Walker</li> <li>Finnegan Patel</li> <li>Fiona Patel</li> <li>Frank Thompson</li> </ul> </section> <section> <Sticky className="top-0"> <h2 className="bg-muted-100 float-right -mt-4 p-4">G</h2> </Sticky> <ul> <li>Gabriella Diaz</li> <li>Gavin Ross</li> <li>Grace Garcia</li> <li>Grace Lewis</li> </ul> </section> <section> <Sticky className="top-0"> <h2 className="bg-muted-100 float-right -mt-4 p-4">H</h2> </Sticky> <ul> <li>Hannah Ramirez</li> <li>Hayden Foster</li> <li>Henry Foster</li> <li>Henry Martinez</li> </ul> </section> <section> <Sticky className="top-0"> <h2 className="bg-muted-100 float-right -mt-4 p-4">I</h2> </Sticky> <ul> <li>Ian Parker</li> <li>Isabel Clark</li> <li>Isabella Wright</li> <li>Isabelle Moore</li> </ul> </section> <section> <Sticky className="top-0"> <h2 className="bg-muted-100 float-right -mt-4 p-4">J</h2> </Sticky> <ul> <li>Jack Robinson</li> <li>Jacob Turner</li> <li>Jake Mitchell</li> <li>Jasmine Kim</li> </ul> </section> <section> <Sticky className="top-0"> <h2 className="bg-muted-100 float-right -mt-4 p-4">K</h2> </Sticky> <ul> <li>Kaitlyn Hall</li> <li>Katherine Adams</li> <li>Katherine Baker</li> <li>Kyle Lewis</li> </ul> </section> <section> <Sticky className="top-0"> <h2 className="bg-muted-100 float-right -mt-4 p-4">L</h2> </Sticky> <ul> <li>Liam Harris</li> <li>Liam Wright</li> <li>Lily Sullivan</li> <li>Lucas Gray</li> </ul> </section> <section> <Sticky className="top-0"> <h2 className="bg-muted-100 float-right -mt-4 p-4">M</h2> </Sticky> <ul> <li>Mackenzie Young</li> <li>Madison Harris</li> <li>Madison Perez</li> <li>Michael Russell</li> </ul> </section> <section> <Sticky className="top-0"> <h2 className="bg-muted-100 float-right -mt-4 p-4">N</h2> </Sticky> <ul> <li>Natalie Hill</li> <li>Nathan Stewart</li> <li>Nathan Turner</li> <li>Nora Murphy</li> </ul> </section> <section> <Sticky className="top-0"> <h2 className="bg-muted-100 float-right -mt-4 p-4">O</h2> </Sticky> <ul> <li>Oliver Phillips</li> <li>Olivia Lopez</li> <li>Olivia Young</li> <li>Owen Nelson</li> </ul> </section> <section> <Sticky className="top-0"> <h2 className="bg-muted-100 float-right -mt-4 p-4">P</h2> </Sticky> <ul> <li>Paige Adams</li> <li>Patrick Campbell</li> <li>Penelope Reed</li> <li>Peter Scott</li> </ul> </section> <section> <Sticky className="top-0"> <h2 className="bg-muted-100 float-right -mt-4 p-4">Q</h2> </Sticky> <ul> <li>Quentin Parker</li> <li>Quinn Taylor</li> <li>Quinn Wright</li> </ul> </section> <section> <Sticky className="top-0"> <h2 className="bg-muted-100 float-right -mt-4 p-4">R</h2> </Sticky> <ul> <li>Rachel Green</li> <li>Rachel Smith</li> <li>Ruby Patel</li> <li>Ryan Thompson</li> </ul> </section> <section> <Sticky className="top-0"> <h2 className="bg-muted-100 float-right -mt-4 p-4">S</h2> </Sticky> <ul> <li>Samuel Hall</li> <li>Samuel Lee</li> <li>Sophia Clark</li> <li>Steven Sanchez</li> </ul> </section> <section> <Sticky className="top-0"> <h2 className="bg-muted-100 float-right -mt-4 p-4">T</h2> </Sticky> <ul> <li>Taylor Carter</li> <li>Taylor Ross</li> <li>Thomas Baker</li> <li>Tiffany Martinez</li> </ul> </section> <section> <Sticky className="top-0"> <h2 className="bg-muted-100 float-right -mt-4 p-4">U</h2> </Sticky> <ul> <li>Ulysses Quinn</li> <li>Uma Wilson</li> </ul> </section> <section> <Sticky className="top-0"> <h2 className="bg-muted-100 float-right -mt-4 p-4">V</h2> </Sticky> <ul> <li>Vanessa Campbell</li> <li>Victor Johnson</li> <li>Victoria King</li> <li>Violet Cooper</li> </ul> </section> <section> <Sticky className="top-0"> <h2 className="bg-muted-100 float-right -mt-4 p-4">W</h2> </Sticky> <ul> <li>William Moore</li> <li>Willow Carter</li> <li>Wyatt Davis</li> <li>Wyatt Hayes</li> </ul> </section> <section> <Sticky className="top-0"> <h2 className="bg-muted-100 float-right -mt-4 p-4">X</h2> </Sticky> <ul> <li>Xander Roberts</li> <li>Xavier Thompson</li> <li>Ximena Rivera</li> </ul> </section> <section> <Sticky className="top-0"> <h2 className="bg-muted-100 float-right -mt-4 p-4">Y</h2> </Sticky> <ul> <li>Yara Ortiz</li> <li>Yasmine Allen</li> <li>Yasmine Johnson</li> </ul> </section> <section> <Sticky className="top-0"> <h2 className="bg-muted-100 float-right -mt-4 p-4">Z</h2> </Sticky> <ul> <li>Zachary Adams</li> <li>Zachary Edwards</li> <li>Zachary Turner</li> <li>Zoe Rodriguez</li> </ul> </section></div>
Here's the <Sticky />
component in action.
You are responsible for giving it a top-x
, left-x
, bottom-x
or right-x
position to stick to.
import { type HTMLAttributes, type PropsWithChildren, forwardRef } from 'react'import { cn } from '#app/utils/tailwind-merge.ts'
/** * Sticky component. * * @component * @example * ```jsx * <div className="mt-14 h-80 overflow-y-auto rounded-lg border"> * <div className="h-10" /> * <Sticky className="top-0 bg-green-500">This sticks</Sticky> * <div className="h-40" /> * <p>Some content</p> * <div className="h-40" /> * <Sticky className="top-0 bg-emerald-500">This also sticks</Sticky> * <div className="h-40" /> * <p>Some more content</p> * <div className="h-40" /> * </div> * ``` * * @param {string} [className] - Additional CSS class names. * @param {React.HTMLAttributes<HTMLDivElement>} [props] - Additional HTML attributes. * @returns {JSX.Element} The Sticky component. */const Sticky = forwardRef<HTMLDivElement, PropsWithChildren<HTMLAttributes<HTMLDivElement>>>(({ className, ...props }, ref) => { return <div ref={ref} className={cn('sticky', className)} {...props} />})Sticky.displayName = 'Sticky'
export { Sticky }