grid timeline simple

by ShaCP

HTML

<div id="timeline_container">
<p id="timeline-units"></p>
</div>

CSS

body {
  width: 100%;
  height: 100vh;
}

* {
  box-sizing: border-box;
}

#timeline {
  /*  margin-top: 1.5em; */
  display: inline-grid;
  /* grid-template-rows: 6em; */
  height: 8em;
  background-color: black;
  /* gap: 1px; */
  --firstAndLastMarksThickness: 2px;
  border: var(--firstAndLastMarksThickness) solid black;
  border-top: unset;
  border-bottom: unset;
  /* width: calc(100% + 4em); */
  position: relative;
  /* grid-gap: 1px; */
}

#timeline::before {
  width: 100%;
  position: absolute;
  content: "";
  height: 1px;
  background-color: black;
  top: 50%;
  pointer-events: none;
  z-index: 1;
}

.timeline-segment {
  outline: 1px solid black;
  background-color: lightskyblue;
  position: relative;
  /* cursor: pointer; */
}

p {
  margin: 0;
  display: inline-block;
}

.duration,
.time {
  display: none;
  position: absolute;
  z-index: 1;
  background-color: whitesmoke;
  padding: 0 0.5em;
  font-size: 0.9rem;
  width: max-content;
}

.duration {
  top: calc(50% - 0.5em);
  left: 0;
  right: 0;
  margin: 0 auto;
}

.right {
  /* left: calc(100% + var(--firstAndLastMarksThickness)); */
  right: calc(100% + 1px);
}

/* display time of current segment and segment to its right */
.active-segment .time,
.active-segment+.timeline-segment .time:first-of-type,
.active-segment>.duration {
  display: inline-block;
}

/* .segment-active + .timeline-segment .time{
  bottom: 0;
} */

/* move to the bottom the time of the segment to the right of the active segment */
.active-segment+.timeline-segment .time,
.timeline-segment:hover+.timeline-segment:not(.active-segment) .time {
  bottom: 0;
}

/* display both the hovered element and the next one's time */

/* I have one "time" element hidden in each "timeline-segment"
with the time for the first time mark of the segment.
When I hover over the segment, both its and the segment
to the right's time will appear, showing the time for both
segment time marks. The last element has both times, because
it doesn't have...

JavaScript

/* create timeline */

(() => {
  var times = [449.6, 458.415, 421.56, 470.67, 472.81, 471.569, 485.175, 489.185, 488.231, 517.55];
  times.sort();
  var unit = "ms"

  var durations = times.reduce((result, time, i) => {
    if (!i) {
      return result;
    }
    result.push(convertBack(convert(time) * 1 - convert(times[--i]) * 1));
    return result
  }, []);

  /* while ((time -parseFloat(times[--i])) * size < timelineMarkTextWidth) {
          console.log(i);
            timelineMarkClearance++
          } */

  var gridColumnWidths = durations.join("vw ") + "vw"

  var timelineSegments = "";

  var lastSegmentIndex = durations.length - 1;
  var lastTimeIndex = times.length - 1;

  var lengthOfTimeLine = times[lastTimeIndex] - times[0];
  var widthOfTimelineMarkText = 68;

  durations.forEach((duration, i) => {

    /* var  */
    var isLastSegment = i === lastSegmentIndex;
    var durationToTheEndInPixels = convertBack(convert(times[lastTimeIndex]) - convert(times[i]));
    console.log(durationToTheEndInPixels);
    durationToTheEndInPixels = durationToTheEndInPixels * (0.01 * window.innerWidth);
    console.log(durationToTheEndInPixels);
    var isDistanceSameAsTimeMarkTextWidth = widthOfTimelineMarkText > durationToTheEndInPixels;
    var textToRightOfSegmentMark =
      isDistanceSameAsTimeMarkTextWidth || isLastSegment ? " right" : "";
    var timeMarkText = `<p class="time${textToRightOfSegmentMark}">${times[i]}</p>`;

    var durationText = `<p class="duration">${duration}</p>`

    var lastTimeMarkText =
      `<p class="time right">${times[i + 1]}</p>`;

    var timelineSegmentTextStyle =
      `transform: translate(1em, calc(${i} * 2em + 9em));`

    var timelineSegmentText =
      `<p class="timeline-segment-text"
	 style="${timelineSegmentTextStyle}">
	 ${times[i] + unit} ${duration + unit} ${times[i + 1] + unit}
	 </p>`;


    timelineSegments +=
      `<div class="timeline-segment">
 ${timeMarkText}
 ${timelineSegmentText}
 ${durationText}
...