Colors & Styles

A deep dive into color theory, gradients, patterns, transparency, compositing, line styles, and shadows on the Canvas.

Lesson 3 of 10

How Computers Represent Color

Before we paint anything, let’s understand how color works on screens. Your monitor has millions of tiny lights, each made of three sub-pixels: one red, one green, and one blue. By mixing these three colors of light at different intensities, your screen can create virtually any color you can see.

This is called the RGB color model. Each channel (Red, Green, Blue) ranges from 0 (off) to 255 (full brightness). That gives us 256 x 256 x 256 = over 16 million possible colors.

Think of it like stage lighting. Imagine three spotlights in a dark theater: one red, one green, one blue. Point them all at the same spot on the wall:

Red only       Green only     Blue only      Red + Green    All three
+------+       +------+       +------+       +------+       +------+
| R    |       |    G |       |      |       | R  G |       | R  G |
|  **  |       |  **  |       |  **  |       |  **  |       |  **  |
| RED  |       | GRN  |       |   B  |       | YLW  |       |   B  |
+------+       +------+       +------+       +------+       +------+
(255,0,0)      (0,255,0)      (0,0,255)     (255,255,0)   (255,255,255)
                                               = Yellow       = White!

Key insight: mixing light is additive. Adding more light makes things brighter. This is the opposite of mixing paint, where adding more paint makes things darker.

The demos below use beginPath() and arc() from Lesson 2 to draw circles. Here, we focus on color rather than shape.

RGB Color Mixing: Additive Light paused

Try this: Change the globalAlpha values from 0.6 to 0.3 for subtle blending, or 0.9 for near-solid layers. Watch how the overlap colors shift.

Color Formats Canvas Understands

Canvas accepts any color format that CSS understands. Let’s explore each one so you know your options.

Named Colors: CSS has 140+ built-in color names like crimson, cornflowerblue, salmon. Easy to read, but limited palette.

Hex (#rrggbb): Each pair of hex digits represents a channel: #ff0000 = red 255, green 0, blue 0. Compact, widely used.

RGB (r, g, b): rgb(255, 0, 0), same as hex but easier to read. Values 0-255 per channel.

RGBA (r, g, b, a): Like RGB but with an alpha (opacity) channel from 0.0 (invisible) to 1.0 (solid).

HSL (h, s%, l%): Hue (0-360 degrees on a color wheel), Saturation (0-100%), Lightness (0-100%). Often more intuitive; we’ll explore this next.

All Color Formats Side by Side paused

The HSL Color Model: Your Secret Weapon

RGB makes you juggle three numbers to get a color. HSL (Hue, Saturation, Lightness) lets you think about color the way you already do: pick a color, decide how bold it should be, then choose how light or dark.

Hue: “What color?” Pick a spot on the rainbow. It is a number from 0 to 360, like degrees on a circle. 0 is red, 120 is green, 240 is blue, and 360 wraps back to red.

Saturation: “How vivid?” At 100% the color is pure and vibrant. At 0% all the color drains out and you get gray.

Lightness: “How light or dark?” 0% is always black, 100% is always white, and 50% gives you the true color.

          The Hue Color Wheel (degrees)

                  0/360 = Red
                     |
          330       |       30
     Magenta  \     |     /  Orange
               \    |    /
      300 ------+-------+----- 60
      Violet    |   *   |    Yellow
               /    |    \
          270 /     |     \ 90
     Blue-Violet    |      Yellow-Green
                    |
                180 = Cyan
                 (turquoise)

Saturation: center (gray) ────> edge (vivid)
Lightness:  separate axis: 0% black, 100% white

HSL is incredibly useful in code because you can generate harmonious color schemes just by shifting the hue angle, and you can create tints and shades by adjusting lightness.

The Hue Wheel: All 360 Degrees paused
Why HSL is Powerful in Code paused

fillStyle and strokeStyle

Every shape you draw on Canvas uses two style properties. Think of them like choosing your art supplies:

fillStyle: the paint color that fills the inside of shapes. Like choosing which paint to pour into a bucket.

strokeStyle: the pen color for outlines. Like choosing which marker to trace edges with.

Both accept any color format. Once set, they stay set until you change them, like picking up a new paintbrush.

fillStyle vs strokeStyle paused

Transparency and Opacity

Transparency lets you see through shapes to whatever is behind them. Canvas gives you two ways to control this.

Analogy: Glass Windows. Imagine stacking colored glass windows:

alpha = 1.0         alpha = 0.5          alpha = 0.0
(fully opaque)      (semi-transparent)   (invisible)
+──────────+        +──────────+         +──────────+
│##########│        │# # # # # │         │          │
│##########│        │ # # # #  │         │          │
│## SOLID ##│        │# SEMI  # │         │ NOTHING  │
│##########│        │ # # # #  │         │          │
+──────────+        +──────────+         +──────────+
Like a wall.        Like tinted          Like clear
Blocks everything   glass. Lets some     glass. Fully
behind it.          light through.       transparent.

Method 1: ctx.globalAlpha = 0.5 affects ALL subsequent draws. Remember to reset it to 1.0!

Method 2: rgba(r, g, b, alpha) or hsla(h, s%, l%, alpha) for per-color transparency. More precise control.

globalAlpha vs RGBA: Two Approaches paused
Transparency Layering: Overlapping Circles paused

Linear Gradients

A gradient smoothly transitions between two or more colors. A linear gradient transitions along a straight line. Think of it like a paint roller that starts with one color and gradually shifts to another.

createLinearGradient(x0, y0, x1, y1) defines the line along which colors change:

Horizontal:  (0, 100) ─────────> (500, 100)
             start                end
             Left to right, same y

Vertical:    (100, 0)
                │
                │  Top to bottom, same x
                v
             (100, 400)

Diagonal:    (0, 0)
                \
                 \  Corner to corner
                  v
                 (500, 400)

After creating the gradient, add color stops: gradient.addColorStop(position, color)

position is 0.0 (start) to 1.0 (end). You can add as many stops as you want!

Linear Gradient Directions paused
Practical Example: Sunset Sky paused

Radial Gradients

A radial gradient transitions colors outward from a center point, like ripples in a pond. It’s defined by two circles: an inner circle (where the gradient starts) and an outer circle (where it ends).

createRadialGradient(x0, y0, r0, x1, y1, r1)

(x0, y0, r0) = inner circle center + radius  (gradient START)
(x1, y1, r1) = outer circle center + radius  (gradient END)

Centered (same center):        Off-center (spotlight):
+───────────────────+          +───────────────────+
│                   │          │                   │
│     .-"""-.       │          │  .-"""-.          │
│   /  inner  \     │          │ / inner \  outer  │
│  │   (r0)   │     │          │ │  (r0)   \  (r1) │
│   \        /      │          │  \       / ---'   │
│     '-...-'       │          │   '-...-'         │
│    outer (r1)     │          │                   │
+───────────────────+          +───────────────────+
Colors radiate evenly          Light source is offset
from center outward            creating a spotlight
Radial Gradient Variations paused

Patterns with createPattern()

Besides solid colors and gradients, you can fill shapes with a repeating pattern. A pattern is like digital wallpaper: you create a small tile, and Canvas repeats it to fill any shape.

createPattern(image, repetition) where:

image = any image source (Image, Canvas, Video)

repetition = “repeat” (tile both ways), “repeat-x” (horizontal only), “repeat-y” (vertical only), “no-repeat” (once)

The easiest way to make patterns is to draw a tile on an offscreen canvas, then use that canvas as the pattern source.

createPattern: Repeating Tile Patterns paused

Composite Operations (Blending Modes)

globalCompositeOperation controls how new shapes interact with existing content on the canvas. The default is “source-over”, where new shapes paint on top. But there are 26 different modes that let you multiply, screen, subtract, and more.

Analogy: Photo editing layers. If you’ve used Photoshop or GIMP, composite operations are like blend modes. They control how a new layer combines with layers below it.

”source” = the new shape you’re drawing

”destination” = what’s already on the canvas

source-over      source-atop      destination-over     xor
+------+         +------+         +------+             +------+
|  BB  |         |  .B  |         |  AA  |             |  BA  |
| AABB |         | AABB |         | AABB |             | AA.BB|
| AA   |         | AA   |         | AABB |             | AA   |
+------+         +------+         +------+             +------+
New on top       New only where   Old on top           Overlap
of old           old exists       of new               becomes clear

A = existing (destination)     B = new shape (source)
Common Composite Operations paused
Practical Use: Eraser with destination-out paused

Line Styles

Lines in Canvas aren’t just “draw a line.” You can control their thickness, how their ends look, how corners connect, and whether they’re dashed.

lineWidth: thickness in pixels. The line is centered on the path, so half the width extends to each side.

lineCap: how line endpoints are drawn:

"butt"       "round"      "square"
---|---      ---O---      --[|]--
Ends at      Adds a       Adds a
the exact    semicircle   rectangle
endpoint     beyond       beyond the
             the end      endpoint

lineJoin: how corners between line segments connect:

"miter"      "round"      "bevel"
  /\           /\           /\
 /  \         (  )         /--\
Sharp        Rounded      Flat
corner       corner       corner
lineCap, lineJoin, lineWidth paused

Dashed Lines and Marching Ants

setLineDash([segments]) creates dashed lines. The array alternates between dash length and gap length. lineDashOffset shifts the pattern; animate it for a “marching ants” selection effect.

setLineDash Patterns paused
Animated Marching Ants (lineDashOffset) paused

Shadows

Canvas can add shadows to anything you draw: shapes, text, and images. There are four shadow properties that work together.

shadowColor: the shadow’s color (use rgba for translucent shadows).

shadowBlur: how fuzzy the shadow is (0 = sharp, higher = softer).

shadowOffsetX / shadowOffsetY: where the shadow falls relative to the shape.

shadowBlur = 0        shadowBlur = 10       shadowBlur = 30
+───+                 +───+                 +───+
│   │x                │   │                 │   │
+───+x                +───+                 +───+
  xxxx                . soft .              .........
Sharp shadow          Moderate blur         Extremely soft

offsetX = 5, offsetY = 5   (shadow cast down-right)
offsetX = 0, offsetY = 0   (glow effect: shadow all around)

Always reset shadows when done! Otherwise every subsequent draw gets shadows too.

Shadow Properties Explained paused
Neon Glow Text and 3D Depth paused

Putting It All Together: Night City Scene

Let’s combine gradients, patterns, transparency, shadows, and compositing into one scene. Study this example to see how all the techniques work together.

Night City: All Color Techniques Combined paused

Lesson 3 Recap: What you learned.

Colors: RGB (how screens work), HSL (how humans think), and all CSS formats. fillStyle for fills, strokeStyle for outlines.

Transparency: globalAlpha (affects everything, so always reset!) vs rgba()/hsla() (per-color control).

Gradients: createLinearGradient for straight-line transitions, createRadialGradient for circular transitions. Both use addColorStop().

Patterns: createPattern repeats a tile image to fill shapes.

Compositing: globalCompositeOperation controls how new shapes blend with existing content (26 modes!).

Lines: lineWidth, lineCap, lineJoin, setLineDash, and animated lineDashOffset.

Shadows: shadowColor, shadowBlur, shadowOffsetX/Y, used for glow, depth, and drop shadows.