Curriculum Timeline – Stylus (CSS) Tutorial
Tags: tutorial, css, beginners, webdev
Published: 2020-05-10 17:17:19

---
title: Curriculum Timeline – Stylus (CSS) Tutorial
published: true
description: How to make a responsive timeline of art exhibitions
tags: #tutorial, #css, #beginners, #webdev
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/ng0zu0hcl4l19jaetlfy.jpg
---

Recently, I came across a need to display a list of artist's exhibitions in a sidebar on a webpage.  I wasn't quite satisfied with the styling of the presentation I had at hand at the time. That lead me to write a snippet of code you'll find in this tutorial. I wrote it in Stylus and HTML. Click on the _View Compiled_ button to see the compiled CSS.

## The Curriculum Timeline – grab the code

For those of you, who just wanna see it in action or just get the final code, here it is…

{% codepen https://codepen.io/crs1138/pen/MWaGEdP default-tab=css,result %}

## Default settings and variables

```sass
$bgColor   ?= #ffffff
$txtColor  ?= #444444
$linkColor ?= #ec008c
```

## The basic structure

AS you can see, in the code above, the actual timeline HTML is made of the following parts:
```html
<!-- The actual timeline HTML starts here -->
<div class="timeline tm">
  <!-- listing of the individual years -->
  <div class="tm__year"> … </div>
  <div class="tm__year"> … </div>
  <div class="tm__year"> … </div>
  <div class="tm__year"> … </div>
  <!-- the actual vertical line representing the timeline -->
  <div class="tm__line"></div>
</div>
```

This is pretty straight forward. The idea is an encapsulating block `.tm` that has its property `position: relative` to provide a point of reference for the vertical line `.tm__line` which is positioned absolutely. The `.tm` block also displays all the `.tm__year` elements. I shall mention these in more detail later.
```sass
.tm
  min-height: 100vh
  position: relative

  /* The vertical line symbolizing the timeline */
  &__line
    position: absolute
    /* defines the width of the vertical line */
    width: 2px
    top: 0
    bottom: 0
    left: 100%
    transform: translateX(-5rem)
    background-color: lighten($txtColor, 80%)
    z-index: -1
```

## The structure of the individual year elements and their labels

Each of the `.tm__year` elements is made of an unordered list of the exhibitions that the artist participated in that year and a label for the particular year.
```html
<div class="tm__year">
  <div class="tm__label">2018</div>
  <ul class="tm__events">
    <li class="tm__event"> … </li>
    <li class="tm__event"> … </li>
    <li class="tm__event"> … </li>
  </ul>
</div>
```
The formatting of the `.tm__year` makes each one of them `position: relative;` to set a reference point for the `.tm__label` element that is positioned absolutely. The label uses a set of `text-shadow` properties to create the illusion of the text outline.
```sass
  /* Definition of the year elements */
  &__year
    position: relative
    min-height: 10rem
    margin-top: 3rem
    &:first-child
      /* making sure the first year sticks to the top */
      margin-top: 0

  &__label
    color: rgba($txtColor, 0.3)
    color: $bgColor
    font-family: 'PT Serif', serif;
    font-weight: bold
    font-size: 4rem
    line-height: 1
    transform: rotate(-90deg)
    transform-origin: 100% 0
    position: absolute
    top: 0
    right: 4.75rem
    max-width: 16rem
    text-align: right
    text-shadow: -1px -1px 0 rgba($linkColor, 0.6),
                  1px -1px 0 rgba($linkColor, 0.6),
                 -1px  1px 0 rgba($linkColor, 0.6), 
                  1px  1px 0 rgba($linkColor, 0.6)
```

## The actual list of exhibitions

There is nothing really special about the unordered list of exhibitions for each year. Each exhibition element consists of its heading and description.
```html
<ul>
  <li class="tm__event">
    <h2 class="tm__event__heading">Ceramiq, Órgiva, Spain</h2>
    A cyanotype exhibition.
  </li>
  …
</ul>
```
The actual styling of the list, its items and their headings
```sass
  &__events
    /* Sets the right edge of the list in line with the vertical line */
    width: calc(100% - 5rem)
    /* Aligns the text of exhibitions to the right edge */
    text-align: right

  &__event
    padding: 1rem 0
    padding-right: 2rem
    /* set the reference point for the timeline bullet points */
    position: relative

    …

    &__heading
      font-size: 1.5rem
      line-height: 1.2
      margin-bottom: 0.5rem
      color: $linkColor
```

## The timeline bullet points

Each event on the timeline is highlighted by a bullet point. These are made by the CSS `::after` pseudo-element thus they don't require any additional HTML markup. As an icing on the cake, I've added a gentle micro-animation. I'm animating the bullet point's `box-shadow` property and offsetting the odd and even bullet points by half of the animation period, thus creating an alternating effect.
```sass
  &__event
    …

    &::after
      content: ''
      width: 1rem
      height: 1rem
      background-color: $linkColor
      position: absolute
      top: 1.5rem
      right: calc(-0.5rem - 1px)
      transform: rotate(45deg)
      animation-duration: 1.5s
      animation-name: microEvent
      animation-iteration-count: infinite
      animation-delay: 0

    &:nth-child(odd)
      &::after
        animation-delay: 0.75s

    @keyframes microEvent
      from
        box-shadow: 0 0 0 rgba($linkColor, 0.5)

      to
        box-shadow: 0 0 1rem 0.5rem rgba($linkColor, 0.1)
```

> _Special thanks go to my wife for letting me use some of her artist's CV records to make the example a bit more natural and for the cover image. Please, reward her goodwill, visit her website [Emma Plunkett Art](https://emmaplunkett.art) and perhaps even buy a piece of her artwork._