网站导航辅助功能 - Enter 键无法打开子导航



我正在构建网站导航。如果我选择一个类别并按回车键,什么都不会发生。如果我按下空格键,我就会看到subnav的闪烁,但随后它就消失了。

我使用按钮元素来触发子导航,而不是锚标记。如果我切换到锚标记,它就会工作。

是什么导致这种情况发生在我的Javascript,有没有办法使这更好?

我把整个导航放到了codepen: https://codepen.io/sibarad/pen/gORqevp?editors=1010

下面是html的一个基本示例:
<ul class="site-menu header-container--nav-mobile">
<li class="site-menu__item site-menu__item--has-submenu">
<button tabindex="0" aria-expanded="false">Nav Link 1
<span class="site-menu__submenu-icon">
<svg aria-hidden="true" width="16" height="16">
<use xlink:href="#mobile-nav-arrow" />
</svg>
</span>
</button>
<!-- Main Nav Item 1 Sub-item -->
<ul class="site-menu__submenu" id="dt_nav-accountbilling">
<li class="site-menu__subitem"><a href="#">Subnav</a></li>
<li class="site-menu__subitem"><a href="#">Subnav</a></li>
</ul><!-- /Main Nav Item 1 Sub-item -->
</li><!-- /Main Nav Item 1 -->

这是我的JS:

// Submenu Hide/Show Mobile and Desktop
const items = document.querySelectorAll(".site-menu__item--has-submenu");
const subButton = document.querySelectorAll(".site-menu__item--has-submenu button");
// Activate Submenu
function toggleItem() {
if (this.classList.contains("submenu-active")) {
this.classList.remove("submenu-active");
} else if (site_menu.querySelector(".submenu-active")) {
site_menu.querySelector(".submenu-active").classList.remove("submenu-active");
this.classList.add("submenu-active");
this.setAttribute('aria-expanded', 'true');
} else {
this.classList.add("submenu-active");
this.setAttribute('aria-expanded', 'false');
}
}
// Event Listeners
for (let item of items) {
if (item.querySelector(".site-menu__submenu")) {
item.addEventListener("click", toggleItem, false);
item.addEventListener("keypress", toggleItem, false);
}
}
// Close Submenu From Anywhere
function closeSubmenu(e) {
let isClickInside = site_menu.contains(e.target);
if (!isClickInside && site_menu.querySelector(".submenu-active")) {
site_menu.querySelector(".submenu-active").classList.remove("submenu-active");
}
}
// Event listener for Close Submenu
document.addEventListener("click", closeSubmenu, false);
document.addEventListener('keydown', (event) => {
if (event.key === 'Escape') {
//if esc key was not pressed in combination with ctrl or alt or shift
const isNotCombinedKey = !(event.ctrlKey || event.altKey || event.shiftKey);
if (isNotCombinedKey) {
closeSubmenu(false);
}
}
});

违规代码在这里:

for (let item of items) {
if (item.querySelector(".site-menu__submenu")) {
item.addEventListener("click", toggleItem, false);
<!-- this will be triggered as well, reversing your toggle -->
item.addEventListener("keypress", toggleItem, false);
}
}

您正在添加2个侦听器,它们将在按空格等时触发。

您不需要第二个侦听器,因为您使用的<button>将把Space等视为单击事件!

删除第二个侦听器将使下拉列表按预期工作。

for (let item of items) {
if (item.querySelector(".site-menu__submenu")) {
item.addEventListener("click", toggleItem, false);
}
}

修复代码和摆弄

/////////////
// Site header/navigation
////////////
(function() {
'use strict';
// Hamburger Animation toggle
const hamburger = document.querySelector('.js-primary-nav__toggle');
const hamburger_text = document.querySelector('.js-primary-nav__toggle-text');
// Mobile Container for Nav Content
const site_menu = document.querySelector('.main-site-menu');
hamburger.addEventListener('click', () => {
hamburger.classList.toggle('toggle-active');
if (hamburger_text.textContent === "Menu") {
hamburger_text.textContent = "Close";
site_menu.classList.add('is-active');
hamburger.setAttribute('aria-expanded', 'true');
document.body.classList.toggle('lock-scroll');
} else {
hamburger_text.textContent = "Menu";
site_menu.classList.remove('is-active');
hamburger.setAttribute('aria-expanded', 'false');
document.body.classList.toggle('lock-scroll');
}
});
// Submenu Hide/Show Mobile and Desktop
const items = document.querySelectorAll(".site-menu__item--has-submenu");
const subButton = document.querySelectorAll(".site-menu__item--has-submenu button");
// Activate Submenu
function toggleItem() {
if (this.classList.contains("submenu-active")) {
this.classList.remove("submenu-active");
} else if (site_menu.querySelector(".submenu-active")) {
site_menu.querySelector(".submenu-active").classList.remove("submenu-active");
this.classList.add("submenu-active");
this.setAttribute('aria-expanded', 'true');
} else {
this.classList.add("submenu-active");
this.setAttribute('aria-expanded', 'false');
}
}
// Event Listeners
for (let item of items) {
if (item.querySelector(".site-menu__submenu")) {
item.addEventListener("click", toggleItem, false);
//item.addEventListener("keypress", toggleItem, false);
}
}
// Close Submenu From Anywhere
function closeSubmenu(e) {
let isClickInside = site_menu.contains(e.target);
if (!isClickInside && site_menu.querySelector(".submenu-active")) {
site_menu.querySelector(".submenu-active").classList.remove("submenu-active");
}
}
// Event listener for Close Submenu
document.addEventListener("click", closeSubmenu, false);
document.addEventListener('keydown', (event) => {
if (event.key === 'Escape') {
//if esc key was not pressed in combination with ctrl or alt or shift
const isNotCombinedKey = !(event.ctrlKey || event.altKey || event.shiftKey);
if (isNotCombinedKey) {
closeSubmenu(false);
}
}
});
}());
body {
font-size: 16px;
line-height: 1.5;
font-family: "Open Sans", "Segoe UI", Tahoma, sans-serif;
}
.os-container--max-width, .header-container--nav-mobile, .header-container {
max-width: 1272px;
margin-right: auto;
margin-left: auto;
padding-left: 12px;
padding-right: 12px;
}
.os-container--fluid {
max-width: 100%;
margin-right: auto;
margin-left: auto;
}
.os-flex-grid {
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin-left: -8px;
margin-right: -8px;
}
@media (min-width: 672px) {
.os-flex-grid {
margin-left: -12px;
margin-right: -12px;
}
}
.os-flex--stack-mobile {
flex-direction: column;
}
@media (min-width: 672px) {
.os-flex--stack-mobile {
flex-direction: row;
}
}
.os-flex-grid__col {
padding-left: 8px;
padding-right: 8px;
-ms-flex: 1 1 0px;
flex-basis: auto;
flex-grow: 1;
min-width: 0;
max-width: 100%;
position: relative;
width: 100%;
}
@media (min-width: 672px) {
.os-flex-grid__col {
flex-basis: 0;
padding-left: 12px;
padding-right: 12px;
}
}
.os-flex-grid__col--12, .cms-flex-grid__col--12 {
flex-basis: 100%;
}
.os-flex-grid__col--9, .cms-flex-grid__col--9 {
flex-basis: 75%;
}
.os-flex-grid__col--6 {
flex-basis: 50%;
}
.os-flex-grid__col--4 {
flex-basis: 33.3333333333%;
}
.os-flex-grid__col--3 {
flex-basis: 25%;
}
.os-flex-grid__col--2 {
flex-basis: 16.6666666667%;
}
.site-header {
background-color: #fff;
list-style: none;
}
.site-header a {
color: #0e75c4;
}
@media (min-width: 1056px) {
.site-header {
margin-bottom: 42px;
}
}
.site-nav {
display: flex;
flex-direction: column;
align-items: normal;
justify-content: flex-start;
width: 100%;
position: relative;
z-index: 3;
}
@media (min-width: 1056px) {
.site-nav {
display: block;
}
}
@media (min-width: 1056px) {
.header-container {
position: relative;
z-index: 5;
}
}
.header-container--nav-mobile {
padding-left: 1.25rem;
padding-right: 1.25rem;
}
@media (min-width: 1056px) {
.header-container--nav-mobile {
padding-left: inital;
padding-right: inital;
}
}
.header-main {
box-shadow: 0 4px 8px -2px rgba(18, 32, 42, 0.12);
padding-top: 16px;
padding-bottom: 16px;
}
@media (min-width: 1056px) {
.header-main {
box-shadow: none;
padding-top: 32px;
padding-bottom: 32px;
}
}
.header-main__items {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
.header-logo img {
width: 100%;
max-width: 131px;
}
@media (min-width: 672px) {
.header-logo img {
max-width: 260px;
}
}
.header-component-wrap {
display: flex;
flex-direction: row;
align-items: flex-end;
}
.header-component-wrap a {
text-decoration: none;
}
.header-component-wrap a:hover {
text-decoration: underline;
}
.header-component-wrap svg {
fill: #213848;
margin-bottom: 8px;
width: 20px;
height: 20px;
}
@media (min-width: 1056px) {
.header-component-wrap svg {
margin-bottom: 0;
margin-right: 8px;
width: 20px;
height: 20px;
}
}
@media (min-width: 1056px) {
.header-component-wrap {
align-items: center;
}
}
.header-main__text {
text-decoration: none;
color: #0e75c4;
font-size: 10px;
font-weight: 600;
letter-spacing: 1.25px;
}
.header-main__text:hover {
text-decoration: underline;
color: #0e75c4;
}
@media (min-width: 1056px) {
.header-main__text {
font-size: 16px;
font-weight: 600;
letter-spacing: normal;
}
}
.site-menu,
.site-menu__submenu {
list-style-type: none;
}
.site-menu {
margin: 0 auto;
background-color: #213848;
display: flex;
flex-direction: column;
align-items: flex-start;
padding-top: 24px;
padding-bottom: 24px;
overflow-y: auto;
}
@media (min-width: 1056px) {
.site-menu {
flex-wrap: nowrap;
flex-direction: row;
align-items: stretch;
justify-content: flex-start;
padding: 0;
padding-right: 8px;
padding-left: 8px;
position: relative;
top: 0;
height: auto;
overflow-y: visible;
border-radius: 6px;
}
}
.main-site-menu {
transition: 0.3s;
position: absolute;
top: 80px;
width: 100%;
left: 0;
left: 0;
opacity: 0;
overflow-x: hidden;
visibility: hidden;
height: 100vh;
background-color: #213848;
padding-bottom: 9.75rem;
}
@media (min-width: 1056px) {
.main-site-menu {
position: relative;
top: 0;
left: 0;
transition: none;
opacity: 1;
visibility: visible;
overflow-x: initial;
height: auto;
padding-bottom: 0;
background-color: transparent;
}
}
.main-site-menu.is-active {
opacity: 1;
visibility: visible;
}
.site-menu__item {
position: relative;
display: inline-block;
margin-bottom: 16px;
width: 100%;
}
@media (min-width: 1056px) {
.site-menu__item {
margin-bottom: 0;
width: auto;
}
}
.site-menu__item a {
display: block;
color: #fff !important;
}
.site-menu__item > a {
font-weight: 600;
font-size: 18px;
}
@media (min-width: 1056px) {
.site-menu__item > a {
padding: 24px 16px;
}
}
@media (min-width: 1272px) {
.site-menu__item > a {
padding: 24px;
}
}
.site-menu__item > a:hover {
cursor: pointer;
}
@media (min-width: 1056px) {
.site-menu__item > a:hover {
background-color: #0e75c4;
}
}
.site-menu__item--has-submenu {
border-bottom: 1px solid #2f4656;
}
@media (min-width: 1056px) {
.site-menu__item--has-submenu {
border-bottom: none;
}
}
@media (min-width: 1056px) {
.site-menu__item.site-menu__button {
margin-left: auto;
}
}
.site-menu__item--has-submenu button {
background-color: transparent;
outline: none;
border: none;
color: #fff;
padding-top: 24px;
padding-bottom: 24px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
width: 100%;
font-size: 16px;
font-weight: 600;
transition: 0.333333333s ease-in-out;
}
.site-menu__item--has-submenu button:hover {
cursor: pointer;
}
@media (min-width: 1056px) {
.site-menu__item--has-submenu button:hover {
background-color: #2f4656;
color: #61bef0;
}
}
.site-menu__item--has-submenu button:focus {
outline: 1px solid #128ddd;
}
@media (min-width: 1056px) {
.site-menu__item--has-submenu button {
padding-top: 16px;
padding-bottom: 16px;
padding-left: 24px;
padding-right: 24px;
font-size: 14px;
}
}
@media (min-width: 1240px) {
.site-menu__item--has-submenu button {
padding-top: 20px;
padding-bottom: 20px;
padding-left: 24px;
padding-right: 24px;
font-size: 16px;
}
}
.site-menu__submenu-icon svg {
width: 16px;
height: 9.33px;
}
@media (min-width: 1056px) {
.site-menu__submenu-icon {
display: none;
}
}
.mobile-nav-arrow {
width: 16px;
height: 9.33px;
transition: 0.3s;
fill: #128ddd;
}
.site-menu__submenu {
font-size: 16px;
background-color: #2f4656;
padding-top: 8px;
padding-right: 24px;
padding-bottom: 8px;
padding-left: 24px;
min-width: 100%;
border-radius: 6px;
transition: max-height 0.4s 0s ease-in-out;
display: none;
max-height: 0;
left: -999rem;
flex-direction: column;
}
@media (min-width: 1056px) {
.site-menu__submenu {
font-size: 14px;
position: absolute;
top: 100%;
left: 0;
margin-left: 0;
min-width: 302px;
display: flex;
flex-direction: column;
border-radius: 0;
border-bottom-right-radius: 6px;
border-bottom-left-radius: 6px;
visibility: hidden;
padding-top: 16px;
padding-bottom: 8px;
}
}
@media (min-width: 1240px) {
.site-menu__submenu {
font-size: 16px;
}
}
@media (min-width: 1056px) {
.site-menu__item--has-submenu:nth-child(7) > .site-menu__submenu {
min-width: 185px;
}
}
@media (min-width: 1240px) {
.site-menu__item--has-submenu:nth-child(7) > .site-menu__submenu {
min-width: 295px;
}
}
@media (min-width: 1272px) {
.site-menu__item--has-submenu:nth-child(7) > .site-menu__submenu {
min-width: 302px;
}
}
.submenu-active .site-menu__submenu {
display: flex;
max-height: inherit;
left: auto;
}
@media (min-width: 1056px) {
.submenu-active .site-menu__submenu {
visibility: visible;
}
}
@media (min-width: 1056px) {
.submenu-active {
background-color: #2f4656;
}
}
.submenu-active > button {
color: #61bef0;
}
.site-menu__submenu-col {
position: relative;
width: 100%;
flex-basis: 0;
flex-grow: 1;
min-width: 0;
max-width: 100%;
list-style-position: inside;
}
@media (min-width: 1056px) {
.site-menu__subitem {
display: inline-block;
}
}
.site-menu__subitem a {
padding-top: 16px;
padding-bottom: 16px;
display: inline-block;
text-decoration: none;
}
.site-menu__subitem a:hover {
text-decoration: underline;
cursor: pointer;
}
@media (min-width: 1056px) {
.site-menu__subitem a {
padding: 0;
margin-bottom: 24px;
}
}
.site-menu__item--mobile-search {
display: block;
}
@media (min-width: 1056px) {
.site-menu__item--mobile-search {
display: none;
}
}
.site-menu__item--mobile-search input {
width: 100%;
padding: 12px;
background-image: url(../images/search-icon.svg);
background-repeat: no-repeat;
background-position: 98% center;
border: 1px solid #687782;
box-shadow: inset 0px 4px 0px #ebebeb;
border-radius: 6px;
}
.primary-nav__toggle {
outline: 0;
border: 0;
background: transparent;
background-color: transparent;
display: inline-block;
cursor: pointer;
padding: 0;
margin: 0;
height: 48px;
}
@media (min-width: 1056px) {
.primary-nav__toggle {
display: none;
}
}
.primary-nav__toggle-bar {
display: block;
width: 24px;
height: 2px;
background-color: #213848;
margin: 6px auto;
transition: 0.4s;
border-radius: 1px;
}
.primary-nav__toggle-bar--bottom {
margin-bottom: 4px;
}
.toggle-active .primary-nav__toggle-bar--top {
transform: rotate(-45deg) translate(-7px, 6px);
}
.toggle-active .primary-nav__toggle-bar--middle {
opacity: 0;
}
.toggle-active .primary-nav__toggle-bar--bottom {
transform: rotate(45deg) translate(-5px, -5px);
}
.lock-scroll {
overflow: hidden;
position: fixed;
width: 100%;
}
<header class="site-header site-header--home">

<nav class="site-nav" role="navigation" aria-label="main menu">
<!-- main header -->
<div class="header-main">
<div class="header-container header-main__items">
<a class="header-logo" href="">Logo</a>
<div class="header-component-wrap">
<!-- Mobile Hamburger Toggle -->
<button class="primary-nav__toggle js-primary-nav__toggle" aria-expanded="false">
<span class="primary-nav__toggle-bar primary-nav__toggle-bar--top"></span>
<span class="primary-nav__toggle-bar primary-nav__toggle-bar--middle"></span>
<span class="primary-nav__toggle-bar primary-nav__toggle-bar--bottom"></span>
<span class="header-main__text js-primary-nav__toggle-text">Menu</span>
</button><!-- /Mobile Hamburger Toggle -->
</div>
</div>
</div>
<!-- Site Navigation Wrappers -->
<div class="header-container">
<div class="main-site-menu">
<!-- Site Nav -->
<ul class="site-menu header-container--nav-mobile">
<!-- Main Nav Item 1 -->
<li class="site-menu__item site-menu__item--has-submenu">
<button tabindex="0" aria-expanded="false">Nav Link 1
<span class="site-menu__submenu-icon">
<svg aria-hidden="true" width="16" height="16">
<use xlink:href="#mobile-nav-arrow" />
</svg>
</span>
</button>
<!-- Main Nav Item 1 Sub-item -->
<ul class="site-menu__submenu" id="dt_nav-accountbilling">
<li class="site-menu__subitem"><a href="#">Subnav</a></li>
<li class="site-menu__subitem"><a href="#">Subnav</a></li>
<li class="site-menu__subitem"><a href="#">Subnav</a></li>
<li class="site-menu__subitem"><a href="#">Subnav</a></li>
<li class="site-menu__subitem"><a href="#">Subnav</a></li>
<li class="site-menu__subitem"><a href="#">Subnav</a></li>
</ul><!-- /Main Nav Item 1 Sub-item -->
</li><!-- /Main Nav Item 1 -->
<!-- Main Nav Item 2 -->
<li class="site-menu__item site-menu__item--has-submenu">
<button tabindex="0" aria-expanded="false">Nav Link 2
<span class="site-menu__submenu-icon">
<svg aria-hidden="true" width="16" height="16">
<use xlink:href="#mobile-nav-arrow" />
</svg>
</span>
</button>
<!-- Main Nav Item 2 Sub-item -->
<ul class="site-menu__submenu" id="dt_nav-savemoney">
<li class="site-menu__subitem"><a href="#">Subnav</a></li>
<li class="site-menu__subitem"><a href="#">Subnav</a></li>
<li class="site-menu__subitem"><a href="#">Subnav</a></li>
<li class="site-menu__subitem"><a href="#">Subnav</a></li>
<li class="site-menu__subitem"><a href="#">Subnav</a></li>
<li class="site-menu__subitem"><a href="#">Subnav</a></li>
<li class="site-menu__subitem"><a href="#">Subnav</a></li>
<li class="site-menu__subitem"><a href="#">Subnav</a></li>
</ul><!-- /Main Nav Item 2 Sub-item -->
</li><!-- /Main Nav Item 2 -->
<!-- Main Nav Item 3 -->
<li class="site-menu__item site-menu__item--has-submenu">
<button tabindex="0" aria-expanded="false">Nav Link 3
<span class="site-menu__submenu-icon">
<svg aria-hidden="true" width="16" height="16">
<use xlink:href="#mobile-nav-arrow" />
</svg>
</span>
</button>
<!-- Main Nav Item 3 Sub-item -->
<ul class="site-menu__submenu" id="dt_nav-outagesstorms">
<li class="site-menu__subitem"><a href="#">Subnav</a></li>
<li class="site-menu__subitem"><a href="#">Subnav</a></li>
<li class="site-menu__subitem"><a href="#">Subnav</a></li>
<li class="site-menu__subitem"><a href="#">Subnav</a></li>
<li class="site-menu__subitem"><a href="#">Subnav</a></li>
<li class="site-menu__subitem"><a href="#">Subnav</a></li>
<li class="site-menu__subitem"><a href="#">Subnav</a></li>
</ul><!-- /Main Nav Item 3 Sub-item -->
</li><!-- /Main Nav Item 3 -->
<!-- Main Nav Item 4 -->
<li class="site-menu__item site-menu__item--has-submenu">
<button tabindex="0" aria-expanded="false">Nav Link 4
<span class="site-menu__submenu-icon">
<svg aria-hidden="true" width="16" height="16">
<use xlink:href="#mobile-nav-arrow" />
</svg>
</span>
</button>
<!-- Main Nav Item 4 Sub-item -->
<ul class="site-menu__submenu" id="dt_nav-safety">
<li class="site-menu__subitem"><a href="#">Subnav</a></li>
<li class="site-menu__subitem"><a href="#">Subnav</a></li>
<li class="site-menu__subitem"><a href="#">Subnav</a></li>
<li class="site-menu__subitem"><a href="#">Subnav</a></li>
<li class="site-menu__subitem"><a href="#">Subnav</a></li>
<li class="site-menu__subitem"><a href="#">Subnav</a></li>
<li class="site-menu__subitem"><a href="#">Subnav</a></li>
<li class="site-menu__subitem"><a href="#">Subnav</a></li>
</ul><!-- /Main Nav Item 4 Sub-item -->
</li><!-- /Main Nav Item 4 -->
</ul><!-- /Site Nav -->
</div>
</div><!-- /Site Navigation Wrappers -->
</nav>
</header><!-- /Begin ES Site Header -->

最新更新