Color Encoding
encodeColor(options)
Map a nominal or ordinal field to point fills, line-series strokes, area fills,
bar fills, rect fills, or arc-sector fills. Ordinal fields may contain ordered numeric categories such as
engine cylinder counts. Quantitative or temporal point and rect fields use continuous color
scales; point fields also support discretized color. Aggregate bars additionally support one aggregate quantitative
color value per final rectangle. Line and categorical bar materializers may use
the field for grouping. Area color must match an existing encodeGroup field.
| Mode | Supported marks | Field types | Important options | | — | — | — | — | | Categorical | point, line, area, bar, rect, arc | point/line/area/bar/rect/arc: nominal, ordinal | bar/area layout; arc overlay; palette and ordinal scale | | Continuous | point, aggregate bar, rect | point/rect: quantitative, temporal; aggregate bar: quantitative | sequential scale; aggregate required for a different bar measure | | Discretized continuous | point | point: quantitative | quantize, quantile, or threshold scale |
| Option | Type | Default |
|---|---|---|
field |
non-empty string | required |
target |
point, line, area, bar, rect, or arc mark ID | current mark |
fieldType |
"nominal", "ordinal", "quantitative", or "temporal" |
"nominal" |
aggregate |
aggregate operation; quantitative aggregate bars only | matching measure aggregate |
layout |
"stack", "fill", "group", "overlay", or "diverging" |
mark policy |
palette |
palette name or { name, count?, extent? }; shorthand for scale.palette |
omitted |
scale.id |
scale ID | "color" |
scale.type |
"ordinal" |
"ordinal" |
scale.domain |
"auto" or category array |
"auto" |
scale.range |
"auto", color array, or palette descriptor |
"auto" |
scale.palette |
palette name or { name, count?, extent? } |
omitted |
program.encodeColor({
field: "Origin",
scale: { palette: "tableau10" }
});
Top-level palette is a shorthand for scale.palette, and scale.palette is the
concise form of scale.range: { palette: "tableau10" }. Provide only one of these
forms. Automatic domains preserve first-appearance order.
Use fieldType: "ordinal" when the values are ordered categories rather than
continuous magnitudes. They still receive discrete palette colors and legend
entries:
program.encodeColor({
field: "Cylinders",
fieldType: "ordinal",
scale: { palette: "reds" }
});
Calling encodeColor again for the same target replaces the categorical field.
Without scale.id, the current color scale is reused and its domain, marks,
and existing legend are recomputed. An explicit new ID retains the previous
named scale. Inferred legend titles follow the new field; explicit titles and
legend appearance remain unchanged.
Named palettes use a frozen 68-name vocabulary. Categorical palettes keep their
native order; count selects or deterministically cycles colors. Continuous,
diverging, and cyclical palettes used for ordinal mappings are sampled to the
domain size unless count is supplied. On a sequential scale, count must be
at least 2 and controls the concrete gradient-stop count. Non-categorical
palettes also accept an optional two-value extent within [0, 1].
program.encodeColor({
field: "Origin",
scale: { palette: { name: "set2", count: 3 } }
});
See continuous color scales for the complete vocabulary.
For an ordinal-category mean bar, layout: "group" is the default. It keeps
the measure stack null, invokes encodeXOffset for vertical bars or
encodeYOffset for horizontal bars, and recomputes the measure domain from
zero and one mean per category/color cell. Negative and positive bars therefore
extend in opposite directions from the same zero baseline. Color and offset
scales are fully resolved, and concrete rects use the implicit 0.72 band width immediately.
groupedBars.encodeColor({
field: "sex",
layout: "group",
scale: { palette: "tableau10" }
});
Calling grouped color again with a new categorical field atomically updates color and the directional offset to one matching first-appearance domain. Existing legends are rematerialized; inferred titles follow the field while explicit titles and styles remain unchanged.
On a complete histogram, encodeColor rematerializes each non-empty bin as
zero-stacked category rects. Stack and fill order follow the resolved color
domain. The y scale continues to use each bin’s total count, and an explicit
domain must contain every observed category.
histogram.encodeColor({
field: "Origin",
layout: "stack",
scale: {
domain: ["USA", "Europe", "Japan"],
palette: "tableau10"
}
});
Histogram color defaults to stack. fill normalizes every non-negative bin
partition to one and uses [0, 1] as the automatic y domain. group places
series side by side within each bin, overlay draws them in color-domain order
without changing opacity, and diverging accumulates positive and negative
values independently around zero. Ordinal aggregate bars support the same five
values; their group and overlay layouts use zero as each rectangle’s start
endpoint and reject explicit measure domains that exclude zero. Call
encodeBarWidth after color only when the implicit 0.72 width is not desired.
histogram.encodeColor({ field: "Origin", layout: "fill" });
On an area mark, color never creates grouping implicitly. Author grouping
directly or through encodeDensity({ groupBy }), then encode that same field:
densityArea.encodeColor({
field: "Origin",
layout: "overlay",
scale: { palette: "tableau10" }
});
Area layouts support stack, fill, overlay, and diverging; group is
bar-only. Each existing path receives the resolved color for its group. Path order,
color domain order, and later legend order share the same ordered categories;
Canvas and shared-scale changes rematerialize every affected area fill.
Once a color layout exists, changing it to another layout is rejected until a
future companion-cleanup contract is implemented; the earlier program remains
unchanged.
Continuous aggregate-bar color
For an aggregate bar, continuous color is computed at the same final category
grain as the rectangle. When the color field matches the quantitative measure,
omitting aggregate inherits that measure aggregate:
bars
.encodeY({ field: "population", aggregate: "sum", stack: null })
.encodeColor({
field: "population",
fieldType: "quantitative",
scale: { type: "sequential", palette: "viridis" }
});
If color uses a different field, its aggregate is required because multiple source rows cannot be chosen arbitrarily for one final rectangle:
bars.encodeColor({
field: "lifeExpectancy",
fieldType: "quantitative",
aggregate: "mean",
scale: { type: "sequential", palette: "viridis" }
});
The resolved color domain contains the per-rectangle aggregate values.
createLegend({ channels: ["color"] }) creates a gradient legend, and
editScale({ id: "color", reverse: true }) rematerializes both bar fills and
the gradient without changing geometry. Continuous bar color rejects
layout; histogram, ranged-bar, line-path, and area-path continuous color are
not part of this contract.