reactjsnext.jsreact-tabs

Sticky headers, with react-tabs


In a web app (NextJS/React) I am using react-tabs to handle tabs.

I wonder how to keep the tab headers sticky. That is preventing them from scrolling up and disapearing when I scroll up the contents of the page.

After searching the net, I tried to use react-sticky, but it does not seem to work.

I even get the impression that react-tabs and react-sticky are not supposed to work together. Tell me if I am wrong.

Here is the relevant current code:

import { Tabs,TabList,Tab,TabPanel } from 'react-tabs';
import 'react-tabs/style/react-tabs.css';
.....

return (
  <Tabs defaultIndex={tabInit()}>
    <TabList>
      <Tab>Title-One</Tab>
      <Tab>Title-Two</Tab>
      <Tab>Title-Three</Tab>
      <Tab>Title-Four</Tab>
      <Tab>Title-Five</Tab>
      <Tab>Title-Six</Tab>
    </TabList>
    <TabPanel><Contents-One/></TabPanel>
    <TabPanel><Contents-Two/></TabPanel>
    <TabPanel><Contents-Three/></TabPanel>
    <TabPanel><Contents-Four/></TabPanel>
    <TabPanel><Contents-Five/></TabPanel>
    <TabPanel><Contents-Six/></TabPanel>
  </Tabs>
)

How can I get the effect I need while using react-tabs ?


Solution

  • You can achieve this using plain CSS.

    1. Add a container around the <Tabs> component
    2. Give fixed height to the above container
    3. Add position: sticky; to the <TabList> component.

    Here is a sample code to try.

    File: App.css

    .tab-container {
      max-height: 400px; /* adding height to create scroll */
      overflow-y: auto;
      border: 1px solid #ccc;
      position: relative;
    }
    
    .tab-list {
      position: sticky;
      top: 0;
      background-color: white;
      z-index: 10;
      border-bottom: 1px solid #ccc;
      margin: 0;
    }
    

    Update the component as below to apply the CSS classes

    File: App.js

    import { Tab, Tabs, TabList, TabPanel } from "react-tabs";
    
    import "react-tabs/style/react-tabs.css";
    import "./App.css";
    
    function App() {
      return (
        <div className="tab-container">
          <Tabs>
            <TabList className="tab-list">
              <Tab>Title 1</Tab>
              <Tab>Title 2</Tab>
            </TabList>
    
            <TabPanel>
              <h2>Any content 1</h2>
              <p>
                This will cause scrolling if it's long enough.
                Add more text here to see the scrolling effect, if required.
              </p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
            </TabPanel>
            <TabPanel>
              <h2>Any content 2</h2>
              <p>
                This is another content section with small content.
              </p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
              <p>More content...</p>
            </TabPanel>
          </Tabs>
        </div>
      );
    }
    
    export default App;
    
    

    Here is the code in a playground: https://playcode.io/2216306

    Let me know if you can see the required effect after these changes or if you face any error.