’ve found that a horizontal timeline is one of the best ways to visualise progress.
Whether you are tracking a shipping route from New York to Los Angeles or displaying a company’s historical milestones, a horizontal layout saves vertical space.
In this tutorial, I will show you exactly how to build a responsive horizontal timeline using three different methods I’ve used in real-world production apps.
Method 1: Build a Custom Horizontal Timeline Using CSS Flexbox
I often prefer building a custom component when I need full control over the design without adding heavy dependencies to the project.
Using CSS Flexbox is the easiest way to align timeline events horizontally while ensuring they remain responsive.
For this example, let’s visualise the key stages of a typical US Real Estate closing process.
Below is the complete code for a custom horizontal timeline. I have used standard CSS-in-JS logic, but you can move the styles to a separate CSS file.
import React from 'react';
const HorizontalTimeline = () => {
const timelineData = [
{ status: 'Offer Accepted', date: 'Oct 01', location: 'Austin, TX' },
{ status: 'Home Inspection', date: 'Oct 05', location: 'Austin, TX' },
{ status: 'Appraisal', date: 'Oct 12', location: 'Austin, TX' },
{ status: 'Financing Approved', date: 'Oct 20', location: 'Dallas, TX' },
{ status: 'Closing Day', date: 'Oct 30', location: 'Dallas, TX' },
];
const containerStyle = {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
padding: '50px',
fontFamily: 'Arial, sans-serif',
};
const timelineWrapper = {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
width: '100%',
maxWidth: '1000px',
position: 'relative',
margin: '40px 0',
};
const lineStyle = {
position: 'absolute',
top: '50%',
left: '0',
right: '0',
height: '4px',
backgroundColor: '#0078d4',
zIndex: '1',
};
const stepStyle = {
zIndex: '2',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
backgroundColor: '#fff',
};
const circleStyle = {
width: '20px',
height: '20px',
borderRadius: '50%',
backgroundColor: '#0078d4',
border: '4px solid #fff',
boxShadow: '0 0 5px rgba(0,0,0,0.2)',
};
const labelStyle = {
marginTop: '10px',
fontSize: '14px',
fontWeight: 'bold',
textAlign: 'center',
};
const dateStyle = {
fontSize: '12px',
color: '#666',
};
return (
<div style={containerStyle}>
<h2>Property Closing Roadmap</h2>
<div style={timelineWrapper}>
<div style={lineStyle}></div>
{timelineData.map((item, index) => (
<div key={index} style={stepStyle}>
<div style={circleStyle}></div>
<div style={labelStyle}>{item.status}</div>
<div style={dateStyle}>{item.date}</div>
<div style={dateStyle}>{item.location}</div>
</div>
))}
</div>
</div>
);
};
export default HorizontalTimeline;You can refer to the screenshot below to see the output.

In this approach, I used a relative-positioned wrapper with an absolute-positioned line to create the “track.”
Each milestone is a flex item that sits on top of that line, creating a clean, professional look common in fintech apps.
Method 2: Use the React-Chrono Library
If you are working on a project with a tight deadline, I highly recommend using react-chrono.
It is a powerful, flexible library that handles many edge cases, such as keyboard navigation and auto-scrolling, out of the box.
I’ve used this specifically for “History” pages where the client wants to showcase decades of growth for a US tech corporation.
First, you need to install the package:
npm install react-chronoHere is how you implement a horizontal timeline using react-chrono. We will use a “Road Trip Across the USA” theme for the data.
import React from 'react';
import { Chrono } from 'react-chrono';
const ChronoTimeline = () => {
const items = [
{
title: "May 2024",
cardTitle: "Starting Point: New York City",
cardSubtitle: "The Big Apple",
cardDetailedText: "Beginning the cross-country journey from Times Square, heading West towards the Great Lakes.",
},
{
title: "June 2024",
cardTitle: "Chicago Stopover",
cardSubtitle: "The Windy City",
cardDetailedText: "Enjoying deep-dish pizza and exploring the architecture of downtown Chicago.",
},
{
title: "July 2024",
cardTitle: "Mount Rushmore",
cardSubtitle: "South Dakota Landmarks",
cardDetailedText: "A historic visit to the Black Hills to see the iconic presidential carvings.",
},
{
title: "August 2024",
cardTitle: "Arrival: San Francisco",
cardSubtitle: "The Golden Gate",
cardDetailedText: "Ending the trip with a sunset view of the Golden Gate Bridge after 3,000 miles.",
}
];
return (
<div style={{ width: "100%", height: "500px" }}>
<h2 style={{ textAlign: 'center' }}>US Cross-Country Travelogue</h2>
<Chrono
items={items}
mode="HORIZONTAL"
itemWidth={250}
showSecondaryCursor
theme={{
primary: "#1d4ed8",
secondary: "#fbbf24",
cardBgColor: "#f3f4f6",
titleColor: "#1e3a8a",
}}
/>
</div>
);
};
export default ChronoTimeline;You can refer to the screenshot below to see the output.

What I like about this library is the mode=”HORIZONTAL” prop, which does all the heavy lifting for CSS.
It also includes a “card” layout that allows you to add detailed descriptions, which is perfect for storytelling or project portfolios.
Method 3: Implement with Material UI (MUI) Lab
Many enterprise-level applications in the US use Material UI as their primary design system. While MUI has a vertical timeline component in their Lab package, you can easily style it to be horizontal.
I’ve found this method works best when your application already uses MUI because it maintains consistent spacing and typography.
npm install @mui/material @emotion/react @emotion/styled @mui/labIn this example, let’s track the “Product Launch Cycle” for a Silicon Valley startup.
import React from 'react';
import Timeline from '@mui/lab/Timeline';
import TimelineItem from '@mui/lab/TimelineItem';
import TimelineSeparator from '@mui/lab/TimelineSeparator';
import TimelineConnector from '@mui/lab/TimelineConnector';
import TimelineContent from '@mui/lab/TimelineContent';
import TimelineDot from '@mui/lab/TimelineDot';
import Typography from '@mui/material/Typography';
import Box from '@mui/material/Box';
const MuiHorizontalTimeline = () => {
const steps = [
{ label: 'Research', date: 'Q1 2024', color: 'primary' },
{ label: 'Design', date: 'Q2 2024', color: 'secondary' },
{ label: 'Beta Test', date: 'Q3 2024', color: 'success' },
{ label: 'Launch', date: 'Q4 2024', color: 'error' },
];
return (
<Box sx={{ width: '100%', padding: 4 }}>
<Typography variant="h4" align="center" gutterBottom>
Startup Product Roadmap
</Typography>
<Timeline position="alternate" sx={{ flexDirection: 'row', padding: 0 }}>
{steps.map((step, index) => (
<TimelineItem key={index} sx={{ '&:before': { display: 'none' } }}>
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center', minWidth: '150px' }}>
<TimelineContent sx={{ py: '12px', px: 2 }}>
<Typography variant="h6" component="span">
{step.label}
</Typography>
<Typography color="textSecondary">{step.date}</Typography>
</TimelineContent>
<TimelineSeparator sx={{ flexDirection: 'row', alignItems: 'center' }}>
<TimelineDot color={step.color} />
{index !== steps.length - 1 && (
<TimelineConnector sx={{ width: '100px', height: '2px' }} />
)}
</TimelineSeparator>
</Box>
</TimelineItem>
))}
</Timeline>
</Box>
);
};
export default MuiHorizontalTimeline;The trick here is applying flexDirection: ‘row’ to the Timeline component.
By default, MUI timelines are vertical, but with a few SX prop overrides, you can make them look great horizontally.
Choose the Right Method
In my experience, picking the right method depends on your project’s scale.
If you only have 3-4 steps and want zero extra bundle size, use Method 1 (CSS). It’s lightweight and fast.
For content-heavy timelines where users need to scroll through many dates, Method 2 (React-Chrono) is the winner.
If you are already in the Material UI ecosystem and want to maintain the “Google-style” look, Method 3 (MUI) is the way to go.
Important Design Considerations
When building horizontal timelines, keep mobile users in mind.
Horizontal layouts can break on small screens (like iPhones) if they aren’t scrollable.
I always recommend adding overflow-x: auto to your container to ensure the timeline can be swiped on mobile devices.
Also, try to limit the amount of text in the “labels” so the circles don’t get pushed too far apart.
I hope you found this tutorial helpful! Using a horizontal timeline can significantly improve the UX of your dashboard or landing page.
You may also like to read:
- How to Convert React Component to TypeScript
- React Pass Function to Child Component
- React Controlled Component
- How to Use Angular Components in React

I am Bijay Kumar, a Microsoft MVP in SharePoint. Apart from SharePoint, I started working on Python, Machine learning, and artificial intelligence for the last 5 years. During this time I got expertise in various Python libraries also like Tkinter, Pandas, NumPy, Turtle, Django, Matplotlib, Tensorflow, Scipy, Scikit-Learn, etc… for various clients in the United States, Canada, the United Kingdom, Australia, New Zealand, etc. Check out my profile.