Modal/Popup - Help And Code Review


I’ve searched around, but couldn’t find any notebooks for a modal/popup, so I’ve tried my hand at patching together one:

I would appreciate any suggestions for good practice regarding this.

I’m also having some trouble with the position of modal and modal-overlay classes. If I set them to “fixed”, it works standalone (from the tar-ball). On Observable, however, it doesn’t work and the modal divs appear somewhere below all the notebook cells (but it does seem to work with position absolute). Any ideas on how to fix this?

Thank you!

1 Like

Hi, and thanks for sharing your work!

Observable’s compositing can be a bit confusing, so I’ll try to clear up some aspects:

  1. Cell contents and editors actually live in separate windows: The cell contents (or rather, your actual notebook) lives inside an iframe (at a different domain) that is placed on the bottom layer of the page. The iframe stretches across the whole height, even outside the parent viewport.
  2. The individual editors live on, inside a container that covers the iframe.
  3. Each cell editor and output wrapper is positioned absolutely. Whenever a cell or editor changes its height, Observable will reposition the following containers (both editors and cells) so that they all line up nicely without overlaps.

In the following screenshot I’ve made the editor windows transparent (by editing the CSS in the dev tools):

Onward to the positioning problem:

  • With position: fixed you position an element relative to its viewport. This has no effect during scrolling because the iframe is always displayed at full height (i.e., there’s no scrolling inside the iframe). The same problem applies to position: sticky.
  • With position: absolute the element is positioned relative to its closest positioned ancestor. For cells this is the wrapper around each cell that aligns its content with the editor windows.

In summary, modals in Observable are hard due to its security model. However, ther are some hacks you can try. E.g., the following notebook is an attempt at sticky positioning through the use of IntersectionObserver:


Remember that this problem is only when you’re running it on Observable, if you embed your chart your modal will work fine!

1 Like

thank you so much for the detailed reply! makes a few points clear, i’ve noticed the iframe but was somehow oblivious that it doesn’t come from the same domain.

perhaps i should define a bit more the scope of my endeavour: was hoping to display this “modal” (popup) on top of the svg only - having it as a “true” modal that obscures the viewport would be a bonus. any suggestions on how to achieve this, that would work both on Observable and standalone?

also a question: is there any way of “naming” a cell containing a style definition? in the exported project, i’m using this code to only include the chart:

const main = runtime.module(define, name => {
  if (name == 'chart') {
    return new Inspector(document.body)

but couldn’t find a way to include the styles defined as

html`<style>aClass {


@radames thanks, i’ve tested it with the exported/standalone project, good to know it works with the embed too :slight_smile:

Unfortunately this is not possible within Observable’s editor UI.

I’d suggest that you pick one of your cells as your new “body” and output everything in there (basically like you’re doing now). In addition you could check for the editor with


and change the target element for your modal accordingly.

Simply name the cell like any other:

myStyle = html`<style>aClass {