Auralinna.blog Tero Auralinna's blog about intriguing world of web development. Tweaking pixels since the '90s.

Navigation wizard example with equal width steps and flexible width of the last step

Published on January 1, 2018. Edited on July 5, 2020.

The title of this blog post is a little bit monstrous, but I'll try my best to explain it. I had an interesting challenge at work a while ago. My task was to create a navigation wizard in which all steps should have equal width except the last one. The width of the last step should be dependent on the text width. However, the last step width shouldn't exceed other steps width either.

Navigation wizard example

In the end, it was pretty easy to implement with CSS Flexbox. The following demo probably explains this better than a thousand words. This example is not optimized for small mobile screen sizes. It scales, but at some point, it won't fit anymore.

Embedded content: https://codepen.io/teroauralinna/pen/MrmryX

1. First version of the navigation wizard

HTML

Let's start by creating a simple list and links for the wizard steps.

<ul class="wizard">
  <li class="wizard__step">
    <a href="#1" class="wizard__step-link">
      This is the first step
    </a>
  </li>
  <li class="wizard__step">
    <a href="#2" class="wizard__step-link">
      This is the second step
    </a>
  </li>
  <li class="wizard__step">
    <a href="#3" class="wizard__step-link">
      This is the third step
    </a>
  </li>
  <li class="wizard__step">
    <a href="#4" class="wizard__step-link">
      This is the fourth step
    </a>
  </li>
  <li class="wizard__step">
    <a href="#5" class="wizard__step-link">
      This is the last step with the flexible width
    </a>
  </li>
</ul>

SCSS

.wizard {
  counter-reset: stepNo;
  display: flex;
  margin: 0;
  padding: 0;
}

.wizard__step {
  flex: 1 0 0;
  list-style: none;
  padding: 0 2% 0 0;
  position: relative;

  &::before {
    border-top: 3px solid #333;
    content: "";
    left: 0;
    position: absolute;
    right: 0;
    top: 25px;
  }

  &:last-child {
    border: 0;
    margin: 0;
    padding: 0;

    &::before {
      border: 0 none;
    }
  }
}

.wizard__step-link {
  color: #333;
  display: block;
  font-size: 1rem;
  font-weight: bold;
  position: relative;
  text-decoration: none;
  z-index: 10;

  &:before {
    background: #333;
    color: #fff;
    counter-increment: stepNo;
    content: counter(stepNo) ".";
    display: block;
    font-size: 2rem;
    height: 50px;
    line-height: 50px;
    margin-bottom: 12px;
    text-align: center;
    width: 50px;
  }

  &:hover,
  &:focus {
    color: #000;
    text-decoration: none;

    &:before {
      background: #fff;
      border: 1px solid #333;
      color: #333;
    }
  }
}

CSS counter feature will be used to generate step numbering. Counter easily keeps step numbers dynamic regardless of how many steps there are.

2. Add flexible width to the last step

Now we have the navigation wizard with equal width steps. We need to change the last step styles slightly to make it flexible based on a text width.

SCSS

.wizard__step {
  &:last-child {
    flex: 0 0 auto;
  }
}

@for $i from 2 through 10 {
  .wizard__step:last-child:nth-child(#{$i}) {
    max-width: 100% / $i;
  }
}

Let me know if you have any thoughts about the implementation or tips on how to improve!