So, you want to create a catchy button using only HTML and CSS. As you will see in this article this is very achievable using these tools. In earlier days developers used to achieve such style using other components like Flash which was proprietary and involved enabling a plugin at the client, besides that it was much slower while displaying.

The main idea behind these new CSS styles is the latest updates to CSS and HTML 5.

When designing your new cool CSS button you can begin examining two dimensions: button category and button states.

In UX lingo, buttons are categorized into these categories:

Raised Buttons

Typically rectangular buttons with a slight shadow. Raised buttons add dimension to mostly flat layouts. Use them to give more prominence to actions in layouts with a lot of varying content. Raised buttons lift and fill with color on pressing them.

Raised Buttons CSS

Flat Buttons

Flat buttons do not lift but fill with color on press. They are used to minimize distraction from content. They are used mainly in dialogs to blend more naturally with the rest of the dialog.

Flat Buttons CSS

Toggle Buttons

Mainly used to represent ON/OFF options for a setting.

Toggle Buttons CSSToggle Button CSS

Ghost Buttons

These are transparent and empty buttons that have a basic shape form such as rectangular. They are bordered by a very thin line and have the internal section being plain text. They are used to lead to secondary content.

Ghost Buttons CSS 

Floating Action Buttons

Part of the Google Material Design guidelines, these buttons lift and display an ink reaction on the press. They are placed as circle icon that floats above the page content and has behaviors that include morphing, launching, and a transferring anchor point.

Action Buttons CSS

Next, you will need to consider what button states you want to support your button.

Creative CSS button states:

  • Normal State: the basic state for the button when it is available to be pressed. The main rule is to make sure the button gives a hint that it is clickable in this state, such as the shadow for raised buttons.
  • Focused State: this happens when hovering over the button. It offers a good visual feedback to the user and a confirmation that the button is ready to accept user action. The examples in this article will focus on this state and the Pressed state.
  • Pressed State: This is the core state of the button that confirms to the user that it was pressed. It can consist of an animation that extends the hover animation or a completely different animation.
  • Inactive State: this is when the button action is not applicable to the current state of the application. It can be implemented by either making it disabled or hide it altogether.

In this article, we will examine how we can implement these types/behaviors using CSS.

CSS animations facilitate the implementation of the “Focused” and “Pressed” states of buttons as described above. Highlighting the state of a button implements the Feedback principle which is highly recommended as one of the 5 Interaction Design principles. Those principles are namely that a good interaction design is Consistent, Visible, Learnable, Predictable, and Provides Feedback.

Feedback is important because it answers the following questions which the human brain asks instinctively:

  • Location: Where am I?
  • Current Status: What’s happening — and is it still happening?
  • Future Status: What will happen next?
  • Outcomes & Results: What just happened?

The CSS features used to build these animations are CSS transitions, CSS button animations, and in some cases, we can use Javascript to add or remove effect classes.

Dimensions of CSS transitions:

  • Which properties to animate: list them explicitly
  • When will the animation start: specify a delay
  • How long the transition will last: set the duration
  • How the transition will run: defined by a timing function (ex. linearly/quick at the beginning and slow at the end/ etc…)

Another CSS feature used to handle the user action of hovering over the button is the “hover” feature. We will group all these concepts in the two cool CSS buttons samples below.

Sample 1: Direction buttons that actually show the direction

This sample demonstrates the use of hover and transitions to reach the desired effect (click on the text block to expand it). For example, the arrow sign replaces the “FORWARD” text coming from the left.

Direction Button CSS Direction Buttons CSS


<head>

<style>

@import url(https://fonts.googleapis.com/css?family=Lato:300,400,700);

&nbsp;

::-moz-focus-inner {

border:0;

}

&nbsp;

* {

margin: 0;

padding: 0;

border: 0;

}

&nbsp;

body {

font-family: 'Lato', Calibri, Arial, sans-serif;

font-weight: bold;

color: #fff;

background: #9e54bd;

}

#wrapper {

width: 800px;

margin: 20px auto;

}

&nbsp;

button {

font: inherit;

color: inherit;

width: 300px;

text-transform: uppercase;

padding: 25px 80px;

margin: 15px 30px;

background: #823aa0;

overflow: hidden;

position: relative;

}

button:before {

left: 48%;

}

button:active {

background: #9053a9;

color: #823aa0;

top: 2px;

}

button > span {

display: inline-block;

transition: all 0.5s;

}

.icon-forward:before {

content: "\2192";

position: absolute;

}

.icon-backward:before {

content: "\2190";

position: absolute;

}

.icon-up:before {

content: "\2191";

position: absolute;

}

.icon-down:before {

content: "\2193";

position: absolute;

}

.btn-1:before {

left: -100%;

transition: all 0.5s;

}

.btn-1:hover:before {

left: 48%;

}

.btn-1:hover > span {

transform: translateX(300%);

}

.btn-2:before {

top: -100%;

transition: all 0.5s;

}

.btn-2:hover:before {

top: 30%;

}

.btn-2:hover > span {

transform: translateY(300%);

}

</style>

</head>

&nbsp;

<div id="wrapper">

<button class="btn-1 icon-forward"><span>Forward</span></button>

<button class="btn-1 icon-backward"><span>Backward</span></button>

<button class="btn-2 icon-up"><span>Upward</span></button>

<button class="btn-2 icon-down"><span>Downward</span></button>

</div>

In this sample we make use of the following CSS classes:

  • before:

This is a pseudo-element that we use to reach various goals depending on the elements inside it.

First of all, we use “before” to prepare the characters that appear on the hover action. You can replace these characters with an image of your choice. For this demo purposes, we just use the arrow characters encoded appropriately in CSS in the “content” property.


.icon-forward:before {

content: "\2192";

position: absolute;

}

.icon-backward:before {

content: "\2190";

position: absolute;

}

For example, to hide the left and right arrows before making the animation in Forward and Backward buttons we do the following:


.btn-1:before {

left: -100%;

transition: all 0.5s;

}

You will notice that both Forward and Backward buttons are replaced by an arrow character that comes from the left. This is because they both use the same “.btn-1” class which has the “left” property set to -100%. The negative sign combined with the transition property implies that the animation happens from left to right. This is built on a coordinate system that considers the corner of the element as the 0 point, so any negative value will imply the left of the element.

You can experiment with the 100% value or you can change the negative sign to no sign (i.e. positive) to see this in effect. For example, changing it to 150% makes the icon appear from the right.

As described earlier, the “transition” element here defines which property to animate: “all”, and how long the transition will last “0.5s”.

Sample 2: sideways expansion hover

This sample animates the Focused state by simulating that the button expands to the left and right, offering a pleasant experience to the user.

Expand Buttons CSS Expand Button CSS


<head>

<script src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.min.js" type="text/javascript"></script>

&nbsp;

<style>

@import url(https://fonts.googleapis.com/css?family=Roboto:400,100,900);

* {

box-sizing: inherit;

transition-property: all;

transition-duration: .6s;

transition-timing-function: ease;

}

&nbsp;

html,

body {

box-sizing: border-box;

height: 100%;

width: 100%;

}

&nbsp;

body {

background: #E1332D;

font-family: 'Roboto', sans-serif;

font-weight: 400;

}

&nbsp;

.buttons {

display: flex;

flex-direction: column;

height: 100%;

justify-content: center;

text-align: center;

width: 100%;

}

&nbsp;

.container {

align-items: center;

display: flex;

flex-direction: column;

justify-content: center;

padding: 1em;

text-align: center;

}

@media (min-width: 600px) {

.container {

flex-direction: row;

justify-content: space-between;

}

}

&nbsp;

h1 {

color: #fff;

font-size: 1.25em;

font-weight: 900;

margin: 0 0 2em;

}

@media (min-width: 450px) {

h1 {

font-size: 1.75em;

}

}

@media (min-width: 760px) {

h1 {

font-size: 3.25em;

}

}

@media (min-width: 900px) {

h1 {

font-size: 5.25em;

margin: 0 0 1em;

}

}

&nbsp;

p {

color: #fff;

font-size: 12px;

}

@media (min-width: 600px) {

p {

left: 50%;

position: absolute;

-webkit-transform: translate(-50%, 0);

transform: translate(-50%, 0);

top: 90%;

}

}

@media (max-height: 500px) {

p {

left: 0;

position: relative;

top: 0;

-webkit-transform: translate(0, 0);

transform: translate(0, 0);

}

}

p a {

background: rgba(255, 255, 255, 0);

border-bottom: 1px solid;

color: #fff;

line-height: 1.4;

padding: .25em;

text-decoration: none;

}

p a:hover {

background: white;

color: #E1332D;

}

&nbsp;

.btn {

color: #fff;

cursor: pointer;

font-size: 16px;

font-weight: 400;

line-height: 45px;

margin: 0 0 2em;

max-width: 160px;

position: relative;

text-decoration: none;

text-transform: uppercase;

width: 100%;

}

@media (min-width: 600px) {

.btn {

margin: 0 1em 2em;

}

}

.btn:hover {

text-decoration: none;

}

&nbsp;

.btn-2 {

letter-spacing: 0;

}

&nbsp;

.btn-2:hover,

.btn-2:active {

letter-spacing: 5px;

}

&nbsp;

.btn-2:after,

.btn-2:before {

-webkit-backface-visibility: hidden;

backface-visibility: hidden;

border: 1px solid rgba(255, 255, 255, 0);

bottom: 0px;

content: " ";

display: block;

margin: 0 auto;

position: relative;

transition: all 280ms ease-in-out;

width: 0;

}

&nbsp;

.btn-2:hover:after,

.btn-2:hover:before {

-webkit-backface-visibility: hidden;

backface-visibility: hidden;

border-color: #fff;

transition: width 350ms ease-in-out;

width: 70%;

}

&nbsp;

.btn-2:hover:before {

bottom: auto;

top: 0;

width: 70%;

}

</style>

</head>

&nbsp;

<body>

<section class="buttons">

<h1>Button Hover Effects</h1>

<div class="container">

&nbsp;

<a href="#" class="btn btn-1">

<svg>

<rect x="0" y="0" fill="none" width="100%" height="100%" />

</svg>

Hover

</a>

&nbsp;

<a href="#" class="btn btn-2">Hover</a>

<!--End of Button 2 -->

&nbsp;

<a href="#" class="btn btn-3">Hover</a>

<!--End of Button 3 -->

&nbsp;

<a href="#" class="btn btn-4">

<span>Hover</span>

</a>

<!--End of Button 4 -->

&nbsp;

<a href="#" class="btn btn-5">Hover</a>

<!--End of Button 5 -->

&nbsp;

</div>

</section>

<script src='http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>

&nbsp;

</body>

This section helps make the text transition smooth, if you omit it you will notice that the text jumps from the non-expanded state to the expanded state in a brisk fashion.


@import url(https://fonts.googleapis.com/css?family=Roboto:400,100,900);

* {

box-sizing: inherit;

transition-property: all;

transition-duration: .6s;

transition-timing-function: ease;

}

Then to control the original drawing of the bounding box we use this section.


.btn-2:after,

.btn-2:before {

-webkit-backface-visibility: hidden;

backface-visibility: hidden;

border: 1px solid rgba(255, 255, 255, 0);

bottom: 0px;

content: " ";

display: block;

margin: 0 auto;

position: relative;

transition: all 280ms ease-in-out;

width: 0;

}

Adding to that we use the following section for the upper border.


/* upper line */

.btn-2:hover:after,

.btn-2:hover:before {

-webkit-backface-visibility: hidden;

backface-visibility: hidden;

border-color: #fff;

transition: width 350ms ease-in-out;

width: 70%;

}

And to control the lower border we use this transition.


/* lower line */

.btn-2:hover:before {

bottom: auto;

top: 0;

width: 70%;

}

As we have seen in the two samples, CSS transition element proves to be a very powerful tool to implement CSS button animation. This article was an introduction to the various concepts you need to consider when designing a new button animation and we also provided a hint of how to reach the desired animation using CSS.