DEV Community

Cover image for CSS Animated Button with Offset Border
Abbey Perini
Abbey Perini

Posted on • Updated on

CSS Animated Button with Offset Border

on a teal and blue background, a yellow button that says 'add' moves into a yellow border when clicked

I’m a believer in finding joy in the little things, and during my last project, that little thing was this button. I have been reading a lot about web design, and wanted my primary buttons to stand out in a big way. I had seen an image of a square button with an offset border while researching a design for an even earlier project, but never got the time to implement it. So for weeks, I’ve been trying to find the time to build this baby, and it was worth the wait.

To div or not to div

I researched a few ways to make the offset border without wrapping it in a container, but ultimately, I wanted an animation that looked like the button was moving into the offset border. If you are looking for an offset border and are ok with it moving with the button itself, you can use position: absolute; and z-index: -1; on the button with the ::before pseudo-selector to create an offset border. (Keep in mind transitions and animations using ::before are not supported in IE or Safari.) Similarly, you can also use an offset box shadow to create a double box effect that will move with the button.

The div solution

First create a div container — using position: relative; and left:, we’ll position the whole button where we want it on the page. Changing the left: property will change its position horizontally, and you can use top: or bottom: to move it vertically. Adjusting the margin will also help.

.primary-button-container {
  position: relative;
  display: block;
  left: 5px;
  width: 90px;
  margin-top: 30px;
  padding: 30px;
  border: 2px solid #EBCBAD;
  box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.25);
Enter fullscreen mode Exit fullscreen mode

Next, the actual button:

.primary-button {
  display: block;
  height: 58px;
  width: 82px;
  background-color: #EBCBAD;
  border: solid #EBCBAD;
  border-width: 0 10px;
  color: #123440;
  font-size: 18px;
  margin: -37px 0px -25px -37px;
  padding: 15px;
  padding-left: 10px;
Enter fullscreen mode Exit fullscreen mode

And, finally, the animation:

.primary-button:active {
  transform: translateY(9px) translateX(9px);
Enter fullscreen mode Exit fullscreen mode

If you’d like to prevent the blue focus outline, you can use this:

button:focus {    
   outline: none;    
Enter fullscreen mode Exit fullscreen mode

However, you should add something else in its place. Check out Transforming Tired Tabbing for lots of options.


Tag me on Twitter (or Github or somewhere…) if you end up using this button! I would be thrilled to see it out in the world spreading more joy.

Top comments (2)

link2twenty profile image
Andrew Bone

Great article, welcome to Dev 😊

This looked like a fun challenge so I thought I'd make a quick mock up

Each one is wrapped in a decorative-space div but that's just to make the cool effect from your first gif 😁

I didn't like the way the outline worked with the way I did it so I added my own outline using an iset box-shadow.

.primary-button:focus {
  outline: none;
  color: #396d83;

.primary-button:focus .primary-button__text  {
  box-shadow: inset 0 0 0 1px #354a76, 0 0 0 1px #fff;
  border-radius: 4px;
Enter fullscreen mode Exit fullscreen mode

Happy Blogging 🎉

abbeyperini profile image
Abbey Perini

Wow! So quick! I love it!!!