Creating a Responsive Sticky Header in React
In this tutorial, we will learn how to create a responsive sticky header in React. A sticky header is a navigation bar that remains fixed at the top of the page, even when the user scrolls down. This improves the user experience by providing easy access to important navigation links at all times.

Introduction
A sticky header is an essential component of a modern website. It helps users navigate through the website without having to scroll back to the top of the page. In addition, a responsive sticky header adjusts its layout and behavior based on the screen size and orientation, ensuring a consistent user experience across different devices.
To create a responsive sticky header in React, we will use the popular React library along with some additional dependencies. Let's get started by setting up our React project.
Setting up the React project
Before we start coding our sticky header, we need to create a new React project and install the necessary dependencies. Follow the steps below to set up the project:
-
Creating a new React project:
Open your terminal and navigate to the directory where you want to create your project. Run the following command to create a new React app:
npx create-react-app sticky-headerThis will create a new directory named
sticky-headerwith a basic React project structure. -
Installing necessary dependencies:
Next, navigate into the project directory by running
cd sticky-header. We will install two additional dependencies:react-router-domandstyled-components. Run the following command to install them:npm install react-router-dom styled-componentsThese dependencies are required for building a responsive sticky header with routing and styling capabilities.
Now that our project is set up, let's move on to creating the Header component.
Creating the Header component
The Header component will serve as our sticky header. It will contain the navigation links and adapt its layout and behavior based on the screen size.
-
Setting up the basic structure:
In the
srcdirectory, create a new file namedHeader.js. Open the file and add the following code:import React from 'react';
import { Link } from 'react-router-dom';
import styled from 'styled-components';
const HeaderContainer = styled.header`
position: sticky;
top: 0;
background-color: #ffffff;
padding: 10px;
z-index: 999;
`;
const Header = () => {
return (
<HeaderContainer>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/contact">Contact</Link>
</li>
</ul>
</nav>
</HeaderContainer>
);
};
export default Header;In this code, we import the necessary dependencies:
React,Linkfromreact-router-dom, andstyledfromstyled-components. We then define theHeaderContainerstyled component that will serve as the container for our sticky header. It has some basic styles like position, background color, padding, and z-index.Inside the
Headerfunctional component, we return the JSX code for our header. It consists of anavelement with an unordered list of navigation links wrapped inLinkcomponents fromreact-router-dom. -
Styling the header:
To style the navigation links, create a new file named
Header.styles.jsin the same directory. Add the following code:import styled from 'styled-components';
export const Nav = styled.nav`
ul {
display: flex;
list-style-type: none;
margin: 0;
padding: 0;
}
li {
margin-right: 10px;
}
a {
text-decoration: none;
color: #000000;
font-weight: bold;
}
`;In this code, we define the
Navstyled component to style the navigation links. We use flexbox to horizontally align the navigation links and add some margin and padding for spacing. Theatag inside theNavcomponent has styles for text decoration, color, and font weight. -
Implementing the sticky behavior:
To make our header sticky, go back to the
Header.jsfile and add the following code at the top of the file:import React, { useEffect, useRef } from 'react';
// ...
const Header = () => {
const headerRef = useRef(null);
useEffect(() => {
const handleScroll = () => {
const header = headerRef.current;
const sticky = header.offsetTop > 0;
if (sticky) {
header.classList.add('sticky');
} else {
header.classList.remove('sticky');
}
};
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, []);
// ...
};In this code, we import
useEffectanduseReffromreact. We create aheaderRefusing theuseRefhook to reference the header DOM element. Inside theuseEffecthook, we define ahandleScrollfunction that checks if the header is at the top of the page (offsetTop > 0). If it is, we add thestickyclass to the header element; otherwise, we remove thestickyclass. We add an event listener for thescrollevent and remove it when the component is unmounted.
Now that we have implemented the basic structure, styling, and sticky behavior of our header component, let's move on to handling responsiveness.
Handling responsiveness
To make our sticky header responsive, we will use media queries to adjust its layout and behavior for different screen sizes.
-
Using media queries:
In the
Header.styles.jsfile, add the following code below theNavstyled component:export const ResponsiveNav = styled(Nav)`
@media (max-width: 768px) {
ul {
flex-direction: column;
}
li {
margin-right: 0;
margin-bottom: 10px;
}
}
`;In this code, we define the
ResponsiveNavstyled component by extending theNavstyled component. Inside the media query, we change the flex direction tocolumnfor screen sizes up to768pxand remove the right margin for list items while adding bottom margin for spacing. -
Adjusting the header for different screen sizes:
Go back to the
Header.jsfile and update the JSX code as follows:// ...
const Header = () => {
// ...
const isMobile = window.innerWidth <= 768;
return (
<HeaderContainer ref={headerRef} className={isMobile ? 'mobile' : ''}>
<ResponsiveNav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/contact">Contact</Link>
</li>
</ul>
</ResponsiveNav>
</HeaderContainer>
);
};
// ...In this code, we use the
isMobilevariable to determine if the screen size is mobile (less than or equal to768px). We add themobileclass to the header container if it is. This allows us to apply different styles to the header for mobile screens.
With this implementation, our sticky header will adapt its layout and behavior based on different screen sizes. Now, let's move on to testing and debugging our header component.
Testing and debugging
To ensure that our header component works correctly and to debug any issues, we will test it and handle common problems that may arise.
-
Testing the header component:
In your project directory, open the
src/App.jsfile and replace its content with the following code:import React from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import Header from './Header';
const Home = () => <h1>Home</h1>;
const About = () => <h1>About</h1>;
const Contact = () => <h1>Contact</h1>;
const App = () => {
return (
<Router>
<Header />
<Switch>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/contact" component={Contact} />
</Switch>
</Router>
);
};
export default App;In this code, we import the
Headercomponent and define three functional components for the home, about, and contact pages. We wrap theHeadercomponent and theSwitchcomponent with theRoutercomponent fromreact-router-domto enable routing.Run your React app by running
npm startin your terminal. You should see the sticky header at the top of the page with the navigation links. Clicking on the links should navigate to the respective pages. -
Debugging common issues:
-
Issue: Sticky header not sticking to the top of the page. Solution: Ensure that the
positionof theHeaderContaineris set tostickyand thetopis0. -
Issue: Sticky header not changing its layout for mobile screens. Solution: Check if the
isMobilelogic is correctly implemented and themobileclass is applied to theHeaderContainerwhen needed. -
Issue: Sticky header not working after navigating to a different page. Solution: Make sure that the
handleScrollfunction is correctly implemented and the event listener for thescrollevent is added and removed as expected.
By testing and debugging our header component, we can address any issues and ensure that it functions as intended.
-
Optimizing performance
To optimize the performance of our sticky header, we can reduce unnecessary re-renders by implementing memoization.
-
Reducing unnecessary re-renders:
In the
Header.jsfile, update the import statement as follows:import React, { useEffect, useRef, memo } from 'react';Wrap the
Headerfunctional component with thememohigher-order component as follows:const Header = memo(() => {
// ...
});By wrapping our component with
memo, React will only re-render it if the props have changed. This can significantly improve performance, especially in larger applications. -
Implementing memoization:
To memoize the
handleScrollfunction, update theuseEffecthook as follows:useEffect(() => {
const handleScroll = () => {
const header = headerRef.current;
const sticky = header.offsetTop > 0;
if (sticky) {
header.classList.add('sticky');
} else {
header.classList.remove('sticky');
}
};
const memoizedHandleScroll = memoize(handleScroll);
window.addEventListener('scroll', memoizedHandleScroll);
return () => {
window.removeEventListener('scroll', memoizedHandleScroll);
};
}, []);In this code, we import the
memoizefunction from a memoization library (e.g.,lodashormemoize-one). We then usememoizeto create a memoized version of thehandleScrollfunction. This ensures that the function is only executed when the dependencies have changed and avoids unnecessary re-renders.
By implementing memoization, we can optimize the performance of our sticky header and reduce unnecessary re-renders.
Conclusion
In this tutorial, we learned how to create a responsive sticky header in React. We set up a new React project, created the Header component with the basic structure, styling, and sticky behavior. We also handled responsiveness using media queries and tested and debugged the component. Finally, we optimized the performance by reducing unnecessary re-renders through memoization.
By following this tutorial, you should now have a good understanding of how to create a responsive sticky header in React. You can further enhance the header by adding additional functionality and styling based on your project requirements.