<dl class="timeline">
  <dt>1969</dt><dd>UNICS</dd>
  <dt>1971</dt><dd>UNIX Time-Sharing System</dd>
  <dt>1978</dt><dd>BSD</dd>
  <dt>1980</dt><dd>XENIX OS</dd>
  <dt>1981</dt><dd>UNIX System III</dd>
  <dt>1982</dt><dd>SunOS</dd>
  <dt>1983</dt><dd>UNIX System V</dd>
  <dt>1986</dt><dd>GNU (Trix)</dd>
               <dd>HP-UX</dd>
  <dt>1987</dt><dd>Minix</dd>
  <dt>1989</dt><dd>NeXTSTEP</dd>
               <dd>SCO UNIX</dd>
  <dt>1990</dt><dd>Solaris</dd>
  <dt>1991</dt><dd>Linux</dd>
  <dt>1993</dt><dd>FreeBSD</dd>
  <dt>1995</dt><dd>OpenBSD</dd>
  <dt>1999</dt><dd>Mac OS X</dd>
</dl>
body {
  //min-width: 900px;
}

html {
  font-family: sans-serif;
  font-size: 14px;
}

dl {
  padding-left: 2em;
  margin-left: 1em;
  border-left: 1px solid;
  
  dt:before {
    content: '-';
    position: absolute;
    margin-left: -2.05em;
  }
}

svg.timeline-visualization {
  circle {
    fill: white;
    stroke: black;
    stroke-width: 2;
  }
  display: inline-block;
}
var SVG_NS = 'http://www.w3.org/2000/svg';

function supportsSvg() {
	return document.implementation &&
		(
			document.implementation.hasFeature('http://www.w3.org/TR/SVG11/feature#Shape', '1.0') ||
			document.implementation.hasFeature('SVG', '1.0')
		);
}

function getDataFromDefinitionList(definitionList) {
  var children = definitionList.children;
  
  var yearIndex = {};
  var data = [];
  var currentYear = null;
  
  for (var childIndex = 0; childIndex < children.length; childIndex++) {
    var child = children[childIndex];
    
    if (child.nodeName == 'DT') {
      currentYear = child.textContent;
    } else if (child.nodeName == 'DD' && currentYear !== null) {
      if (!yearIndex[currentYear]) {
        yearIndex[currentYear] = data.length;
        data.push({
          year: +currentYear,
          values: []
        });
      }
      
      data[yearIndex[currentYear]].values.push(child.textContent);
    }
  }
  return data;
}

function createSvgElement() {
  var element = document.createElementNS(SVG_NS, 'svg');
  element.setAttribute('width', '100%');
  element.setAttribute('height', '250px');
  
  // Improvement... 
  // you should set a viewBox so that when the page scales 
  // the whole timeline is still viewable.
  
  element.classList.add('timeline-visualization');
  
  return element;
}

function drawTimeline(svgElement, data) {
  var paper = Snap(svgElement);
  
  var canvasSize = parseFloat(getComputedStyle(paper.node)["width"]);
  
  var start = +data[0].year;
  var end = +data[data.length - 1].year;
  
  // add some padding
  start--;
  end++; end++;
  
  var range = end - start;
  
  paper.line(0, 200, canvasSize, 200).attr({
    'stroke': 'black',
    'stroke-width': 2
  });
  
  data.forEach(function(datum) {
    var x = canvasSize * (datum.year - start) / range;
    
    paper.circle(x, 200, 6);
    
    paper.text(x, 230, datum.year).attr({
      'text-anchor': 'middle'
    });
    
    var averageIndex = (datum.values.length - 1) / 2;
    var xOffsetSize = 24;
    datum.values.forEach(function(value, index) {
      var offset = (index - averageIndex) * xOffsetSize;
      
      paper.text(x + offset, 180, value)
        .attr({
          'text-anchor': 'start'
        })
        .transform('r -45 ' + (x + offset) + ' 180');
    });
  });
}

if (supportsSvg()) {
  var timeline = document.querySelector('.timeline');
  
  timeline.style.display = 'none';
  
  var data = getDataFromDefinitionList(timeline);
  
  var svgElement = createSvgElement();
  timeline.parentNode.insertBefore(svgElement, timeline);
  
  drawTimeline(svgElement, data);
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.3.0/snap.svg-min.js