Default CSS as a contract

There were some very recent CSS changes that noticably altered the appearance of some of my notebooks. These changes made me wonder:

  • Can/should we consider Observable’s default CSS as part of the API?
  • If not, what would be the alternative? Do I have to detect and forcibly remove the default styles and replace them with my own to guarantee that the appearance of my notebooks will remain unchanged?

The basic answer is yes, we treat CSS in the notebook as an API and go to great lengths to never make changes that would change notebook output. For example, I’d love to refactor a particular CSS variable for our monospace font stack that’s used in the notebook CSS, but since notebooks might reference it and rely on it, we choose not to.

But, this being the web, we can’t control everything. Hence the most recent change: we were using the lovely Iowan Old Style system font on macOS, but the most recent update, Catalina, broke access to that font from Chrome, leaving Macs with Baskerville (a decidedly non-lovely font, with vastly different metrics). So we decided to bail out of system fonts entirely and use Source Serif Pro.

The upshot of that change is that the body font of notebooks is now more guaranteed than it was before, because it won’t vary between operating systems and browsers.

It was unfortunate that we needed to do that because of a buggy OS release, but that – and other changes we make to notebook CSS – have fit more the category of bugfix than modification.

So short answer: yes, we try to have almost no change in notebook CSS. We change notebook-affecting styles when platforms demand it, or it’s a bugfix.

Caveat, though, that CSS that narrowly targets internals of the notebook inspector, all of which is scoped with prefixed classes like .observablehq--string-expand, are not part of what we think of as the API. The inspector lives alongside user code as a matter of necessity, but is not user code, and is liable to change over time as we improve its functionality. I’d recommend not using any of those internal prefixed classes, and not modifying the inspector UI, as a result. Guaranteeing perfect forward compatibility there would just sacrifice too much product progress for too little author usefulness.


Do you see the possibility of providing a one-time dump/build of the worker styles prior the latest updates? My iframe instance hasn’t lived long enough to fetch it from there, and afaik is unable to index notebooks.

Edit: Nevermind, I managed to salvage them from*/*.


A toggle tool is now available via

@tom By the way, --serif is no longer defined.

Friendly reminder that --serif is still missing. It was previously defined as

--serif: "Iowan Old Style","Apple Garamond",Baskerville,"Palatino Linotype","Times New Roman","Droid Serif",Times,"Source Serif Pro",serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";

There’s also a prefetch error for the webfont in Chrome Already reported in small error in the console.

@tom The custom property --serif is still missing. This runs counter to what you claimed above. Is there a technical reason why it was removed?