Pick the form before the color

Name the data's job, let it pick the chart type, then choose colors.

From dataviz, references/choosing-a-form.md.

The job picks the form

Pick a job; the same data redraws to answer it.

One pie for every jobBad
No
Bar, sortedGood
// 1. Is it even a chart?
function pickForm(data, job) {
  if (data.values === 1)      return "stat tile";
  if (data.isRatioToLimit)    return "meter";
  if (data.classes > 7)       return "table + chart";
  return FORM_BY_JOB[job];      // 2. The job picks the form
}

// 3. The form's job picks the color, last.
const FORM_BY_JOB = {
  magnitude:   { form: "bar, sorted",             color: "sequential, one hue" },
  trend:       { form: "line (area if single)",   color: "one hue" },
  identity:    { form: "multi-line / grouped bar", color: "categorical, fixed order" },
  emphasis:    { form: "one line + gray context",  color: "1 hue + gray" },
  polarity:    { form: "diverging bar",            color: "diverging, gray midpoint" },
  partToWhole: { form: "stacked bar, horizontal",  color: "categorical" },
  likert:      { form: "diverging stacked bar",    color: "diverging" },
  beforeAfter: { form: "dumbbell",                 color: "1 hue, 2 shades" },
};

Is it even a chart?

Drag past $5.0M, or past 100% of quota.

One-bar bar chartBad
Stat tileGood

Revenue, Q3

$4.2M

+12% vs Q2

value + delta + sparkline
<!-- one value: a stat tile, not a one-bar bar chart -->
<div class="tile">
  <p class="label">Revenue, Q3</p>
  <p class="value">$4.2M</p>
  <p class="delta" data-dir="up"><span aria-hidden="true">▲</span> +12% vs Q2</p>
</div>

<!-- ratio to a limit: a meter, not a 2-slice pie. Track runs past 100%. -->
<div class="meter" role="meter" aria-valuemin="0" aria-valuemax="125" aria-valuenow="62">
  <div class="fill"></div>   <!-- transform: scaleX(0.496); origin left -->
  <div class="limit"></div>  <!-- left: 80% (100 of 125) -->
</div>

Too many classes for color

Slide past 7 categories.

One hue per classBad
7 max, then a tableGood
const MAX_COLORED = 7;

function partToWhole(classes) {
  if (classes.length <= MAX_COLORED) return { bar: classes, table: null };
  const sorted = [...classes].sort((a, b) => b.share - a.share);
  const top = sorted.slice(0, MAX_COLORED - 1);
  const rest = sorted.slice(top.length);
  const other = { name: `Other (${rest.length})`, share: sum(rest), color: "gray" };
  return { bar: [...top, other], table: sorted };
}

Why it matters, pros and cons

Why it matters

The question narrows the form to one or two options. Color then serves that form, not a mood.

Pros

  • Answers the reader's question at a glance
  • Color keeps one job across charts
  • One number becomes a tile, not a chart

Cons

  • Several questions need several charts, not one
  • Pies still work for ≤6 clearly different shares
  • Throwaway exploration can skip it