Search code examples
htmlcsssassuser-experience

Vertical Connecting Lines with CSS


I would like to have a connecting vertical line between each circle. The "Sections" are dynamic in vertical height.

Menu

Here is the current SASS:

@import '../sass/sa.common';
$color: $sa-gray-4;
$colorActive: $sa-green;
$colorComplete: $sa-green;
.progress-indicator {
  margin-bottom: 50px;
  margin-top: 75px;
  .step {
    margin-top: 40px;
    content: "";
    display: table;
    clear: both;
    position: relative;
    &:first-child {
      margin-top: 0;
    }
    &:last-child {
      div {
        &.circle {
          &:before {
            display: none;
          }
        }
      }
    }
    &.active {
      div {
        color: $colorActive;
        &.circle {
          border-color: $colorActive;
        }
        a {
          color: $colorActive;
        }
      }
    }
    &.complete {
      div {
        color: $colorComplete;
        &.circle {
          border-color: $colorComplete;
          &.filled {
            background-color: $colorComplete;
            color: $sa-white;
          }
        }
      }
    }
    div {
      color: $color;
      display: table-cell;
      float: left;
      padding-top: 2px;
      font-size: 16px;
      font-weight: bold;
      vertical-align: middle;
      &.circle {
        height: 30px;
        width: 30px;
        text-align: center;
        border: 2px solid $color;
        border-radius: 50%;
        &:before {
          content: "";
          position: absolute;
          z-index: 1;
          margin-top: 26px;
          left: 13px;
          border: 1px solid $sa-gray-4;
          height: 125%;
        }
      }
      &.text {
        padding-left: 10px;
        padding-top: 5px;
        ul {
          margin: 0;
          margin-top: 15px;
          padding: 0;
          list-style-type: none;
          li {
            a {
              display: block;
              margin-top: 5px;
              &:first-child {
                margin-top: 0;
              }
            }
          }
        }
      }
    }
  }
}

CSS:

<style type="text/css">@charset "UTF-8";
.btn.btn-green {
  background-color: #80b241;
  color: #ffffff; }
  .btn.btn-green:hover {
    background-color: #88bc47; }

.btn.btn-gray-1 {
  background-color: #595959;
  color: #e7e5e1; }
  .btn.btn-gray-1:hover {
    background-color: #666666; }

.label.label-green {
  background-color: #80b241;
  color: #242424; }

.label.label-gray-1 {
  background-color: #595959;
  color: #ffffff; }

.btn.btn-green {
  background-color: #80b241;
  color: #ffffff; }
  .btn.btn-green:hover {
    background-color: #88bc47; }

.btn.btn-gray-1 {
  background-color: #595959;
  color: #e7e5e1; }
  .btn.btn-gray-1:hover {
    background-color: #666666; }

.label.label-green {
  background-color: #80b241;
  color: #242424; }

.label.label-gray-1 {
  background-color: #595959;
  color: #ffffff; }

.progress-indicator {
  margin-bottom: 50px;
  margin-top: 75px; }
  .progress-indicator .step {
    margin-top: 40px;
    content: "";
    display: table;
    clear: both;
    position: relative; }
    .progress-indicator .step:before {
      content: "";
      position: absolute;
      z-index: 1;
      margin-top: 26px;
      left: 13px;
      border: 1px solid #ADABA6;
      height: 125%; }
    .progress-indicator .step:first-child {
      margin-top: 0; }
    .progress-indicator .step:last-child:before {
      display: none; }
    .progress-indicator .step.active div {
      color: #80b241; }
      .progress-indicator .step.active div.circle {
        border-color: #80b241; }
      .progress-indicator .step.active div a {
        color: #80b241; }
    .progress-indicator .step.complete div {
      color: #80b241; }
      .progress-indicator .step.complete div.circle {
        border-color: #80b241; }
        .progress-indicator .step.complete div.circle.filled {
          background-color: #80b241;
          color: #ffffff; }
    .progress-indicator .step div {
      color: #ADABA6;
      display: table-cell;
      float: left;
      padding-top: 2px;
      font-size: 16px;
      font-weight: bold;
      vertical-align: middle; }
      .progress-indicator .step div.circle {
        height: 30px;
        width: 30px;
        text-align: center;
        border: 2px solid #ADABA6;
        border-radius: 50%; }
      .progress-indicator .step div.text {
        padding-left: 10px;
        padding-top: 5px; }
        .progress-indicator .step div.text ul {
          margin: 0;
          margin-top: 15px;
          padding: 0;
          list-style-type: none; }
          .progress-indicator .step div.text ul li a {
            display: block;
            margin-top: 5px; }
            .progress-indicator .step div.text ul li a:first-child {
              margin-top: 0; }

.category-selector {
  margin-top: 30px; }
  .category-selector .header {
    border-bottom: 2px solid #80b241; }
    .category-selector .header:before, .category-selector .header:after {
      content: " ";
      display: table; }
    .category-selector .header:after {
      clear: both; }
  .category-selector .section-container:before, .category-selector .section-container:after {
    content: " ";
    display: table; }
  .category-selector .section-container:after {
    clear: both; }
  .category-selector .section-container .section {
    float: left;
    height: 400px;
    min-width: 150px;
    overflow-y: scroll; }
    .category-selector .section-container .section .item {
      border-bottom: 1px solid #80b241;
      cursor: pointer;
      padding: 5px 10px 5px 5px; }
      .category-selector .section-container .section .item:last-child {
        border: 0; }
      .category-selector .section-container .section .item.active {
        background-color: #80b241;
        color: #ffffff; }
</style>

And the Markup:

<div class="row">
    <div class="col-lg-3">
        <div class="progress-indicator">
            <div class="step">
                <div class="circle">1</div>
                <div class="text">Select Category</div>
            </div>
            <div class="step active">
                <div class="circle">2</div>
                <div class="text">
                    Fill Out Listing
                    <ul>
                        <li>
                            <a href="#">Vital Fields</a>
                            <a href="#">Image Url</a>
                            <a href="#">Dimensions</a>
                        </li>
                    </ul>
                </div>
            </div>
            <div class="step">
                <div class="circle">3</div>
                <div class="text">Bulk Options</div>
            </div>
            <div class="step">
                <div class="circle">4</div>
                <div class="text">More Options</div>
            </div>
        </div>

        <div class="text-center">
            <button class="btn btn-default" style="margin-bottom: 10px;">
                SAVE AS DRAFT
            </button>
            <button class="btn btn-gray-1">
                MOVE TO PUBLISH QUEUE
            </button>
        </div>
    </div>
    <div class="col-lg-6">
        <div class="category-selector">
            <div class="header">
                <div class="pull-left">
                    <h4>Select a Category</h4>
                </div>
                <div class="pull-right">
                    <button class="btn btn-green">Next</button>
                </div>
            </div>
            <div class="section-container">
                <div class="section">
                    <div class="item" [ngClass]="{active: selectedCategory && category.id === selectedCategory.id}" *ngFor="let category of topLevelCategories" (click)="getSubCategories(category)">
                        {{category.displayName}}
                    </div>
                </div>
                <div class="section" *ngIf="subCategories && subCategories.length > 0">
                    <div class="item" [ngClass]="{active: selectedSubCategory && subCategory.id === selectedSubCategory.id}" *ngFor="let subCategory of subCategories" (click)="getFields(subCategory)">
                        {{subCategory.displayName}}
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div class="col-lg-3">
        Side Nav/Slide In
    </div>
</div>

Solution

  • Not all browsers honor the display of ::before on elements with display:table. (I have a hunch you are experiencing this in FF? - In Chrome they're displayed). There are two possible fixes:

    1. Either replace display:table with display:flex and display: table-cell with display: block...
    2. ...or use proper html elements (divs?) instead of pseudo-elements for lines.

    Other notes you might find useful:

    • remove z-index from .step::before
    • change height:125% to height:calc(100% + {N}px) where {N} is the difference in px between the actual height of .circle and 40px (top margin of .step). Using this technique you can control exact size of line and match the gap between the circles down to the pixel, thus not needing to hide the extra line length.

    Hope the above makes sense and helps. Don't forget to autoprefix.