Skip to content

Axis Scales — Log, Pow, and Symlog

dbt charts's default measure-axis scale is linear. When a metric spans several orders of magnitude — population counts, payload masses, request latencies — a linear scale compresses small values into an unreadable sliver near zero. Set scale.continuous.type on the measure axis to switch to a logarithmic, power, or symmetric-log scale instead.

type: log

axis_y.scale.continuous.type: log is first-class on line and area charts: dbt charts validates the authoring surface (see below) and lets Vega-Lite own tick placement natively (log-decade ticks, computed from the data — never a fixed tick count).

A log scale is undefined at and below zero, so it is rejected whenever the y-axis data contains a value that is 0 or negative — see ERR-LOG-SCALE-REQUIRES-POSITIVE-DATA in the error reference. If your data can include 0 or negative values, use type: symlog instead — it behaves like a log scale away from zero but stays defined through it.

source: examples_db
queries:
  populations:
    type: values
    columns: [year, population]
    values:
      - ["1800", 990000000]
      - ["1900", 1650000000]
      - ["1950", 2536000000]
      - ["2000", 6127000000]
      - ["2025", 8200000000]
charts:
  world_population_log:
    query: populations
    type: line
    title: World Population (log scale)
    x: year
    y: population
    style:
      axis_y:
        scale:
          continuous:
            type: log
rows:
  - world_population_log
18001900195020002025100M200M300M400M500M1G2G3G4G5G10GWorld Population (Log Scale) Data as of 14:52 UTC on 21 Aug 2026 made with dbt charts

log.base sets the log base (default: Vega-Lite's 10):

style:
  axis_y:
    scale:
      continuous:
        type: log
        log:
          base: 2

type: pow / type: sqrt / type: symlog

These scale types reach Vega-Lite the same way type: log does, but without a first-class tick story — dbt charts passes them straight through and does not validate or specialize tick placement for them the way it does for log. pow.exponent configures pow; symlog.constant configures symlog. Unlike log, their domains can include 0, so — verified — they don't hit the log-specific area-mark rendering issue below and need no explicit domain.

style:
  axis_y:
    scale:
      continuous:
        type: pow
        pow:
          exponent: 0.5

Tick cadence on a quantitative axis

Two fields under style.axis_x.ticks control how densely a quantitative axis is ticked. They answer different questions, and only one of them is exact.

ticks.count asks for a number of ticks. Vega-Lite treats it as a target and rounds to the nearest round-numbered ladder, so you get about this many:

style:
  axis_x:
    ticks:
      count: 4

ticks.step names the interval instead, and it is a floor Vega cannot go finer than — step: 1000 on a 0–4k axis ticks at exactly 0 / 1k / 2k / 3k / 4k:

style:
  axis_x:
    ticks:
      step: 1000

Reach for step over an explicit scale.values: [0, 1000, 2000, 3000, 4000] ladder. A values list freezes the axis against the data you had when you wrote it: the day a customer count passes 4,000 the ladder silently stops covering the data. step is a floor, not a list — Vega keeps choosing round numbers above it, and the axis keeps covering the range as it grows.

The two compose: count sets the target, step the floor.

On a temporal x-axis step means a multiple of a calendar grain and needs ticks.time_unit alongside it — see Time axes. On an ordinal or categorical x-axis the domain is discrete, so there is no tick interval to set — including a horizontal bar's axis_x, which is its category axis (the measure lives on axis_y). Authoring ticks.step on any of those raises rather than doing nothing.

Rules

A handful of authoring combinations are rejected at compile time rather than silently producing a misleading chart:

Rule Why
log.base requires type: log (same for pow.exponent/type: pow, symlog.constant/type: symlog) These params are meaningless without the matching scale type.
type: log + zero: true A log domain cannot include 0.
type: log on a bar chart A bar's length encodes magnitude from zero — meaningless on a log scale. Use type: symlog on the bar chart, or switch to line or area for a log scale.
type: log + axis_y.ticks.count A target tick count is meaningless on a log axis; Vega-Lite computes log-decade ticks natively.
axis_x.ticks.step without ticks.time_unit on a non-quantitative x-axis A bare step is a numeric tick interval; only a quantitative scale has one. Add ticks.time_unit on a temporal axis; on a discrete axis, remove it.

See the YAML Schema Reference for the full scale style field list.