css - How to make Header and Sidebars sticky in a layout while scrolling text appears below them? - Stack Overflow

admin2025-05-02  0

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:

  • I used position: sticky with top: 0 for the Header.
  • For the LeftSidebar and RightSidebar, I used a combination of position: sticky and z-index with specified offsets.
  • As shown in the screenshot. As shown in the screenshot, the issue is that the text is appearing above the header
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.

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:

  • I used position: sticky with top: 0 for the Header.
  • For the LeftSidebar and RightSidebar, I used a combination of position: sticky and z-index with specified offsets.
  • As shown in the screenshot. As shown in the screenshot, the issue is that the text is appearing above the header
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.

Share Improve this question edited Jan 2 at 16:35 testing asked Jan 2 at 14:08 testingtesting 35 bronze badges 2
  • 1 You can mark the component you want to be scrollable via the overflow-y property and by specifying a height for that component. – Sarkis Commented Jan 2 at 14:24
  • The goal is to ensure that when scrolling, the text does not overlap or appear above the header, without relying on z-index. The layout is already scrollable, and I am looking for alternative solutions to achieve this behavior. – testing Commented Jan 2 at 14:59
Add a comment  | 

1 Answer 1

Reset to default 0

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.

转载请注明原文地址:http://anycun.com/QandA/1746115842a91888.html