The Button that every Front-End developer should use, the written once-and-forgotten code!!!
Tags: webdev, html, css, beginners
Published: 2023-12-02 12:26:19

# Why would I need a magic button?

I mean, who doesn't want a magic button? a Button that always works!

behaves as you expect it to behave and stays where you put it in the size you specified. I think you already have enough layout and responsiveness problems to add a bad button problem, I know it's just a button why overrengine it? 

Because you will write the code once and forget it, Don't believe me, you can go to review the code on:

- **[CodePen](https://codepen.io/ymhaah/pen/WNJpKJK)**
- **[GitHub](https://github.com/ymhaah/the-Indestructible-button)**

But if you want to understand how I made my magic button. Well, continue reading!

# **HTML** `<button></button>`, Well not that simple!

If when you press the button and something happens use [<button></button>](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button)

- add **[type=”button”](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#attr-type)** To tell the browser how this button behaves, or any other button [type](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button)
.
- if the button is icon only “no text” add [aria-label=”description”](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label)
- if the button is disabled add [disabled`](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/disabled) and [aria-disabled=”true”](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-disabled)

```
<button type="button" class="Button">normal</button>
<button type="button" aria-label=”star” class="Button">*</button>
<button type="button" disabled aria-disabled=”true” class="Button">disabled</button>
```

If when you press the button, you move to another page use the **[Anchor element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a)**  

- add **[role=”button”](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/button_role)** to specify to the browser what is the role of this link.

```html
<a href="#" role="button" class="Button">a link button</a>
```

But if you do not know which one to use, I recommend reading the following: **[Anchors vs Buttons](https://bitsofco.de/anchors-vs-buttons/)**

if you're thinking of using anything else as a button, here's a message from the smart people of [Mozilla](https://developer.mozilla.org/en-US/) telling you why this is a stupid idea.

> Note: If using role="button" instead of the semantic [button] or [input type="button"] elements, you will need to make the element focusable and define event handlers for click and keydown events. This includes handling the Enter and Space keypresses in order to process all forms of user input.
> 

# CSS that just works!


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/88yo36qth6jfm77mca6n.jpg)

I want to admit something; I'm obsessed with buttons!

I've always been interested in creating the perfect button, as the first thing I do when trying a new library is check how they made the button, I even built a library specifically for that, a library that aims to provide only the Important items with high quality, you will find there even a more overrengined button, and If you would like to get it or help me to overengineer the front-end world with some high quality react component, visit **[Moon-RockUI](https://github.com/ymhaah/Moon-RockUI)** 

Help me launch version 1.0.0 soon!

## **Some basics before we start:**

- I will use `rem` and `em` a lot and other css units, if you want to know more, I advise you to read this: **[CSS Units Explained](https://www.digitalocean.com/community/tutorials/css-css-units-explained)**
- In general, I use **[CSS custom properties](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties)** in my own code, It gives me superpowers, but I won't use them in this article

## Button Size:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0pu1datg1ruusjcecykh.jpeg)

the trick here is not to specify a **fixed size**, but rather to set limits for the **largest** and **smallest** size, as the button size will depend mainly on the **font size, t**o determine the size we will follow the basic design rules for buttons to find out more, I recommend reading this: **[Button design for websites and mobile apps](https://www.justinmind.com/blog/button-design-websites-mobile-apps/)**

```css
.Button {
    width: fit-content;
    max-width: min(100%, 100vw);
}
@supports not (width: fit-content) {
	.Button {
		width: auto;
	}
}
```

### **width: fit-content;**

- we use **[fit-content](https://developer.mozilla.org/en-US/docs/Web/CSS/fit-content)** as the size will use the available space, but never more than `max-content`.

### **max-width: min(100%, 100vw);**

- You specify the largest width that the element can reach ***[max-width](https://developer.mozilla.org/en-US/docs/Web/CSS/max-width)***
- using the **[min()](https://developer.mozilla.org/en-US/docs/Web/CSS/min)** To choose the smallest value between **100%** linked to the size of the parent element, which may be half the screen for example.
- **100vw** linked to the screen size.

You do this to allow the element to expand ( if desired ) to either parent size or screen size, without any overflow.


## Button layout, display & Align:

I used to use **[display: Block](https://developer.mozilla.org/en-US/docs/Web/CSS/display)** then I used **[display: inline](https://developer.mozilla.org/en-US/docs/Web/CSS/display)** but when I was learning **[React](https://reactjs.org/)** I discovered **[MUI](https://mui.com/)**, and as usual, the first thing I did was look at how they did their button and I found them using **[inline-flex](https://developer.mozilla.org/en-US/docs/Web/CSS/display)!**

> inline-flex The element behaves like an inline element and lays out its content according to the flexbox model.
> 

```css
.Button {
  display: inline-flex;
	justify-content: center;
	align-items: center;
	vertical-align: middle;
	text-align: center;
}

```

using the magic of Flex We will center any items inside this button. with:

- **[justify-content](https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content)**
- **[align-items](https://developer.mozilla.org/en-US/docs/Web/CSS/align-items)**

We will use properties like **[text-align](https://developer.mozilla.org/en-US/docs/Web/CSS/text-align)** & **[vertical-align](https://developer.mozilla.org/en-US/docs/Web/CSS/vertical-align)** in general for:

- To make sure an extra image or strange text is always in the middle.
- For the person who still uses an old browser (for browser support) In case flex doesn't work for some reason.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g5tm3tzaci6h017irasj.jpeg)



## Button properties, **padding & Font-size:**

Here lies the magic that makes this button work in all cases and all sizes.

```css
.Button {
    padding: max(0.5em, 0.5rem) max(1.5em, 1.5rem);
    font-size: clamp(0.875rem, 0.7rem + 0.7vw, 1.375rem);
}
@supports not (font-size: clamp(0.875rem, 0.7rem + 0.7vw, 1.375rem)) {
	.Button {
		font-size: 1rem;
	}
}
```

this seems more overkill than the max-width trick and it is, but You will only copy this code once and it will work in all cases.

- **[padding](https://developer.mozilla.org/en-US/docs/Web/CSS/padding)**: max(0.5em, 0.5rem) max(1.5em, 1.5rem); The trick here is to use **[max()](https://developer.mozilla.org/en-US/docs/Web/CSS/max)** Where if you notice that I use the same value once with **rem** and once with **em** but why?

The point of max() It is to choose which value is greater; Usually **em** will be bigger, Where if we assume that the font size of the button is **24px.**

> em = 24px and rem = 16px Follow the default browser size
> 

So why do we do this? In general, when using a small font size such as **12px** if you use just **em** The button dimensions will be too narrow Since it is related to the font size, but then **rem** will be the biggest. 

> em = 12px rem = 16px Still at the default text size
> 

we use this trick to define the **minimum** space inside the button and at the same time it allows the button to grow with the font size.


- font-size: clamp(0.875rem, 0.7rem + 0.7vw, 1.375rem); Honestly, I cannot explain to you how to choose these values here, as I will need another article.

But in short using **[clamp()](https://developer.mozilla.org/en-US/docs/Web/CSS/clamp)** Allows you to use a font that is responsive to your screen size with a **minimum of 0.875rem** and a **maximum of 1.375rem** ( for Example ).

> To make it easier, you can use a font size clamp calculator
> 

I **strongly** advise you to read these articles, as they will benefit you as web dev in general:

- **[Linearly Scale font-size with CSS clamp()](https://css-tricks.com/linearly-scale-font-size-with-css-clamp-based-on-the-viewport/)**
- **[Creating a Fluid Type Scale with CSS Clamp](https://www.aleksandrhovhannisyan.com/blog/fluid-type-scale-with-css-clamp/)**
- **[Modern Fluid Typography Using CSS Clamp](https://www.smashingmagazine.com/2022/01/modern-fluid-typography-css-clamp/)**

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/86pbm3rt7pzbrx9az37g.jpg)



## the Cherry on the Button:

```css
.Button {
    overflow: hidden;
    white-space: nowrap;
    cursor: pointer;
    user-select: none;
    appearance: button;

}
```

- **[overflow: hidden;](https://developer.mozilla.org/en-US/docs/Web/CSS/overflow)** To prevent anything from coming out outside the button.
- **[white-space: nowrap;](https://developer.mozilla.org/en-US/docs/Web/CSS/white-space)** Prevent text from going to more than one line.
- **[cursor: pointer;](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor)** The cursor is a pointer that indicates a link. Typically an image of a pointing hand.
- **[user-select: none;](https://developer.mozilla.org/en-US/docs/Web/CSS/user-select)** make The text of the element and its sub-elements is not selectable.
    
    > 'user-select' is not supported by Safari, Safari on iOS.This is an optional feature where if the button contains important text, you may allow it
    > 
- **[appearance: button;](https://developer.mozilla.org/en-US/docs/Web/CSS/appearance)** The appearance CSS property is used to control native appearance of UI controls, that are based on operating system's theme.
    
    > 'appearance' is not supported by Safari on iOS < 15.4.

## Button **hover & focus:**

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kd1r0u6dbi5v004h7tem.jpeg)


Nothing special I just determined how the button behaves in different situations, and I used a cool focus ring trick I learned from the king of CSS.

```css
.Button {
    box-shadow: 0 0 0 -0.4em hsl(0, 0%, 100%),
        0 0 0 -0.6em rgba(13, 109, 253, 0.7);
    transition: box-shadow 400ms cubic-bezier(0.66, -0.2, 0.27, 1.15);

}
.Button:active,
.Button:hover {
    opacity: 0.7;
}
.Button:focus-visible {
    box-shadow: 0 0 0 0.3em hsl(0, 0%, 100%),
        0 0 0 0.5em rgba(13, 109, 253, 0.7);
}
.Button:focus {
    outline: none;
}
```

# **Conclusion + Free gift!**

I hope I kept my promise to you!

“the written once-and-forgotten code” thing, now go and copy the code. I want to fulfill my promise to you, If you would like to use a more complex button in your next project, you can visit **[Moon-RockUI](https://github.com/ymhaah/Moon-RockUI),** Where you can help me create the best button.

version 1.0.0 soon!


## More From Us:

- [Newsletter](https://hefnawystudio.substack.com/?utm_source=navbar&utm_medium=web&r=31jf6o)
- [Twitter / X](https://twitter.com/hafanwy)
- [Instagram](https://www.instagram.com/hefnawystudio/)

## the complete code:

```
.Button {
    width: fit-content;
    max-width: min(100%, 100vw);
    display: inline-flex;
    justify-content: center;
    align-items: center;
    text-align: center;
    vertical-align: middle;
    overflow: hidden;
    appearance: button;
    user-select: none;
    text-transform: capitalize;
    white-space: nowrap;
    text-decoration: none;
    cursor: pointer;
    padding: max(0.5em, 0.5rem) max(1.5em, 1.5rem);
    font-size: clamp(0.875rem, 0.7220363289rem + 0.7648183556vw, 1.375rem);
    box-shadow: 0 0 0 -0.4em hsl(0, 0%, 100%),
        0 0 0 -0.6em rgba(13, 109, 253, 0.7);
    transition: box-shadow 400ms cubic-bezier(0.66, -0.2, 0.27, 1.15);
}
.Button:active,
.Button:hover {
    opacity: 0.7;
}
.Button:focus-visible {
    box-shadow: 0 0 0 0.3em hsl(0, 0%, 100%),
        0 0 0 0.5em rgba(13, 109, 253, 0.7);
}
.Button:focus {
    outline: none;
}
@supports not (font-size: clamp(0.875rem, 0.7rem + 0.7vw, 1.375rem)) {
	.Button {
		font-size: 1rem;
	}
}
@supports not (width: fit-content) {
	.Button {
		width: auto;
	}
}
```