Skip to content

Data Visualization with Observable JS

Jesse Kaczmarski edited this page Apr 19, 2024 · 6 revisions

The API index for Observable JS is here: https://observablehq.com/plot/api

Figure Width and Alignment

CSS

We would like Observable generated figures centered like images are. According to https://www.w3schools.com/howto/howto_css_image_center.asp:

Note that [the image] cannot be centered if the width is set to 100% (full-width).

You can view the CSS styling using the Inspector function of a web browser. For ojs figures, there an "extra" config:

.quarto-figure>figure {
   width: 100%;
   margin-bottom: 0;
}

Changes to the width applied in style.css, _quarto.yml, and in the header of the file have no effect. That CSS style seems to take precedence, but why?

Observable

On the other hand, https://observablehq.com/plot/features/plots#layout-options says "On Observable, the width can be set to the standard width to make responsive plots" which means that the figures resize as the window size changes (i.e. for mobile devices etc). Dynamic figure responsiveness is very valuable.

Width can be changed in the ojs code blocks for Plot.plot, and that does allow the style changes made to CSS via the various methods listed above to have an effect. To maintain responsiveness, can use code Math.max(width, 550) (gotten from Observable forum). However, the legend stayed on the left when the figure and caption moved over which looked dumb.

So maybe figures must have width=100% to be responsive, but that results in them being left justified. We are at an impasse.

Solution

Fixed by adding the option width: width to every plot. That tells Observable JS to make the width of the chart equal to the width of the display block.

Centering legends for Figures

Charts (plots) built with Observable JS have default styling applied to them. Not all styling/placement elements can be modified with options in the Plot.plot({}) call. In particular, we found that wrapping the plots in a Quarto figure element was ideal for centering the charts along with the above full-width plot option.

We noticed through element inspection of the built web book that along the render chain, Observable applies the following CSS class to the legend area of a plot .plot-d6a7b5-swatches-wrap. By default the wrapping behavior justifies to the left.

We center the legends on every chart by adding custom CSS styling to change the wrapping behavior of the legend element,

.plot-d6a7b5-swatches-wrap {
    justify-content: center;
}