<div class="anchor-links-container">
    <nav class="anchor-links" role="navigation" aria-labelledby="anchor-links-title-label" aria-expanded="true" data-gumshoe-header data-scroll-header>
        <div class="anchor-links-title">
            <a href="#" class="anchor-links-title-link" aria-controls="page-content-navigation">
                <i class="uod-icons uod-icons-menu anchor-links-title-menu-icon" role="presentation"></i>
                <span id="anchor-links-title-label" class="anchor-links-title-label">On this page</span>
            </a>
            <a href="#" class="anchor-links-title-close" aria-label="Close Page Content Navigation">
                <i class="uod-icons uod-icons-cross anchor-links-title-close-icon"></i>
            </a>
        </div>
        <div class="anchor-links-list-container">
            <ul id="page-content-navigation" class="anchor-links-list" data-gumshoe>
                <li class="anchor-links-list-item">
                    <a href="#course-description" class="anchor-links-list-item-link" data-scroll>Course description</a>
                </li>
                <li class="anchor-links-list-item">
                    <a href="#what-will-you-study" class="anchor-links-list-item-link" data-scroll>What will you study</a>
                </li>
                <li class="anchor-links-list-item">
                    <a href="#how-will-you-learn" class="anchor-links-list-item-link" data-scroll>How will you learn</a>
                </li>
                <li class="anchor-links-list-item">
                    <a href="#entry-requirements" class="anchor-links-list-item-link" data-scroll>Entry requirements</a>
                </li>
                <li class="anchor-links-list-item">
                    <a href="#fees-and-funding" class="anchor-links-list-item-link" data-scroll>Fees and funding</a>
                </li>
                <li class="anchor-links-list-item">
                    <a href="#how-to-apply" class="anchor-links-list-item-link" data-scroll>How to apply</a>
                </li>
                <li class="anchor-links-list-item">
                    <a href="#careers" class="anchor-links-list-item-link" data-scroll>Careers</a>
                </li>
            </ul>
        </div>
    </nav>
</div>
<div class="anchor-links-container">
    <nav class="anchor-links" role="navigation" aria-labelledby="anchor-links-title-label" aria-expanded="true" data-gumshoe-header data-scroll-header>
        <div class="anchor-links-title">
            <a href="#" class="anchor-links-title-link" aria-controls="page-content-navigation">
                <i class="uod-icons uod-icons-menu anchor-links-title-menu-icon" role="presentation"></i>
                <span id="anchor-links-title-label" class="anchor-links-title-label">On this page</span>
            </a>
            <a href="#" class="anchor-links-title-close" aria-label="Close Page Content Navigation">
                <i class="uod-icons uod-icons-cross anchor-links-title-close-icon"></i>
            </a>
        </div>
        <div class="anchor-links-list-container">
            <ul id="page-content-navigation" class="anchor-links-list" data-gumshoe>
                {% for index, link in links %}
                <li class="anchor-links-list-item">
                    <a href="#{{ link.landmark }}" class="anchor-links-list-item-link" data-scroll>{{ link.label }}</a>
                </li>
                {% endfor %}
            </ul>
        </div>
    </nav>
</div>
{
  "links": [
    {
      "label": "Course description",
      "landmark": "course-description"
    },
    {
      "label": "What will you study",
      "landmark": "what-will-you-study"
    },
    {
      "label": "How will you learn",
      "landmark": "how-will-you-learn"
    },
    {
      "label": "Entry requirements",
      "landmark": "entry-requirements"
    },
    {
      "label": "Fees and funding",
      "landmark": "fees-and-funding"
    },
    {
      "label": "How to apply",
      "landmark": "how-to-apply"
    },
    {
      "label": "Careers",
      "landmark": "careers"
    }
  ]
}
  • Content:
    import gumshoe from 'gumshoe'
    import 'smooth-scroll/dist/js/smooth-scroll.polyfills.js'
    import SmoothScroll from 'smooth-scroll'
    import stickybits from 'stickybits'
    
    // only run the following code if there's an anchor links navigation on the page
    let elementExistsOnPage = $('[data-gumshoe-header]').length > 0;
    if (elementExistsOnPage) {
        // for linking the scroll position and the state of the navigation links
        gumshoe.init({
            offset: 40,
            callback: (nav) => {
                // if no navigation element is in focus, default to selecting the first one.
                if (!nav) {
                    $('[data-gumshoe] li:first-child, [data-gumshoe] li:first-child a').each((el) => {
                        $(el).addClass('active')
                    })
                }
            }
        });
    
        // make the navigation sticky
        stickybits('.anchor-links-container', {
            useStickyClasses: true
        });
    
        // toggle the expanded state of the mobile navigation
        $('.anchor-links-title-link').on('click', (e) => {
            e.preventDefault(); // because we don't want the page to jump around
            $('.anchor-links').toggleClass('active');
        });
    
        // add functionality to the close button
        $('.anchor-links-title-close').on('click', (e) => {
            e.preventDefault(); // because we don't want the page to jump around
            $('.anchor-links').removeClass('active');
        });
    
        // add functionality to the links in mobile view
        $('.anchor-links-list-item-link').on('click', (e) => {
            $('.anchor-links').removeClass('active');
        });
    
        // for smooth scrolling behaviours when clicking links in the navigation
        new SmoothScroll('a[data-scroll]', {
            header: '[data-scroll-header]',
            offset: 40
        });
    }
    
  • URL: /components/raw/anchor-links/anchor-links.js
  • Filesystem Path: components/components/anchor-links/anchor-links.js
  • Size: 1.8 KB
  • Content:
    .anchor-links {
        @include full-bleed-inset;
    
        transition: box-shadow .5s $default-animation-curve;
        box-shadow: none;
        background: $light-grey;
        width: 100vw;
        
        @include for-largerthan-ipad-portrait {
            flex-direction: row;
            box-shadow: none;
        }
        
        box-shadow: 0 1px 10px 0 rgba(0, 0, 0, 0.25);
    
        @include for-largerthan-ipad-portrait {
            box-shadow: none;
        }
    
        &-container {
            @include margin-small;
    
            position: relative;
            z-index: 3;
            height: px-to-em(60, 17);
            
            @include for-largerthan-ipad-portrait {
                height: px-to-em(78, 17);
                background: $light-grey;
                box-shadow: none;
                transition: box-shadow .5s $default-animation-curve;
                width: 100vw;
                box-shadow: none;
                flex-direction: row;
                box-shadow: 0 1px 10px 0 rgba(0, 0, 0, 0.25);
            }
        }
    
        &-title {
            @include body-font;
            @include full-bleed;
    
            display: flex;
            height: px-to-em(60, 17);
    
            @include for-largerthan-ipad-portrait {
                display: none;
            }
    
            a {
                @include disable-underlines;
            }
            
            &-link {
                @include link-colour($text-black);
                flex: 1;
                padding: 0 fluid-margin();
                line-height: px-to-em(60, 17);
                font-weight: bold;
            }
    
            &-label {
                display: inline-block;
                vertical-align: top;
            }
    
            &-menu-icon {
                margin-right: .5em;
                line-height: px-to-em(60, 25);
                font-size: px-to-em(25, 17);
            }
    
            &-close {
                cursor: initial;
                overflow: hidden;
    
                .anchor-links.active & {
                    cursor: pointer;
    
                    &:hover {
                        .anchor-links-title-close-icon {
                            transform: rotate(90deg);
                        }
                    }
                }
            }
    
            &-close-icon {
                transform: rotate(-90deg);
                transition: transform .3s $default-animation-curve, opacity .3s $default-animation-curve;
                opacity: 0;
                padding: 0 fluid-margin();
                line-height: px-to-em(60, 25);
                color: $text-black;
                font-size: px-to-em(25, 17);
    
                .anchor-links.active & {
                    transform: rotate(0);
                    opacity: 1;
                }
            }
        }
    
        &-list {
            display: flex;
            flex-direction: column;
            flex-wrap: nowrap;
            margin: 0 0 1px;
            padding: 0;
            font-size: 0;
            list-style-type: none;
    
            &-container {
                transition: max-height .5s $default-animation-curve;
                max-height: 0;
                overflow: hidden;
    
                .active & {
                    max-height: 1000px;
                }
    
                @include for-largerthan-ipad-portrait {
                    max-height: inherit;
                    overflow: visible;
                }
            }
    
            @include for-largerthan-ipad-portrait {
                flex-direction: row;
            }
    
            &-item {
                display: flex;
                flex: 0 1 auto;
                margin: 0;
                border-bottom: 1px dashed $dark-grey;
                height: px-to-em(50, 17);
                font-size: 17px;
                word-wrap: break-word;
                overflow-wrap: break-word;
    
                &:last-child {
                    border-bottom: 0;
                }
    
                a {
                    @include underline-only-on-hover;
                }
    
                @include for-largerthan-ipad-portrait {
                    height: px-to-em(78, 17);
                }
    
                @include for-largerthan-ipad-portrait {
                    border-bottom: 0;
                    border-left: 1px dashed $dark-grey;
    
                    &:last-child {
                        border-right: 1px dashed $dark-grey;
    
                        &.active {
                            border-right-color: $mid-grey;
                            border-right-style: solid;
                        }
                    }
    
                    &.active,
                    &.active + & {
                        border-left-color: $mid-grey;
                        border-left-style: solid;
                    }
                }
    
                &-link {
                    @include link-colour($text-black);
    
                    align-items: center;
                    display: flex;
                    flex: 1 1 auto;
                    font-family: $header-font;
                    font-size: 16px;
                    line-height: 1.29;
                    margin-bottom: -1px;
                    padding: 0 1em;
                    transition: background-color .3s $default-animation-curve;
    
                    @include for-largerthan-ipad-portrait {
                        font-size: 17px;
                        margin-bottom: 0;
                    }
    
                    &.active {
                        background: $mid-grey;
                    }
                }
            }
        }
    }
    
  • URL: /components/raw/anchor-links/anchor-links.scss
  • Filesystem Path: components/components/anchor-links/anchor-links.scss
  • Size: 5 KB

Anchor Links Component

A on-page navigation and indicator, with animated scrolling and sticky behaviour to keep the menu on screen at all times. On desktop devices this is a horizontal menu and on mobile it collapses to a toggling drop-down style menu. Clicking on a link in the menu will transition the page to that point in the content and automatically collapse the menu to make the content visible if on mobile.

Labels for the menu options and the id element that they reference are specified separately in the configuration. Successful navigation requires a landmark element to exist elsewhere on the page which matches the configuration.

Key Features

  • Accessible markup with ARIA metadata
  • Progressively enhanced - functions without Javascript enabled
  • CSS Sticky behaviours with Javascript fallback for browsers which do not support position:sticky
  • Animated scrolling
  • Current location indication
  • Responsive UI

Properties

Text Block

  • links [Required, Array of Landmark]

Landmark

  • label [required, string]
  • landmark [required, string]