How to Make an HTML Button Not Look Terrible

April 19 2025

HTML buttons are notoriously ugly by default. Let's fix that with a few progressive enhancements—building from a raw <button> element into something polished and usable.

Step 1: Basic Color

We'll start by giving our button a nice blue background and white text:

.btn {
    background-color: #2f8ecc;
    color: #fff;
}

Step 2: Typography

Let's make the text a bit more readable by setting a font and increasing the size. You can also use font-family: inherit if your body or container already has a nice font.

.btn {
    background-color: #2f8ecc;
    color: #fff;
    font-family: 'Muli', sans-serif;
    font-size: 16px;
}

Step 3: Border and Radius

Next, we'll remove the default border and round the corners slightly.

.btn {
    background-color: #2f8ecc;
    color: #fff;
    font-family: 'Muli', sans-serif;
    font-size: 16px;
    border: 0;
    border-radius: 6px;
}

Step 4: Padding

We'll add some padding to make the button feel more balanced. Top and bottom padding is half the font size; left and right give the text some breathing room.

.btn {
    background-color: #2f8ecc;
    color: #fff;
    font-family: 'Muli', sans-serif;
    font-size: 16px;
    border: 0;
    border-radius: 6px;
    padding: 8px 30px;
}

Step 5: Spacing

To avoid the buttons being too cramped when placed together, we add a small margin.

   .btn {
     /* ... previous styles ... */
     margin: 5px;
   }

Step 6: Disabled State

>We don't want disabled buttons to look the same as active ones. Here we change their appearance using the :disabled pseudo-selector.

.btn:disabled {
    background-color: #cfcfcf;
    opacity: 0.9;
}

Step 7: Cursor Behavior

Add cursor feedback: a pointer for active buttons, and a not-allowed icon for disabled ones.

.btn {
    /* ... previous styles ... */
    cursor: pointer;
}

.btn:disabled {
    background-color: #cfcfcf;
    opacity: 0.9;
    cursor: not-allowed;
}

Step 8: Click Feedback

Let's add a little visual feedback when the button is pressed. A subtle scale transform gives a satisfying “click” feel.

.btn:active {
    transform: scale(0.95);
}

However, this applies even to disabled buttons—which we don't want. So we scope it to only apply when the button is enabled:

.btn:enabled:active {
    transform: scale(0.95);
}
    

Step 9: Focus Cleanup

Finally, let's remove the default focus outline:

.btn:focus {
    outline: 0;
}
    

You might want to add your own custom focus style for accessibility later. For now, this just cleans things up visually.

Done

That's it! A clean, functional button with minimal code and clear behavior. You can always build on this—add hover states, animations, or theme variations—but this is a solid baseline.