Three more satisfying buttons and how to make them
Tags: webdev, css, tutorial, design
Published: 2021-07-30 14:24:07


Satisfying buttons can take many forms. Let's see three more!

#Glowing button
This button is made of glass and has a colourful light inside. The light follows a user's interactions — like mouse movement.

##Let's see it in action
{% codepen https://codepen.io/ammadeo/pen/mdmxOwP default-tab=result %}

##How to implement it
**I'd say upfront the implementation is not beginner-friendly.**
Firstly We'll use inner shadows to make a glass-like effect.
If You want to learn more about Glassmorphism, check out [New Glassmorphism? How to Create Neon Glass Effect UI Design](https://blog.prototypr.io/new-glassmorphism-how-to-create-neon-glass-effect-ui-design-3a6c866d3b63) by 
Przemysław Baraniak.
```css
button {
  /* Background color in HSL 
     It's "raw" because it needs to work with custom alpha */
  --color-background-raw: 4, 12%, 16%;

  /* Glass effect inner shadows */
  box-shadow:
    inset 0 2px 1px 0 hsla(0, 0%, 100%, 0.4),
    inset 0 2em 2em 0 hsla(0, 0%, 100%, 0.12),
    inset 0 -3px 0.25em 0 hsla(0, 0%, 100%, 0.12),
    inset 0 -0.25em 1em 0 hsla(0, 0%, 100%, 0.12),
    inset 0 -2em 2em 0 hsla(var(--color-background-raw), 0.05),
    inset 0 0.25em 0.5em 0 hsla(0, 0%, 100%, 0.2);
}
```
Next, we'll use the **after pseudo-element** as a glowing circle following a user's interactions. Let's make use of the [CSS Properties and Values API](https://developer.mozilla.org/en-US/docs/Web/API/CSS_Properties_and_Values_API/guide). This API allows us to define types of CSS Properties, which is needed to animate them.
```css
/* Use CSS Properties and Values API
It enables transitions for css properties 
*/
/* Will control the left position of the glowing circle. */
@property --glow-left {
  /* Allow any length or percentage e.g. 1px, 1em or 20% */
  syntax: '<length-percentage>';
  /* Allow children elements to inherit this property */
  inherits: true;
  /* Set default value */
  initial-value: 50%;
}
/* Will control the top position of the glowing circle. */
@property --glow-top {
  syntax: '<length-percentage>';
  inherits: true;
  initial-value: 50%;
}

/* Glowing circle */
button.glow::after {
  /* Make sure it shows */
  content: "";

  /* Position it */
  position: absolute;
  top: var(--glow-top);
  left: var(--glow-left);
  /* Keep it centred */
  transform: translate(-50%, -50%);

  /* Make it smooth!
     This is why we need CSS Properties and Values API
   */
  transition: 
    top 80ms linear,
    left 80ms linear;
}
```
Let's use a bit of JavaScript to control them.
```ts
// Select the button
const Button = document.querySelector("button.glow");

// Set glow position css properties
const setGlowPosition = (event) => {
  // Get the event's coordinates relative to the button
  const { left, top } = event.target.getBoundingClientRect();
  const offsetX = event.clientX - left;
  const offsetY = event.clientY - top;

  // Prevent setting position on keyboard click
  if (offsetX > 0 && offsetY > 0) {
    // wait for animation frame for better performance
    requestAnimationFrame(() => {
      // set css property
      event.target.style.setProperty("--glow-left", `${offsetX}px`);
      event.target.style.setProperty("--glow-top", `${offsetY}px`);
    });
  }
};

// Set glow position on mousemove (mouse) and click (touch and keyboard)
Button.addEventListener("mousemove", setGlowPosition);
Button.addEventListener("click", setGlowPosition);
```

#Plastic button
The button will deform inwards on press.

##Let's see the implementation
{% codepen https://codepen.io/ammadeo/pen/jOBRgvQ default-tab=result %}

##How to make it?
To make a neuromorphic button, we need to give it a few shadows. By default, we want to make it look raised.
```css
button {
  /* Add outside shadows */
  box-shadow: 
    /* Top left white shadow */
    -4px -4px 16px 0 hsla(0, 0%, 100%, 0.14),
    /* Bottom right black shadow */
    4px 4px 16px 0 hsla(0, 0%, 0%, 0.14);
}

/* On button press */
button:active {
  /* Add inside shadows */
  box-shadow: 
    /* Inner top left black shadow */
    inset -4px -4px 16px 0 hsla(0, 0%, 0%, 0.14),
    /* Inner bottom right white shadow */
    inset 4px 4px 16px 0 hsla(0, 0%, 100%, 0.14);
  
  /* Make it a bit darker */
  filter: brightness(0.96);
}
```
Don't forget about UX! Let's add a light border around it to make it easier to spot.
```css
button {
  /* Add glass-like border  */
  border: hsla(0, 0%, 100%, 0.2) 1px solid;
}
```
Learn more about plastic like buttons from [Neumorphism in user interfaces](https://uxdesign.cc/neumorphism-in-user-interfaces-b47cef3bf3a6) by Michal Malewicz.

#Simple button
Not every satisfying button must be hard to implement. This simple button will use only small transitions and shadows to make it feel great.

##How does it look?
{% codepen https://codepen.io/ammadeo/pen/BaWEEoZ default-tab=result %}

##Let's make it
The implementation will be very similar to the one in the first part of this series. So if You didn't read it, do it now.
```css
button {
  /* Use realistic shadows */
  box-shadow: 1px -1px 2px 0 hsla(0, 0%, 0%, 0.06),
              3px -3px 4px 0 hsla(0, 0%, 0%, 0.08);

  /* Make sure that transform-origin match translate() direction. 
     It makes translate() and scale() work it the same axis */  
  transform-origin: bottom center;
}

/* On button press */
button:active {
  /* Make shadows much smaller */
  box-shadow: 0 0 1px 0 hsla(0, 0%, 0%, 0.06),
              1px -1px 1px 0 hsla(0, 0%, 0%, 0.08);
  
  /* Apply perspective transformation */
  transform: 
    /* Translate down on Y axis */
    translatey(0.25em) 
    /* Make button smaller */
    scale(0.98);
}
```

#Challenge for You
Make Your satisfying button and share it in a comment below. I'd love to see it!