DEV Community

Cover image for Curriculum Timeline – Stylus (CSS) Tutorial

Curriculum Timeline – Stylus (CSS) Tutorial

crs1138 profile image Honza ・3 min read

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…

Default settings and variables

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

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

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.

  min-height: 100vh
  position: relative

  /* The vertical line symbolizing the timeline */
    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.

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

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.

  /* Definition of the year elements */
    position: relative
    min-height: 10rem
    margin-top: 3rem
      /* making sure the first year sticks to the top */
      margin-top: 0

    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.

  <li class="tm__event">
    <h2 class="tm__event__heading">Ceramiq, Órgiva, Spain</h2>
    A cyanotype exhibition.

The actual styling of the list, its items and their headings

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

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


      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.


      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

        animation-delay: 0.75s

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

        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 and perhaps even buy a piece of her artwork.


Editor guide