Work

Work

Snippets

Snippets

Graphics

Graphics

Blog

Blog

Email Search

Google Action Button

By Dónal - February 2018

CSS

Google

Lists

Recreating Google's action button with only CSS

View Demo

You’ve seen this button – create new email, create new calendar event, create new drive folder, etc. It’s Google’s action button from their Material Design repertoire around 2014. It’s a useful little Swiss army knife often anchored to the corner of a Google application, both on desktop and mobile. On occasion it kicks off a single primary function of the app, but more often it will expand a list of functions common to the app, generally dispersing in an upward direction.

From a semantic HTML point of view, this list of options generated by the action button would ideally be in the form of a typical list, like the type we might see in a site navigation. It isn’t quite as simple in Google’s markup, but for now let’s stick to semantics.

We’ll start with a standard HTML unordered list and wrap it in an ‘action-button’ container:

<div id="action-button">
  <ul>
    <li><a href="#">1</a></li>
    <li><a href="#">2</a></li>
    <li><a href="#">3</a></li>
  </ul>
</div>

Using the right background colour, drop shadow, and border-radius, we can easily imitate the style of Google’s action button*. The plus sign is simply a :before and :after pseudo sitting absolutely in the centre:

* Please note that for purposes of clarity I am not using CSS vendor prefixes, which should be used in best practices.

#action-button {
position: absolute;
right: 40px;
bottom: 40px;
width: 60px;
height: 60px;
background: #f44336;
border-radius: 50%;
box-shadow: 0px 2px 9px rgba(0,0,0,0.35);
transition: all 0.2s ease;
}
 
#action-button:before, #action-button:after {
content: "";
position: absolute;
top: 50%;
left: 50%;
background: white;
transition: all 0.4s ease;
border-radius: 1px;
transform: translateX(-50%) translateY(-50%);
}
 
#action-button:before {
width: 20px;
height: 2px;
}
 
#action-button:after {
width: 2px;
height: 20px;
}

The inner list itself will expand radially from the action button via absolute positioning, meaning that the first item will be closest to the hub, the second next in line, and so on. As we normally would have it, the list items will appear in a downward sequence. So in order to reverse the direction upwards but maintain the orientation of the list items, we need to flip the list itself 180 degrees and then flip the list items a further 180 degrees back around to their original orientation:

#action-button ul {
position: absolute;
bottom: 60px;
list-style-type: none;
margin: 0;
padding: 40px 0;
transform: rotate(180deg) translateY(-30px); 
}
 
#action-button ul li {
display: block;
margin-bottom: 10px;
transform: rotate(-180deg); /* Reverse back */
}

The individual list items can be styled similarly to the action button itself. Note that their default state is a transform scale of zero:

#action-button ul li a {
display: inline-block;
width: 24px;
height: 24px;
background: #fff4f2;
border-radius: 50%;
box-shadow: 0px 2px 9px rgba(0,0,0,0.35);
overflow: hidden;
color: #f44336;
font-family: Geneva, sans-serif;
font-size: 18px;
text-align: center;
text-decoration: none;
padding: 18px;
transform: scale(0);
transition: all 0.2s ease;
}
#action-button ul li a:hover {
box-shadow: 0px 2px 10px rgba(0,0,0,0.75);
background: #f44336;
color: #fff4f2;
}
#action-button ul li a:active {
background: #e51102;
}

Now, the magic is all in the hover. The idea is that when we hover over the action button the list items will appear linearly in sequence, just like Google’s version. When we hover away from the button (or from the open list), the items will in reverse sequence disappear back to their hidden state.

This is achieved through the use of sequential transition delays. In this case, the transition delays are applied to the transform (scale) property only so that other properties won’t be affected on hover. The key is to sequence the delays in the order of appearance when the action button is hovered, and then to reverse this sequence on the non-hovered (default) state of the list items. In the example below, the delay sequence is in increments of 0.08s – this might seem a bit quick but it’s always a good practice to keep hover effects relatively snappy, especially if there’s a sequence of events.

/* Set disappear sequence (reverse) */
#action-button ul li:nth-of-type(1) a {
transition: transform 0.2s ease 0.16s, box-shadow 0.2s ease;
}
#action-button ul li:nth-of-type(2) a {
transition: transform 0.2s ease 0.08s, box-shadow 0.2s ease;
}
#action-button ul li:nth-of-type(3) a {
transition: transform 0.2s ease 0s, box-shadow 0.2s ease;
}
 
 
/* Hover to show sequence with delays */
#action-button:hover ul li:nth-of-type(1) a {
transform: scale(1);
transition: transform 0.2s ease 0s, background 0.2s ease, box-shadow 0.2s ease;
}
#action-button:hover ul li:nth-of-type(2) a {
transform: scale(1);
transition: transform 0.2s ease 0.08s, background 0.2s ease, box-shadow 0.2s ease;
}
#action-button:hover ul li:nth-of-type(3) a {
transform: scale(1);
transition: transform 0.2s ease 0.16s, background 0.2s ease, box-shadow 0.2s ease;
}

It’s as simple as that – always great to keep browser tasks to a minimum by using only CSS where JavaScript is not necessarily needed.

View Demo

Share on

Share on Facebook Share on Twitter Share on Google Plus Share on Pinterest

View more

CSS

Google

JavaScript

Lists

Mouse control

Multi-layered

Parallax

Scroll event

Visual feedback