Gradients in CSS

A *lot* is possible with gradients in CSS - from the classic linear, to conic, it's all SUPER fun stuff.

There are three primary types of CSS gradients. There’s the classic, easy to understand linear-gradient, the slightly more complicated radial-gradient, and the simply mind blowing conic-gradient. I’ve used the former two to great extent, but conic gradients are something that I’m still learning about. All of these types of gradients also have their repeating counterparts, which adds one more layer of complexity.
In this article we’re gonna talk about what defines a gradient, what the values in each function mean, how to use each function, and practical applications for each of the types. Bonus: I’ll show you 3 samples of production code where I’m using them.

What’s a gradient?

Simply put, a gradient is an image that smoothly fades from one color to another. In CSS, gradients are represented by the gradient data type. CSS Gradients have no natural or preferred size, nor do they have a preferred ratio. Gradients will always match the size of the element to which they are applied. The data type is defined with one of the 6 gradient functions, which is what I’ll be describing.


What’s the value?

Gradients are specified by defining the starting point and ending point of a gradient line. Depending on the type of gradient, that line may be a line, a ray, or a spiral. Then, colors are defined at points along the gradient line. Colors are smoothly blended to fill in the rest of the line, then each type of gradient defines how to use the color of the gradient line to produce the actual gradient.


Linear Gradients

Linear Gradients are probably the easiest type to understand. The function accepts an argument to control the direction and an argument to define the colors & their interpolation.
The first argument decides the angle or direction of the gradient line. Values may be an angle like 70deg-45deg, or 1.555deg. The other value may be side-or-corner keywords, like leftrighttop, or bottom. Each of these keywords is preceeded by the keyword to, which tells you (the coder) and the browser that the origin of the gradient is the opposite side of the stated direction. This argument is optional, with default value most often being to bottom, though that default value is not part of the standard.
The second argument controls the colors & how they interact with eachother. There’s a lot of room for confusion here, so I’ll work through this slowly the first time. We’ll put direction aside for a moment and focus solely on this argument.

Simple gradients will be defined with two colors, the mixing (interpolation) of which will be decided by the browser. The gradient linear-gradient(red, blue); will be 100% red on the top, 100% blue on the bottom, and a mix of 50% each in the middle. That example is below.

.gradient-simple {
  width: 100%;
  height: 100px;
  background: linear-gradient(red, blue);
}

Those color keywords can be paired with length values to control where one color ends and the next begins.

.gradient-simple-2 {
  background: linear-gradient(red 10%, blue 20%, orange 100%);
}

Defining the next color with a length value that is equivalent to the length value of the preceding color sets a “hard stop”, or a clear seperation of the two colors. Color stops get much more complex, but the basis of them is that you can set where one color stops. You can also pass gradient hints, which will mix the two colors in the same way, but with the midpoint being wherever the hint is.

.gradient-simple-3 {
  background: linear-gradient(red 50%, blue 50%);
}

Let’s throw in the directionality component by setting the angle to 45 degrees.

.gradient-simple-4 {
  background: linear-gradient(45deg, red, blue);
}

Let’s try it with the to right keyword.

.gradient-simple-5 {
  background: linear-gradient(to right, red 10%, blue 10%, blue 90%, red 90%);
}

I think linear gradients are a nice tool to create ambiance. I use them often in progress bars. Look at the top of this page: the hero has a linear gradient background!

Radial Gradients

A radial gradient is a transition between two or more colors that radiate from an origin in a circle of an ellipse. The function accepts arguments for position, ending shape, size, linear color stop, and color hint.
The position is interpreted in the same way as background-position or transform origin, so the same keywords and length values will work here. Left unspecified, the default is center.
The ending shape can be circle, which means the shape of the gradient is a circle with a constant radius, or ellipse which is an axis-aligned ellipse. The default is ellipse.
The size sets the size of the gradient’s ending shape. The size can be given explicitly (with a length value) or by keyword. For circles, the explicit size can be given as any length, but for ellipses, the explicit length value must be a non-negative length percentage with two values. The first value represents the horizontal radius, while the second value represents the vertical radius. The percentages are relative to the box. The keywords are:

  • closest-side: for circles, the ending shape meets the side of the box closest to its center. For ellipses, the ending shape meets both the vertical and horizontal sides closest to the center.
  • closest-corner: the ending shape is sized so that it meets the closest corner from the box at its center.
  • farthest-side: the ending shape is sized to meet the side of the box farthest from its center (or vertical and horizontal sides)
  • farthest-corner: the ending shape is sized so that it meets the farthest corner of the box from its center.

If left unspecified, the default value is farthest-corner.
The linear color stop argument is built of a color-stop’s color value, with one or two optional stop positions (either a percentage or a length along the gradient’s axis). A percentage or length of 0 is the center, while 100% represents the intersection of the ending shape with the virtual gradient ray. Defining two stop positions is the same as declaring two color stops with the same color at the two positions.
The color-hint defines how the gradient progresses between adjacent color stops. The length defines at which point between the two color stops the gradient color should reach the middle of the transition. Left empty, the midpoint is defined as the midpoint of the two stops.
Wow, that was a lot. Let’s get in to putting this to paper, shall we? We’ll start with a basic gradient: an ellipse that is centered, going from orange to blue.

.gradient-ellipse {
  width: 100%;
  height: 250px;
  background-image: radial-gradient(orange, blue);
}

Now, let’s change where the gradient is centered, introduce some color stops, and a color hint.

.gradient-ellipse-2 {
  background-image: radial-gradient(
    circle farthest-side at 20px 200px, red, red 10% 20%, yellow 50%, blue
  );
}

I think radial gradients are pretty neat. I don’t use them often, but for backgrounds and icons they’re a decent tool. They work real well for patterned backgrounds (espcially the repeating variant).

Conic Gradients

I’m real excited to talk about conic gradients, which I just learned about recently. Conic gradients have color transtitions rotated around a center point (as opposed to radiating from the center). Think of a pie chart or a color wheel. The function is pretty semple to understand, I think.
The angle is the first value passed, which is preceded by the from keyterm, and accepts an angle as its value. This value sets the gradient rotation in clockwise direction. Think of this as the start and end point.
The position comes next, which defines the center of the gradient. It accepts the same length, order, and keyterm values as the background-position propery, with the default value being center.
The angular color stop is next, which is really just the color with one or two optional stop positions being an angle along the gradient’s circumference axis.
Lastly is the color hint, which we’ve discussed before.

A quick note on color stops: they can be defined as degrees, gradients, radians, turns, or as percentages (representing degrees, where 0% = 0deg and 100% = 360deg). The default starting point of the arc is 12:00, north – straight up and down. The angle, the first value passed, sets the degrees by which the starting point should be rotated from that origin. Let’s see a gradient, yeah?

.conic-gradient {
  width: 250px;
  height: 250px;
  margin: 0 auto;
  background-image: conic-gradient(blue, green, red);
}

Let’s change where the center is and add some hard color lines. This one’s a bit confusing!

.conic-gradient-2 {
  background-image: conic-gradient(from 10deg at 10% 10%, red 20deg, blue 20deg, blue 35deg, green 35deg);
}

The practical implication of a conic gradient is a pie chart. Let’s go through how to build that. We’ll source numbers from the table below:

NameScoreColor
Deb75Green
Bræntleigh19Orange
Bill42Blue
Craig94Red
Total:230Brown

We know the scores of each player, so we can divide by the total to get the percentage of each score. Deb’s score of 75 is 0.3260869565 of the final score, which is 32.7%. Bræntleigh has 8.26%, Bill has 18.26%, and Craig has 40.87%. We can throw these right in to a conic gradient and they’ll make sense as it, but we can do a little better, too, I think. Let’s put them in descending order (Craig, Deb, Bill, Bræntleigh) and translate them to degrees. Craig’s 40.87% of 360deg is 147.132deg. Deb’s share is 117.72. Bill’s share is 65.736deg. And Bræntleigh’s share is 29.736deg.

Alright, pause from math.

Craig’s slice should go from 0deg to 147.132deg.
Deb’s share should go from 147.132deg to 264.852deg.
Bill’s slice should go from 264.852deg to 330.588deg.
And Bræntleigh’s slice will go from 330.588deg to 360.324deg. Wait – I messed up the math there. It should go to the end! Oops. Here’s all the above in CSS:

.pie {
  widht: 300px;
  height: 300px;
  margin: 0 auto;
  border-radius: 50%;
  background-image: conic-gradient(
    from 0deg at center,
    red 0deg, red 147.132deg, 
    green 147.132deg, green 264.852deg, 
    blue 264.852deg, blue 330.588deg,
    orange 330.852deg, orange 360deg
  );
}

Conic gradients are jus the newest thing I’ve come across, but something else I really like are the repeating variants of all of these. I’m definitely getting a little “ranty” with a lot of this so I promise I’ll try to keep this section short…well, kinda.

Repeating Linear Gradients

I feel like repeating linear gradients will be the easiest to understand, partly because linear gradients are pretty intrinsic. The syntax is exactly the same, but the last value passed (which should be a length) will determine how many times the pattern repeats and the location at which is starts repeating. Here’s some examples:

#rlg {
  width: 100%;
  height: 250px;
  background: repeating-linear-gradient(
  45deg,
  blue, blue 10%,
  seagreen 10%, seagreen 20%);
}

#rlg2 {
  width: 100%;
  height: 250px;
  background: repeating-linear-gradient(130deg,
  #DDD8D2, #DDD8D2 25px,
  #DEC6C4 25px, #DEC6C4 50px,
  #B98A94 50px, #B98A94 75px,
  #4E4E4E 75px, #4E4E4E 100px,
  #42302C 100px, #42302C 125px);
}

Repeating Radial Gradient

Repeating radial gradients take the same concept of repeating linear gradients and uses the last color stop to determine the size and location of the repeat. Again, more examples below. Think “bullseye”!

#rrg {
  width: 100%;
  height: 250px;
  background: repeating-radial-gradient(circle farthest-side at 20px 200px, red 10% 20%, yellow 20% 50%);
}

I’ve been working on this article for a long time and honestly am excited to finally publish it. I’ll try to remember to come back with examples as I use more gradients in my day-to-day!

My sources include the MDN and CSS Working Group. I pull definitions from the CSSWG wherever possible, and try to use MDN as more of a guide about how to talk about things.

Leave a Reply

Your email address will not be published. Required fields are marked *