I am building a React application where I have multiple components like Header, LeftSidebar, RightSidebar, and Home. I am using a Layout component to wrap these components (e.g., LeftSidebar and RightSidebar).
I want to make the Header, LeftSidebar, and RightSidebar sticky so that when I scroll, the content (e.g., text from the Home component) scrolls under the Header and sidebars, rather than overlapping them.
To achieve this, I tried using z-index to fix the issue. While this works, I’m looking for a better or alternative approach to implement this behavior without using z-index.
Here’s what I’ve tried so far:
const Home = () => {
return (
<div
style={{
flex: 5,
overflowY: "scroll",
}}
>
{"Lorem ipsum dolor, sit amet consectetur adipisicing elit. Repudiandae".repeat(
100
)}
<div
style={{
position: "sticky",
top: "100px",
display: "flex",
alignSelf: "start",
}}
>
<h1>Fix this issue without using Z-index</h1>
</div>
{"Hello everyone, I’m looking for the best idea to resolve the problem related to the superposition of elements without using z-index.".repeat(
1000
)}
</div>
);
};
export default Home;
const Header = () => {
return (
<div
style={{
width: "100%",
height: " 60px",
backgroundColor: "rgb(12, 4, 244)",
color: "white",
display: "flex",
gap: "5px",
alignItems: "center",
position: "sticky",
top: "0px",
}}
>
<a href="#" style={{ color: "white" }}>
Home
</a>
<a href="#" style={{ color: "white" }}>
Contact
</a>
<a href="#" style={{ color: "white" }}>
Service
</a>
<a href="#" style={{ color: "white" }}>
Settings
</a>
<a href="#" style={{ color: "white" }}>
About
</a>
</div>
);
};
export default Header;
import { FC, PropsWithChildren } from "react";
import Header from "../header/header";
import LeftSidebar from "../left-sidebar/left-sidebar";
import RightSidebar from "../right-sidebar/right-sidebar";
const Layout: FC<PropsWithChildren> = ({ children }) => {
return (
<>
<Header />
<div
style={{
display: "flex",
minHeight: "calc(100vh - 60px)",
}}
>
<LeftSidebar />
{children}
<RightSidebar />
</div>
</>
);
};
export default Layout;
const LeftSidebar = () => {
return (
<div
style={{
flex: 1,
backgroundColor: "green",
position: "sticky",
top: "60px",
}}
>
LeftSidebar
</div>
);
};
export default LeftSidebar;
const RightSidebar = () => {
return (
<div
style={{
flex: 1,
backgroundColor: "yellow",
position: "sticky",
top: "60px",
}}
>
RightSidebar
</div>
);
};
export default RightSidebar;
However, I’m not sure if this is the best approach or if there’s a more efficient way to handle this layout without relying heavily on z-index.
Instead of playing with z-index and position sticky, you could make only the main content scrollable instead of the whole page. You can have an example on how this works in any AI chat nowadays. If you go to chatgpt and have a conversation long enough you can notice that it's not the page that's scrollable only the content.
It works by putting the whole page in a fixed height of 100vh and having overflow-y: auto;
on the content itself.