/blog/

2024 0906 CSS Timeline

Inspired by Jonas Hietala, I experimented with building a timeline in HTML and CSS. I made something a bit simpler than his, so that it would be easier to type out by hand in a Markdown file.

Features:

  • It uses an <ol> with a mrl-timeline class, on the theory that an ordered list matches a timeline best.
  • It uses as few classes as possible and no divs, and scopes all CSS to ol.mrl-timeline.
  • It can indicate a “discontinuity”, or large jump in time, with an <hr> with the mrl-timeline-discontinuity class applied.
  • CSS naturally works well for customizations, like changing sizes or colors.

It looks like this:

  1. In the beginning the Universe was created.

    This had made many people very angry and has been widely regarded as a bad move


  2. Apollo 11 lands on the moon, marking the first time humans set foot on another celestial body.

  3. The Berlin Wall falls, symbolizing the end of the Cold War and the reunification of Germany.

    This was very good.

  4. The September 11 attacks occur in the United States, leading to significant global changes in security and international relations.

  5. The World Health Organization declares COVID-19 a global pandemic, affecting countries worldwide and leading to unprecedented global health measures.

Source code for timeline with default styles

HTML

<ol class="mrl-timeline">
  <li>
      <time>Year 0</time>
      <p>In the beginning the Universe was created.</p>
      <p>This had made many people very angry and has been widely regarded as a bad move</p>
  </li>
  <li><hr class="mrl-timeline-discontinuity" /></li>
  <li>
      <time datetime="1969-07-20">July 20, 1969</time>
      <p>Apollo 11 lands on the moon, marking the first time humans set foot on another celestial body.</p>
  </li>
  <li>
      <time datetime="1989-11-09">November 9, 1989</time>
      <p>The Berlin Wall falls, symbolizing the end of the Cold War and the reunification of Germany.</p>
      <p>This was very good.</p>
  </li>
  <li>
      <time datetime="2001-09-11">September 11, 2001</time>
      <p>The September 11 attacks occur in the United States, leading to significant global changes in security and international relations.</p>
  </li>
  <li>
      <time datetime="2020-03-11">March 11, 2020</time>
      <p>The World Health Organization declares COVID-19 a global pandemic, affecting countries worldwide and leading to unprecedented global health measures.</p>
  </li>
</ol>

/* -*- mode: html -*- */

CSS

This is the default styling applied to all timelines on the site (as of the time this post was published).

/* Timeline styling
 *
 * Use 1em as the unit and calculate all sizes based on that.
 * This allows the timeline to scale with the font size.
 */

 ol.mrl-timeline {
  /* Width of the timeline line.
   * Make it divisible by 2 for centering.
   */
  --timeline-width: 2px;

  /* Margin between each timeline entry.
   * It's used for calculations so we need to define it here.
   */
  --timeline-entry-margin: 2em;

  /* Colors for the timeline.
   * It's nice to set these here because otherwise
   * customizing them would require overriding ::before and ::after on <li> elements, etc.
   */
  --timeline-color: var(--body-fg-color-deemphasize-nontext);
  --timeline-marker-color: var(--body-fg-color);

  position: relative;
  list-style-type: none;
  padding: 1em 2em 0 2em;
  border: 1px solid var(--body-fg-color-deemphasize-nontext);

  /* The markers will take up .5em to the left of the <ol>'s content box,
   * so it's recommended to add a margin of at least that much to the left.
   */
  margin: 1em;
}

ol.mrl-timeline li {
  position: relative;
  padding-left: 1em;
  margin-left: calc(var(--timeline-width) / 2); /* Center the marker on the line */
  margin-bottom: var(--timeline-entry-margin);
}

/* Draw a circle to mark each event on the timeline */
ol.mrl-timeline li::before {
  content: '';
  position: absolute;
  left: 1em;
  top: .4em; /* Adjust to align with the first line of text */
  width: 1em;
  height: 1em;
  background: var(--timeline-marker-color);
  border-radius: 50%;
  z-index: 1; /* Ensure the line is drawn behind the circle */
}

/* Draw the line segment */
ol.mrl-timeline li::after {
  content: '';
  position: absolute;

  /* Center the line on the marker */
  left: calc(var(--timeline-width) / 2 * -1);

  /* Draw a line between this item's marker and the next.
   * Start just below the marker.
   * Extend to the top of the next item.
   * The height must account for the margin as well.
   */
  top: 0.5em;
  height: calc(100% + var(--timeline-entry-margin));

  width: var(--timeline-width);

  background: var(--timeline-color);

  /*z-index: 2; /* Draw the line in front of the circle when debugging */
}

/* Remove the line segment from the last item */
ol.mrl-timeline li:last-child::after {
  display: none;
}

ol.mrl-timeline time {
  display: block;
  font-weight: bold;
  margin-bottom: .3em;
}

ol.mrl-timeline p {
  margin: 0;
}

/* Styling for the discontinuity marker */
ol.mrl-timeline li .mrl-timeline-discontinuity {
  border: none;
  margin: 0;
  padding: 0;
  height: 1em;
  width: 3em;
  position: relative;
  overflow: visible;

  background: transparent; /* Don't show the <hr> itself */
}

ol.mrl-timeline li .mrl-timeline-discontinuity::before {
  content: '';
  position: absolute;
  left: -1.5em;
  top: 50%; /* Center the marker vertically */
  width: 1em;
  height: 0.2em;
  border-top: 1px solid var(--timeline-marker-color);
  border-bottom: 1px solid var(--timeline-marker-color);
  z-index: 1; /* Ensure the line is drawn behind the discontinuity marker */
}

/* Remove default marker discontinuity items */
ol.mrl-timeline li:has(.mrl-timeline-discontinuity)::before {
  display: none;
}

Here’s an example with more styling: colors and a larger size.

  1. In the beginning the Universe was created.

    This had made many people very angry and has been widely regarded as a bad move

  2. French Constitution of the Fifth Republic adopted

  3. German reunification completed

Source code for timeline with custom styles

HTML

<ol class="mrl-timeline example-customized">
  <li class="mrl-event-universe">
      <time>Year 0</time>
      <p>In the beginning the Universe was created.</p>
      <p>This had made many people very angry and has been widely regarded as a bad move</p>
  </li>
  <li class="mrl-event-france">
      <time datetime="1958-10-04">4 October 1958</time>
      <p>French Constitution of the Fifth Republic adopted</p>
  </li>
  <li class="mrl-event-germany">
      <time datetime="1991-03-15">15 March 1991</time>
      <p>German reunification completed</p>
  </li>
</ol>

/* -*- mode: html -*- */

CSS

(Applied on top of the default CSS.)

/* An example of customizing the timeline */

ol.mrl-timeline.example-customized {
  font-size: 1.5rem;
  line-height: 1.5;
}

/* We can customize inddividual events */
ol.mrl-timeline.example-customized li.mrl-event-universe::before {
  background: blueviolet;
}
ol.mrl-timeline.example-customized li.mrl-event-france::before {
  background: linear-gradient(to right, blue 0%, blue 33%, red 33%, red 66%, white 66%, white 100%);
}
ol.mrl-timeline.example-customized li.mrl-event-germany::before {
  background: linear-gradient(to bottom, black 0%, black 33%, red 33%, red 66%, goldenrod 66%, goldenrod 100%);
}

Responses

Webmentions

Hosted on remote sites, and collected here via Webmention.io (thanks!).

Comments

Comments are hosted on this site and powered by Remark42 (thanks!).