Changing axis label size while using Plot

Hello,

How would I go about changing the font size of the axis labels in a Plot like so:

area = Plot.areaY(datasort, {
  x: "Date",
  y: "Count",
  fill: "Zone",
  order: "sum",
  reverse: true,
  inset: 0,
  title: "Zone"
}).plot({
  width,
  height: 900,
})

I know you can change the font size of Plot.text with fontSize:30 but this only works for marks and not the x and y axis labels.

Is there a way to do this without changing the entire html with something like:

html `<style>
text {
font-size: 22px;
}
</style>`

As that doesn’t work in my situation…

Plot 0.3 introduces a className option on top of the style option; hopefully this is enough to change whatever is necessary?

So I set a className in the Plot like so:

area = Plot.areaY(datasort, {
  x: "Date",
  y: "Count",
  className: "disco",
  fill: "Zone",
  order: "sum",
  reverse: true,
  inset: 0,
  title: "Zone"
}).plot({
  width,
  height: 900,
  style: {
    fontSize: 30,
  },
})

and then I use

html `<disco><style> text { font-size: 22px; } </style></disco>`

to change only the specific SVG element with that className?

So I couldn’t figure out how to use the className properly to set the font-size…

But I did figure out that if I just directly alter the attribute value with:

area.setAttribute("font-size", 30);

It will change the x and y text sizes.

Unfortunately, these attribute settings don’t carry over when you import the cell into another notebook so this doesn’t work for my intended uses.

Does anyone know a way to import the set attributes with the cell? Or a way to set the attribute so that it is imported as set?

If you call area.setAttribute in a different cell, then you’ll need to name, import, and execute that into your other notebook as well for it to take effect. Alternatively, you could bundle it all into a single cell. Something like

{
  let area = ...
  area.setAttribute(ā€œfont-sizeā€, 30);
  return area
}

Of course, that will set the global font-size for the whole figure. You might also inspect the SVG and use CSS selectors to target the text more specifically. Something like so:

{
  let p = Plot.plot({
    marks: [Plot.line(d3.range(0, 20, 0.1).map((t) => [t, Math.sin(t)]))],
    x: { label: "t" },
    y: { label: "y" },
    margin: 60
  });

  let sel = d3.select(p).selectAll("svg > g > text").style("font-size", "20px");

  return p;
}

Of course, that will be quite fragile and would depend on the exact structure of your output. Proper class names would be ideal.

@Fil As far as I can tell, the className option only applies at the top level, not to marks, axes, and such.

Yes. There is an older proposal to extend it to each of the marks and axes here: className option for plot, facets, axes and marks by Fil Ā· Pull Request #253 Ā· observablehq/plot Ā· GitHub

any new way to achieve this?

Yes, there is now a full fledged axis mark that allows you to format the text in all kinds of ways.

You can use the top-level style option to set the font size for the entire plot, including axis ticks and labels. For example:

Plot.plot({
  y: {label: "↑ y"},
  style: {fontSize: "16px"},
  marks: [Plot.lineX(d3.range(0, 20, 0.1), {y: Math.sin})]
})

Or equivalently:

Plot.plot({
  y: {label: "↑ y"},
  style: "font-size: 16px;",
  marks: [Plot.lineX(d3.range(0, 20, 0.1), {y: Math.sin})]
})

If you only want to affect the axes and not other marks, you can use the fontSize option on the axis marks, as @mcmcclur suggested.

Plot.plot({
  marks: [
    Plot.axisX({fontSize: 16}),
    Plot.axisY({fontSize: 16, label: "↑ y"}),
    Plot.lineX(d3.range(0, 20, 0.1), {y: Math.sin})
  ]
})