Basics

Drawing your first shapes with fillRect, strokeRect, and clearRect.

Lesson 1 of 10

In the Foundation lesson you learned what Canvas is, how the coordinate system works, and what the ctx object does. Now it’s time to draw. This lesson covers the three rectangle methods, the simplest way to put shapes on screen, plus colors, draw order, and practical examples.

fillRect: Drawing Filled Rectangles

The simplest drawing command is fillRect(x, y, width, height). It fills a rectangle with the current fillStyle color. You’ll also see ctx.fillText(text, x, y) used in many demos to add labels; it draws a string at the given position using the current ctx.font and fillStyle.

fillRect parameters:

  ctx.fillRect(x, y, width, height)
               │  │    │       │
               │  │    │       └── how tall (in pixels)
               │  │    └────────── how wide (in pixels)
               │  └─────────────── Y of the top-left corner
               └────────────────── X of the top-left corner

  Example: ctx.fillRect(50, 30, 200, 100)

  (50,30) ─────────── 200px ──────────┐
     │                               │
    100px                            │
     │                               │
     └───────────────────────────────┘
                               (250,130)
fillRect(x, y, width, height) paused

Try this: Change the first rectangle’s color to '#ff2d7b' and make its width 300. Hit Run. Notice how the second rectangle draws on top, and its rgba transparency lets the first one show through.

fillStyle: Color Formats Explained

Before drawing, you set the color with ctx.fillStyle. Canvas accepts many color formats. Here are the most common ones:

Color Formats Visual Reference paused

Which format should I use? For beginners, named colors (like ‘red’, ‘dodgerblue’) are easiest. For precise control, use hex codes (‘#00e5ff’). When you need transparency, use rgba. The fillStyle stays set until you change it; it’s like dipping your brush in paint.

strokeRect: Outlined Rectangles

strokeRect(x, y, width, height) draws just the outline of a rectangle, without filling the inside. You control the outline color with strokeStyle, thickness with lineWidth, and pattern with setLineDash([dashLength, gapLength]) for dashed or dotted lines.

strokeRect with Different Line Widths paused

How lineWidth works: The stroke is centered on the edge of the rectangle. A lineWidth of 10 means 5 pixels inside the edge and 5 pixels outside. This is why thick outlines can look like they’re “growing” the rectangle.

  lineWidth = 10

     5px outside
  ──────████████████──────
        █          █
        █  inside  █    5px inside
        █          █
  ──────████████████──────
     5px outside

  The stroke sits ON the boundary line,
  half in, half out.

clearRect: Erasing Pixels

clearRect(x, y, width, height) makes a rectangular area fully transparent. It erases whatever was drawn there. Think of it as a rectangular eraser.

clearRect: Cutting Holes paused

The most common use of clearRect is clearing the entire canvas before redrawing (for animation):

  // Clear everything:
  ctx.clearRect(0, 0, canvas.width, canvas.height);

Draw Order: What Happens When Shapes Overlap

Canvas works like painting on paper with opaque paint: the last thing you draw covers everything before it. This is called the painter’s algorithm. Just like a real painter, the newest layer goes on top.

Draw Order Matters! paused

Key insight: Canvas has no “layers” and no “z-index.” If you want shape A behind shape B, draw A first. If you want to change the order later, you have to clear the canvas and redraw everything in the new order. This is why animation always follows the pattern: clear -> draw everything -> repeat.

Practical Example: Drawing a Robot

Let’s use everything we’ve learned to draw something fun: a robot made entirely from rectangles!

Robot Made of Rectangles paused

Practical Example: A Simple House

Another example using mostly rectangles. Notice how draw order matters for the windows and door (they need to be drawn after the wall). The roof uses beginPath(), moveTo(), lineTo(), and fill() to draw a triangle, and the moon uses arc() to draw a circle. These are path commands covered fully in Lesson 2.

House with Rectangles (and one triangle) paused

Putting It All Together: Night Cityscape

Here’s a more complex scene showing how many simple rectangles combine into something impressive. Study the code; it’s all fillRect, strokeRect, and clearRect!

Night Cityscape: Only Rectangles! paused

Challenges

Try these exercises to practice what you’ve learned. You can open your browser’s console (F12) and create your own canvas, or modify the demo code above by looking at the patterns.

Challenge 1: Traffic Light

  Draw a traffic light:
  - A tall dark rectangle for the housing
  - Three circles (red, yellow, green) stacked vertically
  - A pole (thin rectangle) below

  Hint: You know fillRect for the housing and pole.
  For circles, use:
    ctx.beginPath();
    ctx.arc(x, y, radius, 0, Math.PI * 2);
    ctx.fill();
  (We'll cover arcs fully in Lesson 2!)

Challenge 2: Checkerboard

  Draw an 8x8 checkerboard pattern:
  - Use a nested for loop (row and column)
  - Alternate colors based on (row + col) % 2
  - Each square should be 40x40 pixels

  Hint:
    for (var row = 0; row < 8; row++) {
      for (var col = 0; col < 8; col++) {
        if ((row + col) % 2 === 0) {
          ctx.fillStyle = '#c8c8d0';
        } else {
          ctx.fillStyle = '#1a1a2a';
        }
        ctx.fillRect(col * 40, row * 40, 40, 40);
      }
    }

Challenge 3: Bar Chart

  Draw a bar chart from an array of data:
    var data = [80, 150, 60, 200, 120];

  - Each bar is 50px wide with 20px gaps
  - Bar height = the data value
  - Bars grow UP from the bottom (y = canvasHeight - value)
  - Different color for each bar
  - Labels underneath each bar

  This is a common real-world use of Canvas!

What you learned in this lesson:

  Concept              How to do it
  ──────────────────── ───────────────────────────────
  Set fill color       ctx.fillStyle = '#ff0000'
  Set stroke color     ctx.strokeStyle = '#00ff00'
  Fill a rectangle     ctx.fillRect(x, y, w, h)
  Outline a rectangle  ctx.strokeRect(x, y, w, h)
  Erase an area        ctx.clearRect(x, y, w, h)
  Set line thickness   ctx.lineWidth = 5
  Make dashed lines    ctx.setLineDash([dash, gap])

  Key ideas:
  - (0,0) is top-left. Y goes DOWN.
  - Canvas size != CSS size. Use HTML attributes.
  - Later draws cover earlier draws (painter's algorithm).
  - fillStyle/strokeStyle persist until you change them.