ggplot2 scale_fill_gradient() in R: Custom Color Gradients
ggplot2 scale_fill_gradient() in R maps a continuous variable to a two-color fill gradient (default dark blue to light blue). Pass low and high to set the endpoints, then pair the scale with geom_tile(), geom_raster(), or geom_col().
scale_fill_gradient() # default blue gradient scale_fill_gradient(low = "white", high = "red") # custom 2-color scale_fill_gradient2(low = "blue", mid = "white", high = "red") # diverging 3-color scale_fill_gradientn(colors = c("white", "yellow", "red")) # multi-color palette scale_fill_gradient(limits = c(0, 100), breaks = c(0, 50, 100)) # fixed legend range scale_fill_gradient(na.value = "grey80") # color for NAs scale_fill_gradient(trans = "log10") # log-scaled colors
Need explanation? Read on for examples and pitfalls.
What scale_fill_gradient() does in one sentence
scale_fill_gradient() builds a continuous two-color fill scale for ggplot2. It linearly interpolates between a low color (default dark blue, #132B43) and a high color (default light blue, #56B1F7) across the range of a numeric variable mapped to the fill aesthetic. The function is part of the ggplot2 fill gradient family and lives alongside scale_fill_gradient2() (diverging, three-color) and scale_fill_gradientn() (arbitrary n-color palette).
Syntax and arguments
scale_fill_gradient(low, high, ...) maps the fill aesthetic to a continuous color gradient. Six arguments cover almost every authoring need: low, high, na.value, limits, breaks, and labels.
Key arguments at a glance:
lowandhigh: the two endpoint colors (any valid R color name, hex code, orrgb()value).na.value: color used for missing values in the fill variable (default"grey50").limits = c(min, max): clip the data range; values outside the limits become NA unlessoobis set.breaksandlabels: tick positions and tick labels on the colorbar legend.guide: legend type, usually"colorbar"(default) or"legend".
Five practical patterns
These five recipes cover almost every real-world use of the two-color fill gradient.
scale_fill_continuous() is a shortcut to the default fill scale. Setting options(ggplot2.continuous.fill = "viridis") swaps the project-wide default to viridis palette without touching individual plots.1. Custom low and high colors
2. Fixed limits and custom breaks
3. Diverging three-color with gradient2
4. Multi-color palette with gradientn
5. Gradient on a bar chart
gradient() vs gradient2() vs gradientn()
The three functions span increasing palette complexity.
| Function | Colors | Best for | Key arguments |
|---|---|---|---|
scale_fill_gradient() |
2 | One-directional magnitude | low, high |
scale_fill_gradient2() |
3 | Diverging around a midpoint | low, mid, high, midpoint |
scale_fill_gradientn() |
n | Arbitrary multi-stop palette | colors (vector) |
When to use which:
gradient()for one-directional magnitude (low intensity to high intensity).gradient2()when zero or a center value carries meaning (residuals, correlations, percent change).gradientn()when you want a multi-stop palette (terrain colors, heat, custom corporate palette).
gradient vs gradient2 is a statistical decision, not an aesthetic one.Common pitfalls
Three mistakes account for most scale_fill_gradient bugs.
Pitfall 1: fill vs color aesthetic. Geoms like geom_point(), geom_line(), and geom_text() use color, not fill, for their primary visual. Pair scale_fill_* with fill-capable geoms (geom_tile, geom_raster, geom_col, geom_bar, geom_polygon, geom_sf). For points, lines, and text, use scale_color_gradient() instead.
Pitfall 2: discrete data on a continuous scale. scale_fill_gradient() is continuous. If the fill variable is a factor or character, ggplot errors with "Continuous value supplied to discrete scale". Convert the variable with as.numeric() first or switch to scale_fill_manual() and scale_fill_brewer() for true categories.
Pitfall 3: limits that silently clip the data. Setting limits = c(0, 10) when the data ranges to 25 turns out-of-bounds values into NA (greyed-out cells). Set oob = scales::squish to clamp out-of-bounds values to the nearest limit instead of dropping them, or widen the limits.
#132B43) is much darker than the default high (#56B1F7). Most readers expect "high values look bold, low values look pale" but the default flips that convention. Override the defaults whenever the implicit reading direction matters.Try it yourself
Try it: Take the volcano dataset built into base R and plot it as a heatmap with geom_tile(). Use scale_fill_gradient() with low = "white" and high = "darkgreen". Save the plot to ex_volcano.
Click to reveal solution
Explanation: expand.grid() builds the cell grid, as.vector() flattens the matrix to a numeric column ggplot can map to fill, and coord_equal() keeps cells square so the elevation map reads correctly.
Related ggplot2 functions
After mastering scale_fill_gradient(), these scales handle adjacent jobs.
scale_color_gradient(): same idea applied to the color aesthetic (points, lines, text).scale_fill_viridis_c(): perceptually uniform, colorblind-safe palette.scale_fill_distiller(): continuous ColorBrewer palette built onscale_color_brewer().scale_fill_manual(): discrete categorical fill with explicit color values.scale_x_continuous(): continuous x-axis with a similar limits/breaks API.
For the full argument list and edge cases, see the ggplot2 scale_fill_gradient reference.
FAQ
What does scale_fill_gradient do in ggplot2?
scale_fill_gradient() maps a continuous numeric variable to a two-color fill gradient. It interpolates linearly between a low color and a high color across the range of the variable. The function works with fill-capable geoms such as geom_tile(), geom_raster(), geom_col(), geom_bar(), geom_polygon(), and geom_sf(). Without arguments it produces the default dark-blue to light-blue gradient.
What is the difference between scale_fill_gradient and scale_color_gradient?
The two scales are identical in mechanics but apply to different aesthetics. scale_fill_gradient() targets the fill aesthetic, used by area geoms like tiles, bars, and polygons. scale_color_gradient() targets the color aesthetic, used by points, lines, and text. Choose the one that matches the aesthetic in your aes() mapping; mixing them silently does nothing because the scale targets the wrong slot.
How do I add a midpoint to a ggplot gradient?
Switch to scale_fill_gradient2() and pass midpoint. The diverging variant uses three colors (low, mid, high) and centers the mid color on the midpoint value. A correlation heatmap typically uses scale_fill_gradient2(low = "blue", mid = "white", high = "red", midpoint = 0) so negative correlations show blue, positive show red, and values near zero render white.
How do I reverse the direction of scale_fill_gradient?
Swap the values you pass to low and high. For example, scale_fill_gradient(low = "red", high = "white") reverses the default direction. There is no direction = -1 argument on scale_fill_gradient() itself; that argument exists on scale_fill_viridis_c() and scale_fill_brewer(), not on the generic gradient scale.
What is scale_fill_gradientn used for?
scale_fill_gradientn() accepts an arbitrary vector of colors and builds a multi-stop palette by interpolating between them in order. Pass colors = c("white", "yellow", "orange", "red") for a heat palette, or any custom sequence. Use gradientn when two colors (gradient) or three (gradient2) cannot express the palette shape you want, such as terrain maps or branded multi-color scales.