How to make a button looked like it's staying pressed down

·

4 min read

Let's say you have a button on your page and when the user clicks it, it should look like it's staying pressed until they do something else. How do you do that? It's pretty easy, you just need a box shadow and a bit of JavaScript.

Button set up

Let's set up our button in HTML:

<button class="button">Button</button>

Nothing exciting here, it's just a button with a class of button. You don't need the class in this example, but let's assume it's on a page that includes other buttons that do other things, so we'd need a class to differentiate it.

And the CSS for the button:

.button {
  position: relative;
  padding: 0.5em 1em;
  border: 0;
  border-radius: 0.5em;
  background-color: pink;
  box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.5);
  cursor: pointer;
}

The position: relative is needed later. The padding, border and border radius are just there to make it look pretty. The background colour is too, but it also makes it stand out from the page. The box-shadow is only a very small one, but it's enough to make the button look like it's not flat on the page.

Making the button looked pressed

Now to make the button look pressed we remove the box-shadow and move it by the amount of space the box-shadow was taking up:

.button:active {
  top: 2px;
  left: 1px;
  box-shadow: none;
}

The position relative on the button was so that the top and left work here. Without it the CSS doesn't know what that top and left is in relation to and it doesn't do what you'd expect.

Now, when you click the button it goes down and right a bit, which makes it look like it's gone from sticking up from the page a bit, to being flat against the page. Which is roughly how a button works in the real world.

But of course, the active pseudo class only kicks in while you're clicking the button. Once you take your finger off the mouse, it's not active any more and it pops back up. To make it look like it's stayed pressed, we need JavaScript.

Making the button look staying pressed

For this we need an event listener. It's going to listen for the button click and when it hears it, it'll do something.

const button = document.querySelector('.button');

button.addEventListener('click', () => {
  console.log('Button clicked');
});

You can select the button lots of ways, but I like querySelector because when I'm in CodePen and have to therefore type the whole thing myself, I don't have to remember where the capital letters are. It also works for everything, I don't have to select button, .button and #button in different ways.

I used an arrow class in here because I've got into the habit of only using them. You can use a normal function:

const button = document.querySelector('.button');

button.addEventListener('click', function() {
  console.log('Button clicked');
});

You can also put that console log in another function, rather than using an anonymous function. Again, I'm used to using anonymous functions unless I have more than one listener wanting to do the same thing.

Here it is calling a function:

const button = document.querySelector('.button');

function clicked() {
  button.classList.toggle('active');
}

button.addEventListener('click',clicked);

So now the question is, how do we make it appear to stay pressed down? Well, we can add CSS into JavaScript eg:

button.style.boxShadow = 'none';

But in this case we want to add three styles and we already have them defined in our CSS for the active pseudo class. So let's re-use that:

const button = document.querySelector('.button');

button.addEventListener('click', () => {
  button.classList.add('active');
});

And then update the CSS:

.button:active,
.active {
  top: 2px;
  left: 1px;
  box-shadow: none;
}

And just like that, it works!

I have put this all in CodePen so you can try it out. There are a couple of additions in here versus the code above:

  1. I've added some CSS to the html and body to centre the button on the page, so it's easier to see
  2. Rather than adding the active class, I'm toggling it. classList.toggle means that if the class is applied, then remove it, but if it's not on there, add it. It means that you can test clicking the button multiple times without having to refresh the page.