In-page Anchors

Hey @jerry.nummi,

For your use case of the sub navigation. Something I do is use the HTMLSerializer to automatically add id's to my H2's from my rich texts. Like I do here:

  if (type === Elements.heading2) {
    var id = element.text.replace(/\W+/g, '-').toLowerCase();
    return '<h2 id="' + id + '">' + children.join('') + '</h2>';
  }

Then I build a component that looks at the Slices on the current page, takes any H2 titles and creates a link to these. This example is in Vue, but you can easily recreate it in whatever technology:

<template>
    <section v-if="sections.length" class="table-of-content">
        <h5>On this page</h5>
        <ul>
            <li v-for="([anchor, text], index) in sections" :key="`section-${index}`">
                <a :href="`#${anchor}`">
                    {{ text }}
                </a>
            </li>
        </ul>
    </section>
</template>

<script>
export default {
    name: 'toc-slice',
    props: {
		slices: {
			type: Array,
			required: true
		}
    },
    computed: {
        sections: function () {
            const buildAnchor = (text) => text.replace(/\W+/g, '-').toLowerCase()
            return this.slices
                .map((slice) => {
                    if(!(slice.slice_type === 'title' && slice.primary.title)) return;
                    const heading = slice.primary.title.find(elem => elem.type === 'heading2');
                    if(heading) return [buildAnchor(heading.text), heading.text];
                })
                .filter(e => !!e)
        }
    }
}
</script>

Here's the full file.

Let me know if you have any questions about this.

Thanks.

3 Likes