Jump to main content

Morphing Menu Button Updated

  • Published:
  • Category: CSS

Let’s Make This Fancier

My previous article, Morphing Menu Button, showed how we could create an almost exact replica of Codrop’s Morphing Button Concept with only CSS.

A colleague of mine, @artlawry, and I were talking about my original article shortly after I published it, and we (mostly he) came up with a way to make this a bit more usable.

By making the menu hit area actually styled (my bad on being lazy the first time through) and by coming up with a way to make it easier to close the sidebar navigation than with just the small X that was originally there.

So let’s take a look at the updated demo before diving into what was changed.

See the Pen Morph Menu Button Updated by Scott (@scottohara) on CodePen.

Let's start with the HTML

<div class="page">

    <!-- new! -->
    <input type="radio" id="nav-expand" name="nav" class="invis" />
    <nav class="nav-side">
      <label for="nav-collapse" class="close">
        &times;
      </label>
      <!-- new! -->
      <label for="nav-expand" class="btn-label">
        <span class="top"></span><span class="middle"></span><span class="bottom"></span><span class="label">MENU</span>
      </label>

      <ul class="menu-list">
        <li>
          <a href="#!" title="descriptive title">
            Link Label
          </a>
        </li>
      </ul>
    </nav>

    <!-- new! -->
    <input type="radio" id="nav-collapse" name="nav" checked="checked" class="invis" />
    <main class="main-base" role="main">

      <header class="header-base" role="banner">
        ...
      </header>

      <article>
        ...
      </article>

      <footer>
        ...
      </footer>

      <!-- new! -->
      <label for="nav-collapse" class="overlay"></label>
    </main>

  </div>

I’ve added a &lt;!-- new! --> comment near all the areas of the HTML that have changed since the previous article.

As you can see, an actual menu icon has been put in place using only &lt;span> elements and CSS. (To see an example of a menu nav icon that uses less markup, but has a small bit of JS to toggle classes, check out this codepen.)

Next, instead of using a checkbox to initiate the showing / hiding of the navigation and pushing the page over, we’re instead using radio buttons.

Switching to the radio buttons allowed us to initiate the overlay effect, which is just a &lt;label> styled through the class .overlay to mimic an overlay (a bit repetitive there, no?) on top of the content. This helps drive focus to the nav menu, since all other content has been darkened out. It serves the double purpose of providing a larger hit area to close the nav sidebar (since it’s a label that also targets the nav-collapse radio button).

As with before, the order of the mark-up here is important, as we are relying heavily on the sibling selector + and :checked pseudo class to affect the various transitions that are happening on our page.

Now here is the updated parts of the CSS. You can see the full CSS by checking out the codepen demo above.

.btn-label {
  cursor: pointer;
  display: block;
  height: 60px;
  left: 0;
  position: absolute;
  top: 0;
  width: 60px;
}
  .btn-label .top {
    background-color: #fff;
    height: 3px;
    left: 12px;
    position: absolute;
    right: 12px;
    top: 12px;
  }

  .btn-label .middle {
    background-color: #fff;
    height: 3px;
    left: 12px;
    position: absolute;
    right: 12px;
    top: 22px;
  }

  .btn-label .bottom {
    background-color: #fff;
    height: 3px;
    left: 12px;
    position: absolute;
    right: 12px;
    top: 32px;
  }

  .btn-label .label {
    text-align: center;
    position: absolute;
    bottom: 2px;
    left: 0;
    right: 0;
    font-size: 12px;
  }

  #nav-expand:checked + .nav-side .btn-label {
    display: none;
  }

.close {
  border-bottom: 1px solid #fff;
  cursor: pointer;
  display: none;
  font-size: 30px;
  height: 40px;
  line-height: 30px;
  padding-right: 15px;
  text-align: right;
}

  #nav-expand:checked + .nav-side .close {
    display: block;
  }

#nav-expand:checked + .nav-side {
  bottom: 0;
  height: 100%;
  left: 0;
  width: 200px;
}

  #nav-expand:checked + .nav-side .menu-list {
    height: 100%;
  }

  #nav-expand:checked + .nav-side .btn-label {
    color: transparent;
    display: inline-block;
    height: 20px;
    line-height: 20px;
    text-align: center;
    width: 20px;
  }

  #nav-expand:checked + .nav-side + .main-base,
  #nav-collapse + .main-base {
    left: 200px;
  }


  #nav-collapse + .main-base > .overlay {
    background-color: rgba(0,0,0,.5);
    bottom: 0;
    left: 0;
    opacity: 1;
    position: absolute;
    right: 0;
    top: 0;
    transition: opacity .3s;
  }

  #nav-collapse:checked + .main-base {
    left: 0;
  }

  #nav-collapse:checked + .main-base > .overlay {
    bottom: 0;
    height: 0;
    left: 0;
    opacity: 0;
    position: absolute;
    right: 0;
    top: 0;
    width: 0;
  }

And that’s it!

Thanks again to @artlawry for extending this out for me. Be sure to follow him on Twitter n’ all.