Pizza Time Hovers

Chris Coyier //

Hover Maester Jenn Lukas sent me a link to PizzaTime.com. We agreed that 1) those are some pretty neat hovers! and 2) it's pretty cool that there is a quality website at all at a domain like PizzaTime.com - in which that she typed in randomly hoping there would be.

They have a set of navigational boxes that look like this:

Then they go through a neat multi-step transitional thing to essentially turn red:

The red square that the icon is in expands left/right to fill the parent box, then up/down afterward. The text and border change colors to remain visible over the expanded red box.

The HTML

We'll use this:

<a href="#0" class="pizza-link">
  <span class="icon maki-embassy"></span>
  <h3>Find a Store</h3>
  <p>We've got a location near you! As far as Bellingham and Lewiston and Yakima and South to Olympia.</p>
</a>

In case you haven't gotten the memo yet, it's cool to wrap whatever you want in an anchor tag now, so it's easy to make this whole box a link. In our case we'll use that anchor to style the actual box.

Just for this demo, I used We Love Icon Fonts and picked some random icons to use. That site has you use spans with pre-determined classes to show the icons. If I were to take this concept to production, in this case, I'd probably use a pseudo element instead because these icons hold no content value. Or if I was using a span system, I'd apply it with a data-icon attribute and aria-hidden. Read more.

The CSS

This is a decent use case for of nesting in Sass. Everything we're working with here is related to this .pizza-time link, so let's just nest under that. Some boring CSS removed...

.pizza-link {
  display: block;
  float: left;
  /* yadda yadda yadda */
  h3 {
    border-bottom: 1px solid #eee;
    /* relative positioning keeps it on top of :before */
    position: relative;
  }
  p {
    /* relative positioning keeps it on top of :before */
    position: relative;
  }
  h3, p {
    /* "ease" and "all" are implied */
    @include transition(0.2s);
  }
  .icon {
    position: absolute;
    color: white;
    /* position in middle on top */
  }
  &:before {
    content: "";
    background: #D62121;
    /* position in middle on top */
    /* BELOW icon and other content */
    /* :before makes this easier than :after */
    position: absolute;
    width: 50px;
    height: 50px;
    top: 20px;
    left: 50%;
    margin-left: -25px;
    @include transition(
      /* FIRST STEP */
      width 0.2s,
      left 0.2s,
      margin-left 0.2s,
      /* SECOND STEP */
      top 0.2s 0.2s,
      height 0.2s 0.2s
    );
  }
  &:hover, &:active {
    h3 {
      color: white;
      border-bottom-color: #E14646;
    }
    p {
      color: white;
    }
    &:before {
      width: 230px;
      left: 0;
      top: 0;
      margin-left: 0;
      /* hacky, but the parent element */
      /* doesn't have explicit height */
      /* so can't use 100% */
      height: 320px;
    }
  }
}

Three notable points:

  1. The "red box" is a pseudo element. In the past I would have used a span or something here, but now we're able to transition pseudo elements, so might as well.
  2. Because the "red box" is an absolutely positioned :before, all we have to do to the other content inside is give it position: relative and it will sit on top of the red box in the natural document stacking order.
  3. We made the transition "multi-step" by comma-separating all the values to be transitioned. The horizontal-related properties go first: width, left, margin-left. Then the vertical-related properties go "second": top, height. By specifying a delay value equal to the duration value of the first step values, they will happen in sequence after the "first step" properties.

Demo

Check out this Pen!

I think we're all aware now that most touch screens don't have hover states. Perhaps users of these devices won't see our little fancy hover. That's OK. They are links. They still work.