DEV Community

Cover image for Create a vertical timeline
Phuoc Nguyen
Phuoc Nguyen

Posted on • Originally published at phuoc.ng

Create a vertical timeline

Here's what we'll cover:

  • Discover how to position an item precisely using the grid-column property.
  • Learn how to define the gap between columns with the grid-column-gap property.
  • Learn how to use the grid-auto-flow property.

A timeline is a visual representation of events that took place over time. It's a powerful tool for displaying information chronologically, making it easier for viewers to understand the sequence of events. Timelines are versatile and can be used in fields such as history, science, project management, and personal development.

In history, timelines are frequently used to show the progression of significant events or periods. They can also showcase important figures and their contributions during specific time periods.

In science, timelines can illustrate the evolution of species or the development of scientific theories.

In project management, timelines are essential tools for planning and tracking progress. They help teams visualize tasks and deadlines, ensuring that everyone is on the same page.

For personal development, timelines can track progress towards goals or milestones. They provide a clear picture of what has been accomplished and what still needs to be done.

In this post, we'll go through the steps to create a vertical timeline using CSS grid.

Creating the HTML structure for the timeline

To build a timeline, we first need to structure the content of the timeline using HTML. In our example, we'll start by creating a div element with a class of timeline. This div will serve as the container for all our timeline items.

<div class="timeline">
    <!-- An item -->
    <div class="timeline__date">...</div>
    <div class="timeline__separator"></div>
    <div class="timeline__content">
        <div class="timeline__title">...</div>
        <div class="timeline__description">...</div>
    </div>

    <!-- Repeat other items ... -->
</div>
Enter fullscreen mode Exit fullscreen mode

Each item will be structured using three additional div elements: one for the date or time of the event, one as a separator, and one for the content related to that event. The content div has two child divs for the title and description. You can customize this structure as per your requirements.

With this structure, we can easily style each item using CSS grid properties, which we'll cover in detail in the next section.

Styling the timeline with CSS grid

To make our timeline look great, we'll use CSS grid properties. First, we set the container to display: grid, which turns it into a CSS grid container. Then, we define the gap between columns with the grid-column-gap property and set it to 1rem. This creates a nice one-rem gap between each column.

Next, we define the columns using the grid-template-columns property. In our example, we have three columns. The first column is for the date or time of the event and is set to a fixed width of 5rem. The second column is used as a separator between items and has a width of only 0.125rem. The third column takes up the remaining space and is used for the content related to that event.

.timeline {
    display: grid;
    grid-column-gap: 1rem;
    grid-template-columns: 5rem 0.125rem 1fr;
}
Enter fullscreen mode Exit fullscreen mode

To create a vertical separator, all we need to do is set the background property to the color of our choice. In our example, we've gone with a light shade of gray (rgb(203 213 225)) to create a visible separation between each item on the timeline. If you'd like, you can play around with different colors and shades to match your design preferences.

.timeline__separator {
    background: rgb(203 213 225);
}
Enter fullscreen mode Exit fullscreen mode

To connect the date of each item with its corresponding content, we can use a dot as a visual aid. First, we set the position of the separator element to relative. Then, we add a ::before pseudo-element to create the dot connector. We set the content property to an empty string to create a content-less element that only serves as a visual aid.

Next, we set its position to absolute, which takes it out of the normal flow of elements and allows us to position it with respect to its closest positioned ancestor (in this case, the separator element). We then position the dot connector by setting its top value to 0.25rem, which is half of our desired distance from the top edge of the separator element.

Finally, we center it horizontally by setting its left value to 50% and translating it back by half its own width using the transform: translateX(-50%) property-value pair.

.timeline__separator {
    position: relative;
}
.timeline__separator::before {
    content: '';
    position: absolute;
    top: 0.25rem;
    left: 50%;
    transform: translateX(-50%);
}
Enter fullscreen mode Exit fullscreen mode

To create a circle shape for the dot connector, we just need to add some additional CSS properties to the ::before pseudo-element. First, we set the border-radius property to 50%, which makes it a perfect circle. Then we set the height and width properties to the same value, like 1rem, to create a uniform circular shape. This simple tweak transforms our dot connector into a visually appealing and informative element that effectively connects each date or time with its corresponding content.

.timeline__separator::before {
    background: inherit;
    border-radius: 50%;
    height: 1rem;
    width: 1rem;
}
Enter fullscreen mode Exit fullscreen mode

Here's what the timeline looks like:

The content featured in the timeline is from The History of the Web

Reversing date and content in alternate rows

Let's mix things up a bit and create a new version of our timeline where the date and content are swapped in every other row. The date and content will have the same width, and we'll place a separator in the middle.

To achieve this new layout, we'll make some changes to the .timeline class. We'll still use display: grid to create a CSS grid container, but this time we'll adjust the grid-template-columns property to have two equal columns of 1fr. This will give us an even amount of space on either side of our separator element.

.timeline {
    grid-template-columns: 1fr 0.125rem 1fr;
}
Enter fullscreen mode Exit fullscreen mode

Next, let's get into positioning the elements of each item explicitly. Since the separators are always placed in the middle, we can use the grid-column property to make it happen. This property specifies where an item should start and end within a grid row. In our case, we set the separator element to span across one column by using grid-column: 2;. This ensures that it is always positioned in the middle column of our three-column grid, effectively separating each date and content div.

.timeline__separator {
    grid-column: 2;
}
Enter fullscreen mode Exit fullscreen mode

We're going to use the same approach to position the date on our timeline. By default, it shows up in the first column. But we want to switch things up and move it to the third column in every other row.

To make this happen, we use the nth-child(6n+4) selector in the .timeline__date class. This selector targets every 6th item starting from the 4th item, which are the date divs we want to swap with their corresponding content divs. By setting the grid-column property of these selected date divs to 3, we position them on the right side of the timeline, swapping their position with their corresponding content divs.

.timeline__date {
    grid-column: 1;
}
.timeline__date:nth-child(6n+4) {
    grid-column: 3;
}
Enter fullscreen mode Exit fullscreen mode

Similarly, to make the content span across the third column of our three-column grid, we use grid-column: 3. However, in alternate rows where we swap the position of the date and content divs, we set it to span across the first column by using grid-column: 1.

We can achieve this effect by using the nth-child(6n) selector in the .timeline__content class. This selector targets every sixth item, starting from the first item, and sets its grid-column property to 1. This ensures that in alternating rows, where the content div is positioned on the left side of the separator element, it spans across only one column instead of three.

.timeline__content {
    grid-column: 3;
}
.timeline__content:nth-child(6n) {
    grid-column: 1;
}
Enter fullscreen mode Exit fullscreen mode

We can easily customize the position of timeline items according to our design preferences by using the nth-child selector along with other CSS properties.

Here's how the timeline layout looks now:

Although we've properly positioned the items in our grid container, the layout still seems to be broken. Specifically, in alternate rows, the separators don't take up the full height of the corresponding item. However, we can fix this issue by using the grid-auto-flow property.

The grid-auto-flow property controls how items are placed in a grid container when there isn't enough space to fit them all. By default, it's set to row, which places items in rows from left to right and top to bottom.

But we can change this behavior by setting grid-auto-flow to column. This will cause items to flow into columns from top to bottom and left to right, instead of rows. This is great for creating a vertical timeline with multiple columns of events.

Another value we can use for the grid-auto-flow property is dense. When set to dense, the grid algorithm will attempt to fill in gaps that are created when items have different heights or widths. It does this by placing smaller items in available spaces between larger ones, instead of leaving those spaces empty. This can result in a more compact and efficient use of space in our grid layout.

.timeline {
    grid-auto-flow: dense;
}
Enter fullscreen mode Exit fullscreen mode

Check out the modified timeline below:

Conclusion

To sum up, we've just covered how to create a vertical timeline using CSS grid properties. By defining columns and gaps, we can style our timeline to our liking and add visual elements like dot connectors and background colors.

But that's not all. We also explored an alternate layout where the date and content divs are swapped in alternating rows. To make this work, we used the grid-column property to position each item correctly and the grid-auto-flow property to fill in gaps.

CSS grid is a powerful tool for creating complex layouts with ease. Armed with these techniques, you can now craft stunning and informative timelines that are visually appealing.


If you found this series helpful, please consider giving the repository a star on GitHub or sharing the post on your favorite social networks 😍. Your support would mean a lot to me!

If you want more helpful content like this, feel free to follow me:

Top comments (0)