Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Responsive arrow progress bar with transparent borders

I am trying to build a progress bar as seen often within checkouts.

Transparent border progress bar

The problem is, that the borders between the arrows are transparent and the whole thing should be responsive. I got it this far:

http://codepen.io/MrBambule/pen/rVBeoz

But I can't figure out how to get the items of the bar to span the whole width of the parent container (red border in the pen) and stay responsive.
I think I could figure it out with JS but I'd rather have a CSS solution.
Help would be much appreciated.

HTML

<ul class="progress-nav">
  <li class="active">
    <span>1. FOO</span>
  </li>
  <li>
    <span>2. BAR</span>
  </li>
  <li>
    <span>3. BAZ</span>
  </li>
</ul>

CSS

$bar-color: rgba(255, 255, 255, 0.2);
$bar-active-color: rgba(255, 255, 255, 0.6);
$arrow-size: 22px;

body {
  background: linear-gradient(left, #803689, #5eb6e4);
}

.progress-nav {
  position: relative;
  font-size: 0;
  margin: 100px auto;
  width: 80%;
  max-width: 900px;

  // dummy border to display the width problem 
  border: 1px solid red;

  li {
    position: relative;
    color: #fff;
    font-size: 12px;
    display: inline-block;
    width: 20%;
    margin-right: 48px;
    list-style: none;
    background: $bar-color;
    padding: $arrow-size 0;

    transition: background .5s, color .5s;

    span {
      position: absolute;
      width: 100%;
      top: 50%;
      left: 50%;
      transform: translateX(-33px) translateY(-35%);
    }

    &:before,
    &:after {
      content: '';
      position: absolute;
      display: block;
      top: 0;

      transition: all .5s;
    }
    &:before {
      border: $arrow-size solid $bar-color;
      border-left-color: transparent;
      left: -$arrow-size*2;
    }
    &:after {
      border: $arrow-size solid transparent;
      border-left-color: $bar-color;
      right: -$arrow-size*2;
    }
    &:first-child:before {
      border: none;
      width: $arrow-size*2;
      height: $arrow-size*2;
      background: $bar-color;
      border-radius: 4px 0 0 4px;
    }
    &:last-child:after {
      border: none;
      right: -$arrow-size;
      width: $arrow-size;
      height: $arrow-size*2;
      background: $bar-color;
      border-radius: 0 4px 4px 0;
    }

    &.active,
    &:hover {
      background: $bar-active-color;
      color: #000;

      &:before {
        border-color: $bar-active-color;
        border-left-color: transparent;
      }
      &:after {
        border-left-color: $bar-active-color;
      }
      &:first-child:before,
      &:last-child:after {
        background: $bar-active-color;
      }
    }
  }
}
like image 706
Karsten Buckstegge Avatar asked Apr 20 '15 09:04

Karsten Buckstegge


1 Answers

you could use something like:

.wrap {
  width: 100%;
  height: 30px;
  z-index:-2;white-space: nowrap;
  overflow:hidden;
}
.wrap div:first-child{margin-left:-2%;}
.progress {
  margin:0;
  margin-left:0.5%;
  height: 30px;
  width: 25%;
  position: relative;
  display: inline-block;
  text-align: center;
  line-height: 30px;
  transition: all 0.8s;
}
.progress:before,
.progress:after {
  content: "";
  position: absolute;
  transition: all 0.8s;
  z-index:-1;
}
.progress:before {
  height: 50%;
  width: 100%;
  top: 0;
  left: 0;
  background: rgba(0, 0, 0, 0.2);
  -webkit-transform: skew(45deg);
  -moz-transform: skew(45deg);
  transform: skew(45deg);
}
.progress:after {
  height: 50%;
  width: 100%;
  top: 50%;
  left: 0;
  background: rgba(0, 0, 0, 0.2);
  -webkit-transform: skew(-45deg);
  -moz-transform: skew(-45deg);
  transform: skew(-45deg);
}
.progress:hover:before,
.progress:hover:after {
  background: tomato;
}
<div class="wrap">
  <div class="progress">
    simple
  </div>
  <div class="progress">
    as
  </div>
  <div class="progress">
    complex
  </div>
  <div class="progress">
    Web Development
  </div>
</div>

which is responsive to the width of the screen.

It makes use of the transform:skew property for the middle bars, and a small border hack for the two far elements. This results in the output shown below:

Result

enter image description here

NOTE

If you are creating these dynamically (and want them all along the same line), then you will need to alter the width stated in the first css rule (currently set to 23%).

like image 144
jbutler483 Avatar answered Nov 03 '22 01:11

jbutler483