p5.js Beginner Article 6

Text & Typography

Render text, load custom fonts, measure string dimensions, and use type as a visual element.

⏱ 16 min read text fonts typography textSize textAlign

Basic text rendering

function draw() {
  background(20);
  fill(255);
  textSize(24);
  text('Hello, world!', 50, 100);
}

text(str, x, y) draws the string at position x, y. By default, x,y is the baseline-left of the first character.

Text style functions

textSize(32);         // font size in pixels
textStyle(BOLD);      // NORMAL, BOLD, ITALIC, BOLDITALIC
textFont('Georgia');  // any system font or loaded font
textLeading(32);      // line spacing for multi-line text

textAlign()

Control how x,y maps to the text’s position:

textAlign(LEFT, TOP);        // x is left edge, y is top
textAlign(CENTER, CENTER);   // x,y is the centre — most useful
textAlign(RIGHT, BASELINE);  // x is right edge, y is baseline (default)

// Example: centred label under a shape
function drawLabel(x, y, label) {
  fill(255);
  textAlign(CENTER, TOP);
  textSize(12);
  text(label, x, y + 8);
}

Multi-line text

text() with four arguments wraps text within a bounding box:

text('This is a long paragraph that will wrap inside the box.', x, y, w, h);
// Arguments: string, x, y, maxWidth, maxHeight

You can also use \n for manual line breaks:

text('Line one\nLine two\nLine three', 50, 100);

Measuring text

textWidth(str) returns the pixel width of a string at the current text settings:

textSize(20);
let w = textWidth('Hello');
// Useful for centering text or placing decorations relative to it

textAscent() and textDescent() return the height above and below the baseline.

Loading a custom font

Load a .ttf or .otf font file using loadFont() in preload():

let myFont;

function preload() {
  myFont = loadFont('fonts/SpaceMono-Regular.ttf');
}

function setup() {
  createCanvas(600, 200);
}

function draw() {
  background(20);
  textFont(myFont);
  textSize(48);
  fill(100, 200, 255);
  textAlign(CENTER, CENTER);
  text('Creative Coding', width / 2, height / 2);
}

Google Fonts offers hundreds of free fonts. Download the TTF from fonts.google.com and place it in your sketch folder.

Text as a visual element

Text becomes genuinely interesting when you treat letters as shapes:

Kinetic type — text follows the mouse

let message = 'CREATIVE';
let letters = [];

function setup() {
  createCanvas(800, 200);
  textSize(80);
  textFont('Impact');

  for (let i = 0; i < message.length; i++) {
    letters.push({
      ch: message[i],
      x:  80 + i * 88,
      y:  140,
      tx: 80 + i * 88,
      ty: 140
    });
  }
}

function draw() {
  background(15);
  noStroke();

  for (let l of letters) {
    // Repel from mouse
    let d = dist(mouseX, mouseY, l.tx, l.ty);
    if (d < 80) {
      let angle = atan2(l.ty - mouseY, l.tx - mouseX);
      l.x = l.tx + cos(angle) * map(d, 0, 80, 60, 0);
      l.y = l.ty + sin(angle) * map(d, 0, 80, 60, 0);
    } else {
      l.x = lerp(l.x, l.tx, 0.15);
      l.y = lerp(l.y, l.ty, 0.15);
    }

    fill(map(l.x - l.tx, -60, 60, 255, 100), 150, 255);
    textAlign(CENTER, CENTER);
    text(l.ch, l.x, l.y);
  }
}

Text on a path (circular)

function setup() {
  createCanvas(400, 400);
  noLoop();
}

function draw() {
  background(20);
  translate(width / 2, height / 2);

  let message = 'AROUND THE CIRCLE • AROUND THE CIRCLE • ';
  let radius  = 150;
  textSize(16);
  fill(200, 150, 255);
  noStroke();

  for (let i = 0; i < message.length; i++) {
    let angle = TWO_PI / message.length * i - HALF_PI;
    push();
    translate(cos(angle) * radius, sin(angle) * radius);
    rotate(angle + HALF_PI);
    textAlign(CENTER, CENTER);
    text(message[i], 0, 0);
    pop();
  }
}

Pixel-sampling text

Render text to a graphics buffer and use its pixels to place shapes:

let pg;

function setup() {
  createCanvas(600, 200);
  pg = createGraphics(600, 200);
  pg.textSize(120);
  pg.textAlign(CENTER, CENTER);
  pg.fill(255);
  pg.text('CODE', width / 2, height / 2);
  pg.loadPixels();
}

function draw() {
  background(15);
  noStroke();

  for (let x = 0; x < pg.width; x += 6) {
    for (let y = 0; y < pg.height; y += 6) {
      let idx = (x + y * pg.width) * 4;
      let bright = pg.pixels[idx];
      if (bright > 128) {
        fill(map(x, 0, width, 100, 255), 150, map(y, 0, height, 255, 100));
        circle(x, y, 5);
      }
    }
  }
}

Key takeaways

  • text(str, x, y) draws text; textSize(), textStyle(), textFont() control appearance
  • textAlign(horizontal, vertical) changes how x,y maps to the text anchor
  • textWidth() measures a string’s rendered width in pixels
  • Load custom fonts with loadFont() inside preload()
  • text() with four arguments wraps text in a bounding box
  • Treat letters as shapes: render to a graphics buffer and sample pixels to create dot-matrix text effects