🏠 back to Observable

Old and new cycling maps

Around 2004, I started experimenting with the then new Google Maps API to display my bike rides. Sadly, I lost a lot of the data, but it turned up on the Internet Wayback machine. In part, inspired by this, I decided to convert that old page into an Observable page. Here’s the result:

That page also contains a bit of discussion surrounding my experience with encoded polylines.

In addition, I figured I should display some new rides as well:


These are great, Mark. Nice riding, btw.

1 Like

I recently embedded the new version of this map into a web page and thought I’d mention that here. I think it’s a nice example of illustrating how much we can change the appearance using a little CSS:

1 Like

Woah, Mark! These views are impressive! Looks like there’s a bit more at play than CSS? You also present elevation views for different layers. Sorry for being a bit of a ‘dult’, but are you running the CSS via Observable or via the embedded map separately?

Also -THANKS for sharing :slight_smile: In addition by being inspired by your coding and mathematics prowess, I am also inspired by your cycling!

1 Like

Thanks! The elevation view you refer to is exactly the elevation_chart_container that appears right under the map once you choose a route to display. The CSS that forces the map to fill the page and the elevation chart to appear on the map is all specified in the style element in the page.

1 Like

Thanks again Mark!

While folks can easily dig in, please allow me to articulate here on the forum my understanding (mostly to learn myself, and sorry if this is crowding space!).

The CSS contributions to which you are pointing our attention are those that affect the map’s rendering to a stand-alone HTML page view. This CSS is applied within the page source (i.e. visible when clicking ‘view source’). It does not come via the notebook. This is the CSS style element that responds to it:

    <style media="screen">
      body {
        padding: 0;
        margin: 0;
      html, body, #all, #observablehq-map_container {
        height: 100%;
        width: 100vw;
      #all {
        position: relative
      #observablehq-map_container, #observablehq-elevation_chart_container {
        position: absolute
      #observablehq-elevation_chart_container {
        z-index: 1000;
        bottom: 0

Without this adjustment, the map would render like this:


… So definitely this full screen view is an improvement :slight_smile:

Within the notebook, however, you have further CSS definitions: These definitions allow you to control the look and feel of the map icons. [I initially thought that you were calling attention to these styling elements (rather than the embed code); apologies for not being clear on this earlier!]

What your embed code teaches is that you are you are able to separate out how you control the map rendering within Observable and without it. The way you construct your map <div> container within the notebook is the ‘secret sauce’:

map_container = {
  let container = d3
    .style("width", "100%")
    .style("height", h);
  yield container.node();

… If I am reading this correctly, what this does is to tell the map always to fill the full width of the <div> it which it lives. This bit of CSS in the container’s construction is important, and it does carry into the embedded notebook. Your in-page style definitions simply ‘elaborate’ on this, so to speak, by asking also that your height extends 100% so that you get a full page map view.

I think I am getting it?

…Within your map are so many smooth and beautiful features, including the ‘select’ and ‘zoom to’ dimensions. These are not controlled by CSS. (Lots to learn here, thanks for sharing).

I really enjoy seeing this and learning! Thanks for your time and for all the examples. Apologies that I am slow to understand. :frowning: More reading ahead! [I’ve faltered lots before on getting maps to embed and still look nice, so I’m very interested] :slight_smile:

Thanks again!

Well, there is one other important element in the embedding script in the Javascript file - the last line, in particular

main.redefine('h', `${window.innerHeight}px`)

The parameter h defines the height of the map in the Observable notebook, so this line forces the map to fill the window from top to bottom. As written, the height is not responsive to a change in window size. It would be easy to include a window.onresize function, but I wasn’t too worried about that.

Yes - this is generally my approach. I view the Observable notebook as a great place to write literate Javascript code; I rarely worry about layout there. In fact, the layout in the notebook should be linear, in my view. Layout and other presentation aspects for a fully developed visualization belong in HTML/CSS for a webpage.

I would love to take credit for all that but those are pretty standard Leaflet tools

Thanks again!

1 Like