Maximus Decimus Maximus Decimus - 2 months ago 5
CSS Question

Connecting dots with an ordered list in CSS3

I'm just trying to connect some dots with an ordered list but I cannot make it work. I want to turn on a segment according to the active class and additionally I want to add the name of the student between the segment like this pictureenter image description here

Then I can switch to turn on the other segment with the class active.

This is what I've been trying to do.

jsfiddle

UPDATE

I updated my fiddle because I forgot to add the class active to the li element

UPDATE

I updated again my fiddle to show where I should go the name of the person.



ol.timetable li {
min-width: 25%;
}

.timetable {
width: 100%;
list-style: none;
list-style-image: none;
margin: 20px 0 20px 0;
padding: 0;
}

.timetable li {
float: left;
text-align: center;
position: relative;
}

.timetable .date {
display: block;
vertical-align: bottom;
text-align: center;
margin-bottom: 1em;
color: #2B2B2B;
}

.timetable .dot {
color: black;
border: 3px solid #B2B2B2;
background-color: #B2B2B2;
border-radius: 50%;
line-height: 1.2;
width: 1.2em;
height: 1.2em;
display: inline-block;
z-index: 2;
}

.timetable .active .date,
.timetable .active .dot span {
color: black;
}

.timetable .dot:before {
content: "";
display: block;
background-color: #B2B2B2;
height: 0.4em;
width: 50%;
position: absolute;
bottom: 0.9em;
left: 0;
z-index: 1;
}

.timetable .dot:after {
content: "";
display: block;
background-color: #B2B2B2;
height: 0.4em;
width: 50%;
position: absolute;
bottom: 0.9em;
right: 0;
z-index: 1;
}

.timetable li:first-child .dot:before {
display: none;
}

.timetable li:first-child .dot:after .active {
border: 3px solid #F26227 !important;
background-color: #F26227 !important;
}

.timetable li:last-of-type .dot:after {
display: none;
}

.timetable .active .dot {
border: 3px solid #F26227;
background-color: #F26227;
}

.timetable .active .dot:before,
.timetable .active .dot:before {
background-color: #F26227;
}

<ol class='timetable'>
<li class="active">
<span class='date'>5/26/2017</span>
<span class='active dot'>
<span>
</span>
</span>
</li>
<li class="active">
<span class='date'>5/29/2017</span>
<span class='active dot'>
<span></span>
</span>
</li>
<li>
<span class='date'>6/5/2017</span>
<span class='dot'>
<span></span>
</span>
</li>
</ol>




Answer

To simplify how much CSS you need to write, I'd suggest making each line segment composed of just one long :before pseudo-element, rather than a combination of a :before and :after. This also makes it simpler to fill in the preceding line segment when the associated item is active.

For placement of the label, I'm going to assume you'll be adding/removing the <span> containing it dynamically, so it'll be up to you to determine where it should be best placed. To position and center it accordingly, I suggest absolute positioning and a small transformation to center the text.

Putting this all together, you get:

ol.timetable li {
  min-width: 25%;
}
.timetable {
  width: 100%;
  list-style: none;
  list-style-image: none;
  margin: 20px 0 20px 0;
  padding: 0;
}
.timetable li {
  float: left;
  text-align: center;
  position: relative;
}
.timetable .date {
  display: block;
  vertical-align: bottom;
  text-align: center;
  margin-bottom: 1em;
  color: #2B2B2B;
}
.timetable .dot {
  color: black;
  border: 3px solid #B2B2B2;
  background-color: #B2B2B2;
  border-radius: 50%;
  line-height: 1.2;
  width: 1.2em;
  height: 1.2em;
  display: inline-block;
  z-index: 2;
}
.timetable .active .date,
.timetable .active .dot span {
  color: black;
}
.timetable .dot:before {
  content: "";
  display: block;
  background-color: #B2B2B2;
  height: 0.4em;
  width: 100%;
  position: absolute;
  bottom: 0.9em;
  left: -50%;
  z-index: 1;
}
.timetable li:first-child .dot:before {
  display: none;
}
.timetable .active .dot {
  border: 3px solid #F26227;
  background-color: #F26227;
}
.timetable .active + .active .dot:before {
  background-color: #F26227;
}
.timetable li > span:nth-child(3){
  position:absolute;
  right:0;
  bottom:-15px;
  transform: translateX(50%);
}
<ol class='timetable'>
  <li class="active">
    <span class='date'>5/26/2017</span>
    <span class='active dot'>
     <span>
     </span>
    </span>
    <span>John Doe</span>
  </li>
  <li class="active">
    <span class='date'>5/29/2017</span>
    <span class='active dot'>
      <span></span>
    </span>
  </li>
  <li>
    <span class='date'>6/5/2017</span>
    <span class='dot'>
      <span></span>
    </span>
  </li>
</ol>

Note that if the label element isn't guaranteed to be in the same place within the item, I'd suggest adding a class to it to make it easier to target with CSS. Also, if you'd like to hide any unfilled lines behind the active dots, just set the z-index on .timetable .dot:before to a negative value.

Also note the usage of the sibling selector in .timetable .active + .active .dot:before. This ensures that only the line between two active dots will be highlighted, rather than every line associated with an active item.

Hope this helps! Let me know if you have any questions.