How to Create a Horizontal Timeline in React

’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.

Create Horizontal Timeline in React

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-chrono

Here 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.

Horizontal Timeline in React

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/lab

In 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:

51 Python Programs

51 PYTHON PROGRAMS PDF FREE

Download a FREE PDF (112 Pages) Containing 51 Useful Python Programs.

pyython developer roadmap

Aspiring to be a Python developer?

Download a FREE PDF on how to become a Python developer.

Let’s be friends

Be the first to know about sales and special discounts.