Lee Jordan

CSS only 3d buttons

Cover

These buttons use absolutely positioned translucent elements over a flat colour button to simulate a shiny 3d effect using the :before and :after pseudo elements. They also use an active state that simulates the button being pressed into the page. The core principle is the same in all these buttons but the implementation is subtly different. These buttons could be further enhanced by using other attributes such as background gradients, different borders, different shadow effects, multiple states and maybe even some keyframe animations.

#bubble

#bubble-left

#bubble-inverse

#keyboard

#keyboard-rounded

#full keyboard

#How to create this effect

#The button

First we are styling the buttons themselves. There's a lot you can do with this to personalise it so I've only included the bits that are relevant for the 3d effect. Relative position is required because we're positioning the pseudo elements absolutely. The -2px top raises the button up slightly so we can "push" it in to the page when it's active. We're specifying both an inset and a regular box-shadow so that the css transition animates correctly. If we only applied an inset box-shadow in the active state, it would not transition smoothly.

button.three-d {
    transition: all 0.1s ease-in;
    position: relative;
    top: -2px;
    box-shadow: inset 0 0 0 0 #000000, 0 2px 2px #000000;
}

#The active state

In the active state the button is "pushed" down 2px and we invert the two box-shadows to give the impression of depth.

button.three-d:active {
    top: 0;
    box-shadow: inset 0 2px 2px 0 #000000, 0 0 0 #000000;
}

#The overlay

Then we need to create our translucent overlays using absolutely positioned :before and :after pseudo elements. This is what gives them the 3d effect.

button.bubble:before {
    content: "";
    position: absolute;
    display: block;
    width: 100%;
    height: 30%;
    top: 0;
    left: 0;
    right: 0;
    background-color: #FFFFFF;
    border-radius: 2px 2px 50% 50%;
    opacity: .30;
}

#Cross browser concerns

IE8 and below manage to support :before and :after but they will not allow the use of opacity on these pseudo elements so you get solid white blocks which obscure the button content. If I wanted a fully cross browser solution, I would need to add markup (probably by using absolutely positioned spans). Therefore in all the examples I have effectively turned the overlays off by making them transparent in ie < 8

<!--[if lt IE 9]>
    <style type="text/css">
        a:before, a:after {
            background:transparent !important;
        }
    </style>
<![endif]-->

#More info

You can check out the code on github or view all the examples on one page.