DEV Community

Nic
Nic

Posted on

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

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>
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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');
});
Enter fullscreen mode Exit fullscreen mode

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');
});
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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';
Enter fullscreen mode Exit fullscreen mode

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');
});
Enter fullscreen mode Exit fullscreen mode

And then update the CSS:

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

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.

Discussion (3)

Collapse
fiddeou profile image
Esteban Fiddeou

How can I make the buttons stay pressed for a specific time, and then return?

Collapse
nicm42 profile image
Nic Author

setTimeout is your friend here. You can add it into the click listener after you set the button to look pressed:

  button.classList.add('active');
  setTimeout(() => { button.classList.remove('active'); }, 2000);
Enter fullscreen mode Exit fullscreen mode

The 2000 there is the number of milliseconds it should wait before it executes. 2000ms is 2 seconds.

You can see the whole thing in the Codepen at codepen.io/nicm42/pen/OJjdoqe

Collapse
fiddeou profile image
Esteban Fiddeou

Cool thanks!