No Time Dad

A blog about web development written by a busy dad

Retro Style Stacked Button

Intro

Have you noticed that most buttons these days all look the same? Everyone is using the same semi-rounded corner solid color button. This could be because of people using frameworks like Material or Bootstrap. Or it could be that we see what everyone else is doing and we just follow them. I have done it lots of times. I’ll probably continue to do it. In fact, many of my examples use these same styled buttons.

I really enjoy seeing a site that has a unique take on buttons (or any elements really). The average visitor to your site probably won’t notice it or know the difference, but I do. I appreciate the thought that goes into designing a unique element. Whoever made that unique button was actively avoiding the round filled button and decided to go against the grain a bit. A small act of rebellion.

Some inspiration & investigation

I stumbled on a unique button style on the TryNow site and really appreciated the thought that went into it. Their whole site is actually designed really well, but the buttons caught my attention first. The buttons have a fun retro style that was much different than what I’ve seen before. Below is an example of one of their buttons.

After seeing such a nice button, the natural next step is to inspect it and see how it is built. I was expecting to find that the button was composed of two divs stacked on top of each other, with one of the divs using position: absolute;. That is pretty much what I did find, but I noticed they were using z-index to change the stacking context. That is not totally uncommon from what I’ve seen. What did surprise me a little bit was that their sizing values were were sort of random. I saw things like 0.238rem or 0.421rem. My first thought after seeing this was “wow, this developer is extremely precise”. Then I noticed in the css panel that some of the css selectors has webflow in the name. Webflow, being a no-code tool, probably allows you to drag to re-size element, which is how you’d end up with random sizes like that. The person who made the button is still probably extremely precise.

As always, I thought it would be fun to try and come up with my own version of this button. Maybe without using z-index, since I think position: absolute on its own might be enough. The position property is pretty powerful. It might also bring you to tears. There is a really good write-up on this property in the MDN docs.

Building the button

It turns out that stacking elements can be a tricky thing. There are more than a few ways to do it, and I am not sure if any of those ways is the way. The way I’ve chosen to do it for this button is to use a parent div with postition: relative with two child divs that both use position: absolute. You can then move either child element around as needed using the positioning properties top, right, bottom, and left.

Basic structure

The basic structure of the html and css for this button element will look as follows:

<div class="Parent">
  <a href="#home">
    <div class="Button Bottom__Child"></div>
    <div class="Button Top__Child">...</div>
  </a>
</div>
.Parent {
  position: relative;
}

.Button {
  /* Shared positioning and size */
  position: absolute;
  height: 55px;
  width: 150px;
}

.Bottom__Child {
  /* Needs to slide out slightly from the bottom */
  left: 8px;
  top: 8px;
  ...
}

.Top__Child {
  ...
  /* Primarily just styling, positioning will be default */
}

Note that the Bottom__Child div is actually above the Top__Child div in the markup. This is a little confusing. It is also probably where z-index would come into play. You could set z-index: -1 on the second div, which would force the first div to be the Top__Child. I think that in itself is a little more confusing, so I chose to leave them as they were.

Styling the button

Now that we have our basic structure for the button, really all we need to do is style it and change the hover behavior. The bottom div will have a white background color with a dark border. The dark boarder on the bottom will be the same border that is used for the background color on the top div. We’ll also add a 3px dark border on both divs.

The bottom div will remain unchanged when you hover over the button, but the top div background color should change to match the bottom div’s color. We’ll also update the text color to the dark color so you can still read the text when you hover.

We’ll update the two child selectors in our css and add a new selector to handle the :hover styles on our Top__Child. In the Parent selector I defined two custom properties to hold the values for each of the colors. I think having the custom property names make it easier to understand how the colors are switching around on hover. Our html will remain the same as above.

...
.Parent {
  --dark-blue: #2b2d42;
  --light-grey: #e9ecef;
  position: relative;
}

.Button {
  position: absolute;
  height: 55px;
  width: 150px;
}

.Bottom__Child {
  left: 8px;
  top: 8px;
  background-color: var(--light-grey);
  border: 3px solid var(--dark-blue);
}

.Top__Child {
  /* Use flexbox to align the text in the element */
  display: flex;
  justify-content: center;
  align-items: center;
  color: var(--light-grey);
  font-weight: 700;
  font-size: 24px;
  /* Solid dark color when not hovering */
  background: var(--dark-blue);
  /* You won't notice the border when not hovering */
  border: 3px solid var(--dark-blue);
}

.Top__Child:hover {
  /* Change to the light background on hover */
  background-color: var(--light-grey);
  /* Switch to dark text on hover so the words are still readable */
  color: var(--dark-blue);
}

Thoughts, final code, and demo

So, there we have a nice button that breaks out of the “round button solid color” mold a bit. As mentioned earlier, there are a few different ways to build this exact button. One of the more interesting ones is using css grid. An example of stacking with css grid can be found in this css-tricks article.

A word of caution on using the position: absolute method I’ve described here. Aligning and spacing around the element is really annoying. It just won’t go where I want it to go. I found that I had to add lots of padding to adjacent elements to get things to line up near this button. It is so annoying, in fact, that I probably won’t use this button at all in any type of nav bar or any place where alignment really matters. Maybe the grid version of stacking is easier for alignment.

I do also recognize that this retro styled button is an acquired taste. Some people really prefer the look of the “round button solid color” button. That is fine. It is not for everyone and I accept that. But I do think that buttons and elements like this will help your page or product stand out a bit more than others, and I think that makes it worth it to go against the grain and break out of the mold a little bit with your designs.

.Parent {
  --dark-blue: #2b2d42;
  --light-grey: #e9ecef;
  position: relative;
}

.Button {
  position: absolute;
  height: 55px;
  width: 150px;
}

.Bottom__Child {
  left: 8px;
  top: 8px;
  background-color: var(--light-grey);
  border: 3px solid var(--dark-blue);
}

.Top__Child {
  display: flex;
  justify-content: center;
  align-items: center;
  color: var(--light-grey);
  background: var(--dark-blue);
  border: 3px solid var(--dark-blue);
  font-weight: 700;
  font-size: 24px;
}

.Top__Child:hover {
  color: var(--dark-blue);
  background-color: var(--light-grey);
}
<div class="Parent">
  <a href="#home">
    <div class="Button Bottom__Child"></div>
    <div class="Button Top__Child">Log in</div>
  </a>
</div>