CSS Buttons with Pseudo-elements

In this tutorial, I’ll show you how to create buttons with a twist, using just one anchor tag per button and the great power of CSS.

cssbuttons_main

Hola, amigos. For the last month or so, I’ve been experimenting with the power of CSS pseudo-elements, specially when it comes to mixing them with buttons and that way recreating some great effects that were only possible to do with sprites, in the past.

In this tutorial, I’ll show you how to create buttons with a twist, using just one anchor tag per button and the great power of CSS.

The font used is ‘Open Sans’ by Steve Matteson.

Disclaimer:
I’ll not be using CSS vendor prefixes in this tutorial or else it would be crazy long, but you will find them in the downloadable files.

I avoided CSS transitions since, right now, Firefox is the only browser that supports them on pseudo-elements. Plus, I believe that these buttons work just fine without them.

Tiny break: 📬 Want to stay up to date with frontend and trends in web design? Subscribe and get our Collective newsletter twice a tweek.

Markup

The structure of all these buttons needs just one anchor tag for it to work, since we will be creating the other elements with the ::before pseudo-class.


     Click me!

Example 1

cssbuttons_01

I think this is the easiest one, with a very regular CSS.

CSS

First of all, we will give the general style of the button, including its active state. It is important to notice the relative positioning, since it will help us later with the positioning of the ::before element:

.a_demo_one {
	background-color:#ba2323;
	padding:10px;
	position:relative;
	font-family: 'Open Sans', sans-serif;
	font-size:12px;
	text-decoration:none;
	color:#fff;
	border: solid 1px #831212;
	background-image: linear-gradient(bottom, rgb(171,27,27) 0%, rgb(212,51,51) 100%);
	border-radius: 5px;
}

.a_demo_one:active {
	padding-bottom:9px;
	padding-left:10px;
	padding-right:10px;
	padding-top:11px;
	top:1px;
	background-image: linear-gradient(bottom, rgb(171,27,27) 100%, rgb(212,51,51) 0%);
}

Then, we create the gray container using the ::before pseudo-element. Absolute positioning makes our life easier to, believe it or not, position our element:

.a_demo_one::before {
	background-color:#ccd0d5;
	content:"";
	display:block;
	position:absolute;
	width:100%;
	height:100%;
	padding:8px;
	left:-8px;
	top:-8px;
	z-index:-1;
	border-radius: 5px;
	box-shadow: inset 0px 1px 1px #909193, 0px 1px 0px #fff;
}

Example 2

cssbuttons_02

This one is a little bit more complex because of the 3D’ish look. This button is outside of its ‘container’, but when you click it, it goes down:

CSS

.a_demo_two {
	background-color:#6fba26;
	padding:10px;
	position:relative;
	font-family: 'Open Sans', sans-serif;
	font-size:12px;
	text-decoration:none;
	color:#fff;
	background-image: linear-gradient(bottom, rgb(100,170,30) 0%, rgb(129,212,51) 100%);
	box-shadow: inset 0px 1px 0px #b2f17f, 0px 6px 0px #3d6f0d;
	border-radius: 5px;
}

.a_demo_two:active {
	top:7px;
	background-image: linear-gradient(bottom, rgb(100,170,30) 100%, rgb(129,212,51) 0%);
	box-shadow: inset 0px 1px 0px #b2f17f, inset 0px -1px 0px #3d6f0d;
	color: #156785;
	text-shadow: 0px 1px 1px rgba(255,255,255,0.3);
	background: rgb(44,160,202);
}

And here’s the tricky part:

Since the position of the pseudo-element depends on its parent, once the parent moves down a few pixels, you have to move up the pseudo-element that same amount of pixels.

.a_demo_two::before {
	background-color:#072239;
	content:"";
	display:block;
	position:absolute;
	width:100%;
	height:100%;
	padding-left:2px;
	padding-right:2px;
	padding-bottom:4px;
	left:-2px;
	top:5px;
	z-index:-1;
	border-radius: 6px;
	box-shadow: 0px 1px 0px #fff;
}

.a_demo_two:active::before {
	top:-2px;
}

Example 3

cssbuttons_03

I think this one is my favorite since it was the first one I ever made this way and people seem to really like it. It is a divided button that “breaks” once you click it.

CSS

Again, the first thing we have to do is create the lighter part. In here, you’ll notice a right margin, this is in order to compensate for the width of the pseudo-element if you want to center the button. You don’t need it if that is not a problem for you.

.a_demo_three {
	background-color:#3bb3e0;
	font-family: 'Open Sans', sans-serif;
	font-size:12px;
	text-decoration:none;
	color:#fff;
	position:relative;
	padding:10px 20px;
	border-left:solid 1px #2ab7ec;
	margin-left:35px;
	background-image: linear-gradient(bottom, rgb(44,160,202) 0%, rgb(62,184,229) 100%);
	border-top-right-radius: 5px;
	border-bottom-right-radius: 5px;
	box-shadow: inset 0px 1px 0px #2ab7ec, 0px 5px 0px 0px #156785, 0px 10px 5px #999;
}

.a_demo_three:active {
	top:3px;
	background-image: linear-gradient(bottom, rgb(62,184,229) 0%, rgb(44,160,202) 100%);
	box-shadow: inset 0px 1px 0px #2ab7ec, 0px 2px 0px 0px #156785, 0px 5px 3px #999;
}

And then the pseudo-element’s CSS:

.a_demo_three::before {
	content:"ยท";
	width:35px;
	max-height:29px;
	height:100%;
	position:absolute;
	display:block;
	padding-top:8px;
	top:0px;
	left:-36px;
	font-size:16px;
	font-weight:bold;
	color:#8fd1ea;
	text-shadow:1px 1px 0px #07526e;
	border-right:solid 1px #07526e;
	background-image: linear-gradient(bottom, rgb(10,94,125) 0%, rgb(14,139,184) 100%);
	border-top-left-radius: 5px;
	border-bottom-left-radius: 5px;
	box-shadow:inset 0px 1px 0px #2ab7ec, 0px 5px 0px 0px #032b3a, 0px 10px 5px #999 ;
}

.a_demo_three:active::before {
	top:-3px;
	box-shadow:inset 0px 1px 0px #2ab7ec, 0px 5px 0px 0px #032b3a, 1px 1px 0px 0px #044a64, 2px 2px 0px 0px #044a64, 2px 5px 0px 0px #044a64, 6px 4px 2px #0b698b, 0px 10px 5px #999 ;
}

Example 4

cssbutton_04

This time, we will use the pseudo-element as a pointer, using one image as a background, though you can use some of those great icon fonts.

CSS

.a_demo_four {
	background-color:#4b3f39;
	font-family: 'Open Sans', sans-serif;
	font-size:12px;
	text-decoration:none;
	color:#fff;
	position:relative;
	padding:10px 20px;
	padding-right:50px;
	background-image: linear-gradient(bottom, rgb(62,51,46) 0%, rgb(101,86,78) 100%);
	border-radius: 5px;
	box-shadow: inset 0px 1px 0px #9e8d84, 0px 5px 0px 0px #322620, 0px 10px 5px #999;
}

.a_demo_four:active {
	top:3px;
	background-image: linear-gradient(bottom, rgb(62,51,46) 100%, rgb(101,86,78) 0%);
	box-shadow: inset 0px 1px 0px #9e8d84, 0px 2px 0px 0px #322620, 0px 5px 3px #999;
}

.a_demo_four::before {
	background-color:#322620;
	background-image:url(../images/right_arrow.png);
	background-repeat:no-repeat;
	background-position:center center;
	content:"";
	width:20px;
	height:20px;
	position:absolute;
	right:15px;
	top:50%;
	margin-top:-9px;
	border-radius: 50%;
	box-shadow: inset 0px 1px 0px #19120f, 0px 1px 0px #827066;
}

.a_demo_four:active::before {
	top:50%;
	margin-top:-12px;
	box-shadow: inset 0px 1px 0px #827066, 0px 3px 0px #19120f, 0px 6px 3px #382e29;
}

Example 5

cssbuttons_05

This example is a bit cheesy, I know, but you can use it in so many and really useful ways.

CSS

.a_demo_five {
	background-color:#9827d3;
	width:150px;
	display:inline-block;
	font-family: 'Open Sans', sans-serif;
	font-size:12px;
	text-decoration:none;
	color:#fff;
	position:relative;
	margin-top:40px;
	padding-bottom:10px;
	padding-top:10px;
	background-image: linear-gradient(bottom, rgb(168,48,232) 100%, rgb(141,32,196) 0%);
	border-bottom-right-radius: 5px;
	border-bottom-left-radius: 5px;
	box-shadow: inset 0px 1px 0px #ca73f8, 0px 5px 0px 0px #6a1099, 0px 10px 5px #999;
}

.a_demo_five:active {
	top:3px;
	background-image: linear-gradient(bottom, rgb(168,48,232) 0%, rgb(141,32,196) 100%);
	box-shadow: inset 0px 4px 1px #7215a3, 0px 2px 0px 0px #6a1099, 0px 5px 3px #999;
}

.a_demo_five::before {
	background-color:#fff;
	background-image:url(../images/heart.gif);
	background-repeat:no-repeat;
	background-position:center center;
	border-left:solid 1px #CCC;
	border-top:solid 1px #CCC;
	border-right:solid 1px #CCC;
	content:"";
	width:148px;
	height:40px;
	position:absolute;
	top:-30px;
	left:0px;
	margin-top:-11px;
	z-index:-1;
	border-top-left-radius: 5px;
	border-top-right-radius: 5px;
}

.a_demo_five:active::before {
	top: -33px;	
	box-shadow: 0px 3px 0px #ccc;
}

In the end

And well, this is it, for now. Remember that these buttons are still kind of experimental, so not every browser supports them that well.

Thank you for reading this tutorial and I hope that you find it useful.

Sergio Camalich

Sergio Camalich is a mexican graphic designer, specialized in web design and front-end development, working at Element Studios and freelancing. He loves camping and is addicted to root beer.

Stay in the loop: Get your dose of frontend twice a week

Fresh news, inspo, code demos, and UI animationsโ€”zero fluff, all quality. Make your Mondays and Thursdays creative!

Feedback 80

Comments are closed.
  1. Excellent tutorial. I think I’m going to have to start using some of these ideas. Thank you.

  2. Thanks! One of the best CSS3 button tutorials ever. (Coulda used 2 days ago, too! ๐Ÿ˜‰

  3. Wow! Love the buttons. Great work! Has anyone experimented yet with which browsers they work well in, and which they don’t?

  4. Thank you all for your comments!

    @Alan A.: I’ve tested them in all major browsers and the only one giving troubles is IE. Once again.

  5. It’s a good job Sergio, but I have tested in IE 7 it is not working even also in IE 9.
    Hope some Javascript required for it or a chek with ie-css3 may be done

  6. Excelent work. I see last time you post more CSS3 tutorials. That is a good thing to use the latest technices. Good luck ๐Ÿ™‚

  7. What I’m missing is a hover effect to actually get feedback whether the button is clickable.

    Is it possible to add this?

  8. I think Codrops team must redesign this website ๐Ÿ™‚ Your tutorial is too Great then The Website ๐Ÿ˜€ hahha
    ~Just Kidding ๐Ÿ™‚

  9. Nice job!! and good tuts!

    However, example #3 isn’t looking good in Firefox 9.01 Windows: the height of the left dark blue part isn’t the same as the right part.

    Good luck.

  10. Wowy, they look awesome! I know CSS becomes more powerful every day, but that’s really amazing already!
    Just bad that there are still way too many old IE versions out there.

  11. Amazing buttons and dito tutorial! Definitely number 3, plan to use that in an upcoming project. Thanks so much!

  12. As usually, a great job. It’s always the same impatience to discover your codes.
    Thank you very much.

  13. These are amazing buttons, but it makes me crazy when a browser doesn’t support them. When will write code without paying attention to browser compatibility. By the way, thanks a lot..

  14. Nice buttons, Demo4 isn’t working properly on Opera 11.60 (Mac).. the arrow positioning is not right. Is there any way to fix that issue?

  15. Ok that’s it… you get a special folder on my bookmarks bar for all the awesome stuff you do!!

  16. Huh, I’m in a bit of a pickle. I really love the fifth design because of the whole “you-better-love-us” concept. But I can not make it work as it is intended to. Before one clicks the button the heart should be grey and only after clicking the color should change to red. Easy you say? Well I’m stuck, could anyone point me in the right direction?

  17. @kristjanfou You have to do something like this:

    .a_demo_five::before {
    background-image:url(../images/gray_heart.gif);
    }

    .a_demo_five:active::before {
    background-image:url(../images/red_heart.gif);
    }

    If you watch the CSS closely, you’ll notice that the ::before element has a background image, so you just have to add a different background image to the active state of the button, as in the example above, and that’s it.

  18. Excellent work I was looking for a great simple menu that was elegant and yet simple at the same time.

    I put it into my cms site as a selectable include file. Gave it some dynamic colors to follow the site’s current theme and wow.

    In Firefox and Chrome this thing is s thing of beauty Your demo does not fully do justice to the gradient glowing effect. Although that is not there in IE it was an unexpected bonus. I think it looks awesome and will keep it. Thanks and keep up the good work.

  19. @Sergio Camalich

    I see what you mean, but doing so the “red heart” is applied only while clicking the button. I need it to stay red after clicking.

    I have tried your solution and it turns back grey right after releasing the click.

    • .a_demo_five:visited::before {
      background-image:url(../images/red_heart.gif);
      }

      will leave the heart red if you already clicked the link once.

      .a_demo_five:hover::before {
      background-image:url(../images/red_heart.gif);
      }

      will get the red heart only when you have the cursor over the button ๐Ÿ™‚

      I have one problem though, with demo 4, the background gradient doesn’t work, and even if I use an image instead, it doesn’t work at all….

  20. Interesting if you click and drag the elements stay depressed? is this by design?

  21. Excelent… For sure I will use some of this ideas for my next project…. Thanks for sharing…