Colorbars

Reviewed & published by Brayan K

A colorbar is the labeled strip beside a plot that acts as the legend for a colormap, translating each color back into the numeric value it represents.

Part of the free Matplotlib course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.

In this lesson you'll attach a colorbar with fig.colorbar(), give it a label and custom ticks, change its orientation and size, and share a single bar across several subplots.

What You'll Learn in This Lesson

1 Your First Colorbar

Color-carrying plots like imshow and scatter return a mappable — an object that knows its colormap and value range. Capture it in a variable and hand it to fig.colorbar(mappable, ax=ax). Without that mappable, Matplotlib has nothing to build the legend from.

import matplotlib.pyplot as plt
import numpy as np

data = np.random.default_rng(0).random((10, 10))

fig, ax = plt.subplots(figsize=(6, 5), constrained_layout=True)
im = ax.imshow(data, cmap="viridis")   # imshow returns a "mappable"

# Attach a colorbar to that mappable, on this Axes
cbar = fig.colorbar(im, ax=ax)
cbar.set_label("Value")

ax.set_title("Heatmap with a Colorbar")
plt.show()
The chart this code draws: Capture the mappable and attach a labeled colorbar
What this code draws, rendered with Matplotlib.

What you'll see: a 10×10 viridis heatmap with a vertical colorbar on its right edge, labeled "Value", running from dark purple at the bottom to bright yellow at the top.

2 Orientation, Ticks, Shrink & Pad

A colorbar is highly tunable. Use orientation="horizontal" to drop it below the plot, ticks=[...] to mark exactly the values you care about, shrink to scale its length, and pad to set the gap between plot and bar. Combine them to fit any layout.

import matplotlib.pyplot as plt
import numpy as np

data = np.random.default_rng(1).random((8, 8)) * 100

fig, ax = plt.subplots(figsize=(7, 4), constrained_layout=True)
im = ax.imshow(data, cmap="plasma")

# Horizontal colorbar, shrunk, with custom ticks and a label
cbar = fig.colorbar(im, ax=ax, orientation="horizontal",
                    shrink=0.8, pad=0.1, ticks=[0, 25, 50, 75, 100])
cbar.set_label("Percent")

ax.set_title("Custom Colorbar")
plt.show()
The chart this code draws: Horizontal orientation with custom ticks, shrink, and pad
What this code draws, rendered with Matplotlib.

What you'll see: a plasma heatmap with a shorter, horizontal colorbar sitting below it, marked only at 0, 25, 50, 75, and 100, and labeled "Percent".

3 One Colorbar for Many Subplots

When several panels share a scale, a single colorbar is cleaner than one per panel. The key is to give every panel the same vmin and vmax so a color means the same thing everywhere, then pass a list of Axes to the ax argument.

import matplotlib.pyplot as plt
import numpy as np

# Two panels that should share ONE colorbar -> same color scale
data1 = np.random.default_rng(2).random((10, 10))
data2 = np.random.default_rng(3).random((10, 10))

fig, axes = plt.subplots(1, 2, figsize=(9, 4), constrained_layout=True)

im0 = axes[0].imshow(data1, cmap="cividis", vmin=0, vmax=1)
im1 = axes[1].imshow(data2, cmap="cividis", vmin=0, vmax=1)
axes[0].set_title("Sensor A")
axes[1].set_title("Sensor B")

# One colorbar spanning BOTH axes
cbar = fig.colorbar(im1, ax=axes, shrink=0.8)
cbar.set_label("Reading")

plt.show()
The chart this code draws: One scale, two panels, a single shared colorbar
What this code draws, rendered with Matplotlib.

What you'll see: two cividis heatmaps side by side titled "Sensor A" and "Sensor B", with a single colorbar on the far right serving both — because both panels use the identical 0–1 scale.

🎯 Your Turn: Fill in the Blanks

Replace each ___ to add a labeled colorbar to a colored scatter plot.

import matplotlib.pyplot as plt
import numpy as np

x = np.random.default_rng(4).random(200)
y = np.random.default_rng(5).random(200)
z = x * y

fig, ax = plt.subplots(figsize=(6, 5), constrained_layout=True)
sc = ax.scatter(x, y, c=z, cmap="magma", s=40)

# Add a colorbar for the scatter's mappable (sc), on this Axes
cbar = fig.___(sc, ax=ax)

# Label the colorbar
cbar.___("x * y")

ax.set_title("Scatter")
plt.show()

Hint: the figure method is colorbar, and the label method on the returned object is set_label.

📋 Common Errors & Quick Reference

❌ RuntimeError: No mappable was found

You called fig.colorbar() without passing the plot object. Capture it first: im = ax.imshow(...), then fig.colorbar(im, ax=ax).

❌ The colorbar squashes my plot

Use constrained_layout=True and tune shrink/pad, instead of letting Matplotlib carve a large default slice out of the Axes.

❌ Shared colorbar doesn't match a panel

The panels auto-scaled differently. Give every panel the same vmin and vmax before sharing one bar.

CallWhat It Does
fig.colorbar(im, ax=ax)Attach a colorbar
cbar.set_label("...")Add a text label
orientation="horizontal"Place the bar below the plot
ax=[ax1, ax2]Share one bar across panels

🏆 Mini Challenge: Temperature Grid

Draw a temperature heatmap and give it a shrunk, padded vertical colorbar with custom ticks, a label, and smaller tick text.

import matplotlib.pyplot as plt
import numpy as np

grid = np.random.default_rng(6).normal(20, 5, (12, 12))

fig, ax = plt.subplots(figsize=(6, 5), constrained_layout=True)
im = ax.imshow(grid, cmap="coolwarm")

cbar = fig.colorbar(im, ax=ax, shrink=0.75, pad=0.04,
                    ticks=[10, 15, 20, 25, 30])
cbar.set_label("Temperature (C)")
cbar.ax.tick_params(labelsize=9)

ax.set_title("Temperature Grid")
plt.show()
The chart this code draws: A fully styled colorbar: ticks, label, shrink, pad
What this code draws, rendered with Matplotlib.
import matplotlib.pyplot as plt

grid = [[1, 2], [3, 4]]

fig, ax = plt.subplots()
im = ax.imshow(grid, cmap="plasma")
bar = fig.colorbar(im, ax=ax, label="units", shrink=0.8)

print("Axes on the figure:", len(fig.axes))
print("The colourbar has its own axes:", bar.ax is not fig.axes[0])
print("Label:", bar.ax.get_ylabel())
print("Range it covers:", [int(v) for v in im.get_clim()])
print("It follows the image's colormap:", bar.cmap.name == im.get_cmap().name)

# ✅ Expected output:
# Axes on the figure: 2
# The colourbar has its own axes: True
# Label: units
# Range it covers: [1, 4]
# It follows the image's colormap: True
The chart this code draws: A colourbar is its own axes, with its own label, following the image's colormap
What this code draws, rendered with Matplotlib.

❓ Frequently Asked Questions

Lesson complete — your color scales now explain themselves!

You attached colorbars with fig.colorbar(), labeled and re-ticked them, changed orientation and size with shrink and pad, and shared a single bar across multiple panels.

Practice quiz

What is a 'mappable' that fig.colorbar() needs?

  • A plot object carrying a colormap and value range
  • A dictionary of ticks
  • A figure title
  • A list of colors

Answer: A plot object carrying a colormap and value range. A mappable (from imshow, scatter, contourf, etc.) carries the colormap and limits the colorbar reads.

Which call attaches a colorbar for a captured image im on a given Axes?

  • ax.colorbar(im)
  • fig.colorbar(im, ax=ax)
  • plt.bar(im)
  • im.colorbar(ax)

Answer: fig.colorbar(im, ax=ax). fig.colorbar(im, ax=ax) draws the colorbar and ties it to that Axes.

Which method adds a text label to the colorbar object cbar?

  • cbar.title()
  • cbar.text()
  • cbar.set_label('Value')
  • cbar.label()

Answer: cbar.set_label('Value'). cbar.set_label('Value') labels the colorbar.

Which argument places the colorbar below the plot?

  • shrink=0.5
  • pad=0.1
  • ticks=[...]
  • orientation='horizontal'

Answer: orientation='horizontal'. orientation='horizontal' drops the bar below the plot.

What does the shrink argument do to a colorbar?

  • Scales its length
  • Changes its color
  • Moves it to the top
  • Adds ticks

Answer: Scales its length. shrink scales the bar's length, e.g. shrink=0.7 makes it 70% as long.

To share one colorbar across two panels, you pass ax as:

  • a single Axes
  • a list of Axes, e.g. ax=[ax1, ax2]
  • a string
  • None

Answer: a list of Axes, e.g. ax=[ax1, ax2]. Passing a list of Axes makes one bar serve all of them.

What must match across panels for a shared colorbar to be honest?

  • The figure size
  • The titles
  • The same vmin and vmax
  • The number of ticks

Answer: The same vmin and vmax. Same vmin/vmax means a color means the same value in every panel.

Which argument chooses exactly which values get marked on the bar?

  • pad
  • shrink
  • orientation
  • ticks=[...]

Answer: ticks=[...]. ticks=[0, 25, 50, 75, 100] marks just those values.

What error appears if you call fig.colorbar() with no mappable?

  • RuntimeError: No mappable was found
  • ValueError: bad shape
  • KeyError: cmap
  • IndexError

Answer: RuntimeError: No mappable was found. You must capture and pass the plot object; otherwise there is no mappable.

Which method restyles the colorbar's tick labels?

  • cbar.set_label()
  • cbar.ax.tick_params()
  • cbar.ticks()
  • cbar.format()

Answer: cbar.ax.tick_params(). cbar.ax.tick_params(labelsize=9) adjusts the tick text on the colorbar.

Continue this course

Frequently asked questions

What is a mappable, and why does fig.colorbar() need one?

A mappable is any plot object that carries a colormap and a value range — the thing returned by imshow, scatter, contourf, or pcolormesh. fig.colorbar() reads the colormap and limits from that object to draw the matching color scale, so you must capture and pass it: im = ax.imshow(...); fig.colorbar(im, ax=ax).

How do I add a label and custom ticks to a colorbar?

Capture the colorbar object and call its methods: cbar = fig.colorbar(im, ax=ax); cbar.set_label('Value'). Pass ticks=[...] to fig.colorbar() to choose exactly which values get marked, and use cbar.ax.tick_params() to restyle them.

How do I make a colorbar horizontal or smaller?

Pass orientation='horizontal' to place it below the plot. Use shrink to scale its length (shrink=0.7 makes it 70% as long) and pad to set the gap between the plot and the bar. These three arguments cover most layout tweaks.

How do I share one colorbar across several subplots?

Give every panel the same vmin and vmax so they use an identical scale, then pass a list of Axes to the ax argument: fig.colorbar(im, ax=[ax1, ax2]). Matplotlib steals a little room from each panel and draws a single shared bar.