No Time Dad

A blog about web development written by a busy dad

Gradient Buttons with CSS

Everyone is using gradient backgrounds these days. I get it. They’re a different way to add some pop to the background. Apple probably started this trend with their OS, and lots of other companies started implementing them on their sites. Call me a purist, but I still prefer a clean white background with solid colors. I might be alone in that, though.

One of my favorite usages of a grandient background is stripe’s landing page. Their background actually moves. I’m not sure what kind of css trickery is involved there, but it’s cool. Below is a screenshot of part of their landing page. I like how the gradient background is only on part of the page. It isn’t overwhelming.

stripe_landing_page

It turns out that buttons can have gradients too. I’m not sure if it’s as common as page backgrounds, but it’s an interesting use of gradients. It does require some additional considerations like focus and hover states, but implementing a gradient background on a button is reasonably straight-forward.

Building buttons

The best place for me to start is with a baseline button. I can then add modifier classes to it and make different versions of the gradient background. The modifiers will also allow to control the hover and focus states individually as needed.

I’ve written about the baseline button previously, and I’ll be reusing those styles here. I’ll be making the buttons in this example using React, but that’s mostly just for convenience. They can easily be translated to html or another web framework as needed.

The nice thing about having the baseline button selector defined is that I only need to add a couple more rules to make a button with a gradient that really pops. The gradient is defined by using the linear-gradient css function with the background property.

I won’t dig into it in this post, but the linear-gradient function takes a number of arguments and is very flexible as a result. You can get very creative with it. I ended up just grabbing some gradients from cssgradients for these examples.

const BaselineButton = () => (
  <button type="button" className={styles.Button}>Button</button>
);
.Button {
  background-color: #fff;
  border-color: #dbdbdb;
  border-width: 1px;
  color: #363636;
  border-radius: 0.5rem;
  padding: 1rem 1.5rem;
}

.Button:hover {
  border-color: #b5b5b5;
  color: #363636;
}

.Button:focus {
  outline: none;
  border-color: #485fc7;
  color: #363636;
  box-shadow: 0 0 0 0.125em rgba(72, 95, 199, 0.25);
}

The AquaButton example was convenient because the blue already matched the :focus state, I just had to change the text color. The other considerations were changing the background on :hover so users could visually tell the button is clickable, and maintaining a text color that’s easy to read.

const AquaButton = () => (
  <button type="button" className={`${styles.Button} ${styles.Aqua_Button}`}>Button</button>
);
...

/* Modifiers that overwrite some Button styles */
.Aqua_Button {
  /* Add the gradient */
  background: linear-gradient(90deg, #00d2ff 0%, #3a47d5 100%);
  /* White text is easier to see on blue */
  color: white;
}

.Aqua_Button:hover {
  /* Flip the colors */
  background: linear-gradient(#00d2ff 0%, #3a47d5 100%);
  /* Retain white text */
  color: white;
}

.Aqua_Button:focus {
  /* Retain white text */
  color: white;
}

The CucumberButton is similar to the AquaButton but it keeps the text color dark and changes the outline to be light.

const CucumberButton = () => (
  <button type="button" className={`${styles.Button} ${styles.Cucumber_Button}`}>Button</button>
);
...

.Cucumber_Button {
  background: linear-gradient(90deg, #e3ffe7 0%, #d9e7ff 100%);
}

.Cucumber_Button:hover {
  border-color: #9bfaa9;
  background: linear-gradient(#e3ffe7 0%, #d9e7ff 100%);
}

.Cucumber_Button:focus {
  border-color: #9bfaa9;
}

The third example here is a little more complex. It uses the radial-gradient css function instead of linear-gradient. It’s just as flexibile as linear-gradient, but it creates a gradient that “radiates” from an origin point.

I changed the origin point on hover, as well as the :focus box-shadow color. I somehow ended up with a button that looks like it’s from the 80s. Which I’m into.

const SunburstButton = () => (
  <button type="button" className={`${styles.Button} ${styles.Sunburst_Button}`}>Button</button>
);
...

.Sunburst_Button {
  color: white;
  background: radial-gradient(
    circle farthest-corner at 10% 20%,
    rgba(255, 37, 174, 1) 0%,
    rgba(241, 147, 55, 1) 53.4%,
    rgba(250, 237, 56, 1) 99.5%
  );
}

.Sunburst_Button:hover {
  color: white;
  border-color: rgb(247, 124, 1);
  background: radial-gradient(
    circle farthest-corner at 100% 20%,
    rgba(255, 37, 174, 1) 0%,
    rgba(241, 147, 55, 1) 53.4%,
    rgba(250, 237, 56, 1) 99.5%
  );
}

.Sunburst_Button:focus {
  color: white;
  border-color: rgb(247, 124, 1);
  box-shadow: 0 0 0 0.125em rgb(247, 124, 0.05);
}

Conclusion

A fun experiment with buttons and gradients. The real superstar here was the base Button selector that I was modifying. Having a base to work from is so helpful for any type of element. Recreating the same elements over and over isn’t a lot of fun. It’s nice to be able to just modify the base.