🏠 back to Observable

Bug report: local anchor link

My cell contains:

md`should generally be [clipped](#map) to that triangle`

The link sends me to a worker-blob url (https://static.observableusercontent.com/worker/worker.41429f6ab0e6ad622d896965f31e125c7a51392b3ce5e5da530ef441930ce3ce.html#map)

Yes, I’m afraid that because the cell output is safely contained in a sandboxed frame, it’s a little more difficult than normal to link directly to other parts of the page.

But it can be done!

You need to target your link to the parent frame, and use the full URL of the published notebook, like so:

html`<a target="_parent" href="https://beta.observablehq.com/@jashkenas/my-cool-notebook#map">clipped</a>`

I know, but I’d still file it as a bug :slight_smile:

This has been fixed! Thanks for the bug report.

1 Like

I can’t seem to get local anchor links to work in my notebooks. Am I doing something wrong here?

[Not sure if I should have made a new thread or not, but this seemed like a relevant place to ask…]

Hey Bryan - anchor links refer to named cells, so instead of a cell like

md`<a name="anchorplace"></a><sup>1</sup> **The link should lead here!**`

You’ll want to do:

anchorplace = md`<sup>1</sup> **The link should lead here!**`

The distinction is that the output of your cell is actually a separate page - it’s an iframe under the code. Naming the cell like ↑ creates an id on the top frame instead, so it’s linkable from other cells.

1 Like

Thanks tom! Looks like that does the trick. It’s so basic that I must have missed this in the tutorials…

No problem! It’s a pretty subtle difference, and it’s totally reasonable to expect the former to work given typical web pages - this is one of those parts where Observable does work a little differently.

1 Like

Any plans to fix this or provide a workaround? The workaround postet doesn’t seem to work anymore, and having to split every paragraph into it’s own cell seems a bit cumbersome and breaks text flow.

I’m writing an paper and have references in the text and an auto generated bibliography at the bottom. The ability to jump from a reference to the point where it’s used would be pretty sweet.

Would it be possible to use JavaScript (as in https://stackoverflow.com/a/28607479/7351594) to simulate local anchors?

For example, accessing https://observablehq.com/@observablehq/downloading-and-embedding-notebooks#writing-values-from-javascript would scroll to “Writing values from JavaScript”.

Sure, I believe @mike’s “TOC” notebook uses this technique:

Edit this doesn’t address the question which is about having the notebook automatically navigate to the anchor on page load.

Hmmm, I think it’s different, since it works inside the same iframe, but: https://observablehq.com/@mbostock/toc#hooray doesn’t scroll until the Hooray title

Oh, I see what you mean.

Sorry about misinterpreting your question!

1 Like

Yup, possible since this change was made a while back. Here’s a rough example:

Note that this doesn’t handle finer details like user scrolling or changing hashes. (Btw: the notebook is “untitled” because Observable expects the <h1> in the first cell.)

1 Like

I think it’s not what I meant either, sorry for not being clear :slight_smile: It’s not about being able to access the hash from the cells.

What I’m wondering is if the pages served by Observable could include some JavaScript (or any other solution) to simulate the natural way of automatically scrolling to the anchor if the URL contains something after #, ie if I browse https://observablehq.com/@mbostock/toc#hooray, I hope to see the Hooray title on top of the page. The question is for the Observable maintainers as a feature request.

Note that it already works in some cases. Eg, https://observablehq.com/@observablehq/introduction-to-data#inline scrolls to “Inline” title. I imagine that it’s due to the internal link created in the first cell: [inline](#inline)

My question is we could have the same behavior for all the titles, in any notebook, without the need to insert an internal link in one of the cells.

That is exactly what my example does. :wink:

Edit: Note however that the test interval may be too short for you, so that the notebook hasn’t fully loaded when the scroll is finally performed.

OK :ok_hand: :slight_smile:

Sorry, I didn’t notice it, because it seems to work only on first access to the URL (I had selected the URL again and pressed Enter, and it didn’t scroll to the title).

And yes, the question is if this kind of code could be included in the Observable pages by default. I understand it might be difficult, because the final height of the cells is not known before rendering…

I’ve exanded the example to handle element tracking and user input (code moved to the end of the notebook). However, I can absolutely not recommend this solution for the following reasons:

  • window.scrollTo() cannot be used, only node.scrollIntoView(). This makes it impossible to account for Observable’s sticky top bar, which will often cover the target element. Edit: As a workaround, an empty, absolute positioned div is used as scroll target.
  • Interactions outside the iframe are not registered. If e.g. the user scrolls while the pointer is over an editor area, or left or right of the iframe, the interaction cannot be tracked.

This is how the implementation works:

  • Query the element ID repeatedly until the target has been found.
  • Scroll the target element into view at regular intervals (250ms by default).
  • Abort searching and tracking as soon as a user interaction has been registered.
2 Likes