Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixing CLS with Responsive Nav #299

Open
dmolsen opened this issue Jan 3, 2022 · 2 comments
Open

Fixing CLS with Responsive Nav #299

dmolsen opened this issue Jan 3, 2022 · 2 comments
Labels
enhancement New feature or request

Comments

@dmolsen
Copy link

dmolsen commented Jan 3, 2022

Background

All of our websites are seeing us get dinged by Google in search rankings for poor CLS scores on mobile. The nav is the main culprit. As an example, on mobile, the WVU home page has a score of 0.5 CLS with nav and 0.0 without. Anything over 0.1 is considered Bad.

We are currently using responsive-nav.js as our default at least on the home page. I believe it's used as part of the design system too (it's in the repo at least). The issue with this solution is that it shows the full navigation by default on mobile and then hides it if JS is enabled. This causes the CLS issue. I understand the interest in a progressively enhanced solution. e.g. if JS is not available then the nav is available.

I've hacked a solution for the WVU home page that doesn't require dropping responsive-nav.js in the short-term. I'm not entirely sure it is an accessible solution but it does address both the CLS and progressive enhancement.

Implementation Suggestions

Add a script element with a type of text/template with an ID as well as a noscript element. The navigation should be rendered into both. If JS is off then the noscript tag will show and the content rendered. Use the init callback in responsive-nav.js to pull the content from script element into the nav ul.

The only issue with this solution is that if there are sub-menus in the nav then they don't get styled properly on mobile and there are no "toggles" to open the sub-menu. This is where is gets hacky. My solution essentially re-runs the responsive-nav.js set-up sans the init.

So same basic solution as we have now with minimal template changes. The only other change would be the responsive-nav.js set-up with the init and second call to itself.

Examples:

"use strict";
var customToggle = document.getElementById("nav-toggle"),
    navigation = responsiveNav(".nav-collapse", {
        animate: !0,
        insert: "before",
        transition: 600,
        customToggle: "#nav-toggle",
        init: function() {
            var el = document.getElementById('wvu-nav--menu-items');
            el.parentElement.innerHTML = el.innerHTML;
            responsiveNav(".nav-collapse", {
                animate: !0,
                insert: "before",
                transition: 600,
                customToggle: "#nav-toggle",
                enableFocus: !0,
                enableDropdown: !0,
                menuItems: "menu-items",
                subMenu: "sub-menu",
                openPos: "relative",
                openDropdown: '<span class="screen-reader-text">Open sub menu</span>',
                closeDropdown: '<span class="screen-reader-text">Close sub menu</span>',
                open: function() {
                    customToggle.innerHTML = '<img src="https://static.wvu.edu/global/images/icons/wvu/hamburger-menu--1.0.0.svg" alt="" />Close Menu'
                },
                close: function() {
                    customToggle.innerHTML = '<img src="https://static.wvu.edu/global/images/icons/wvu/hamburger-menu--1.0.0.svg" alt="" />Open Menu'
                },
                resizeMobile: function() {
                    customToggle.setAttribute("aria-controls", "wvu-nav")
                },
                resizeDesktop: function() {
                    customToggle.removeAttribute("aria-controls")
                }
            });
        },
        open: function() {
            customToggle.innerHTML = '<img src="https://static.wvu.edu/global/images/icons/wvu/hamburger-menu--1.0.0.svg" alt="" />Close Menu'
        },
        close: function() {
            customToggle.innerHTML = '<img src="https://static.wvu.edu/global/images/icons/wvu/hamburger-menu--1.0.0.svg" alt="" />Open Menu'
        },
        resizeMobile: function() {
            customToggle.setAttribute("aria-controls", "wvu-nav")
        },
        resizeDesktop: function() {
            customToggle.removeAttribute("aria-controls")
        }
    });
@dmolsen dmolsen added the enhancement New feature or request label Jan 3, 2022
@adamjohnson
Copy link
Contributor

Why not just display: none; the nav while it's collapsed, then add some styles to undo that inside the <noscript> element?

Maybe I'm missing something...

@dmolsen
Copy link
Author

dmolsen commented Jan 10, 2022

This particular fix was pushed to the WVU home page and seems to be working. I still need to investigate a suggestion from AJ about updating SCSS. Will do later this week.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants