I have a custom dropdown and I've set up focus states on the dropdown and the items in it. But, when I select an item from the first menu, the focus goes to the nav and not the next dropdown. Is there a way to target the second dropdown after the first one?
Here's a Codepen if you'd prefer.
for (const dropdown of document.querySelectorAll(".custom__select-wrapper:not(.clearFilter)")) {
dropdown.addEventListener("click", function () {
this.querySelector(".custom__select").classList.toggle("open");
});
}
for (const option of document.querySelectorAll(".custom__option")) {
option.addEventListener("click", function () {
if (!this.classList.contains("selected")) {
this.parentNode
.querySelector(".custom__option.selected")
.classList.remove("selected");
this.classList.add("selected");
this.closest(".custom__select").querySelector(
".custom__select-trigger h6"
).textContent = this.textContent;
if (this.getAttribute("data-type")) {
current_story = this.dataset["type"];
}
}
});
}
window.addEventListener("click", function (e) {
for (const select of document.querySelectorAll(".custom__select")) {
if (!select.contains(e.target)) {
select.classList.remove("open");
}
}
});
@charset "UTF-8";
nav ul {
list-style-type: none;
display: flex;
flex-direction: row;
width: 100%;
justify-content: space-evenly;
}
.content {
display: flex;
flex-direction: column;
align-items: center;
}
button.clear {
border: 0;
background: #fff;
}
#selectedFilter {
color: #005fec;
}
ul {
padding-left: 0;
margin: 0;
}
.filter {
padding-right: 15px;
padding-left: 15px;
margin-bottom: 2rem;
display: flex;
flex-direction: column;
}
@media (min-width: 768px) {
.filter__settings {
display: flex;
flex-direction: row;
border-top: 1px solid #E0E5EC;
border-bottom: 1px solid #E0E5EC;
}
}
.custom__select {
position: relative;
display: flex;
flex-direction: column;
}
@media (min-width: 768px) {
.custom::before, .custom__options {
transition: all 0.2s ease-in;
}
}
.custom__select-wrapper {
position: relative;
user-select: none;
padding: 0;
border-bottom: 1px solid #E0E5EC;
}
.custom__select-wrapper:last-child {
border: 0;
}
.custom__select-wrapper.clearFilter {
display: flex;
flex-direction: column;
justify-content: center;
}
.custom__select-wrapper .selected-clearFilter {
position: relative;
user-select: none;
padding: 1rem 0 !important;
}
@media (min-width: 768px) {
.custom__select-wrapper {
padding: 0 2em;
border: 0;
display: flex;
justify-content: center;
align-items: center;
}
.custom__select-wrapper:first-child, .custom__select-wrapper:last-child {
padding: 0;
}
}
.custom__select-wrapper h6 {
padding: 20px 3px;
color: #62668C;
font-weight: 300;
}
.custom__select-trigger {
position: relative;
display: flex;
align-items: center;
justify-content: space-between;
cursor: pointer;
}
@media (min-width: 768px) {
.custom__select-trigger {
justify-content: space-evenly;
margin-right: auto;
}
}
.custom__select-wrapper h6, .custom__select-trigger h6 {
font-size: 0.75rem;
line-height: 0.75rem;
letter-spacing: 1px;
text-transform: uppercase;
padding: 20px 0;
}
.custom__select-trigger h6 {
color: #005fec;
font-weight: 900;
}
.custom__select-wrapper #selectedFilter {
font-size: 12px;
line-height: 12px;
letter-spacing: 1px;
text-transform: uppercase;
color: #005fec;
font-weight: 800;
padding: 0;
}
.custom__options {
display: none;
top: 100%;
left: 0;
right: 0;
border-top: 0;
opacity: 0;
visibility: hidden;
pointer-events: none;
z-index: 2;
color: #E0E5EC;
}
@media (min-width: 768px) {
.custom__options {
display: unset;
position: absolute;
background-color: #005fec;
max-height: 320px;
overflow-y: scroll;
}
.custom__options#storyFilter {
overflow: hidden;
}
}
.custom__options.active {
display: block;
visibility: visible;
opacity: 1;
z-index: 10;
}
.custom__select-trigger, .custom__option {
letter-spacing: 1px;
font-weight: 800;
color: #005fec;
border: 0;
background: transparent;
}
@media (min-width: 768px) {
.custom__select.open::before {
content: "";
position: absolute;
bottom: 0;
left: 11px;
border-left: 11px solid transparent;
border-right: 11px solid transparent;
border-bottom: 11px solid #005fec;
}
}
.custom__select .custom__options {
min-width: 15rem;
}
.custom__select.open .custom__options {
display: block;
opacity: 1;
visibility: visible;
pointer-events: all;
color: #fff;
min-width: 15rem;
}
@media (min-width: 768px) {
.custom__select.open .custom__options {
display: unset;
box-shadow: 0px 12px 30px rgba(0, 0, 0, 0.12);
}
}
.custom__option {
position: relative;
display: block;
padding: 0 22px 0 12px;
font-weight: 400;
color: #62668C;
cursor: pointer;
font-size: 1rem;
line-height: 1rem;
margin: 1.5rem 0;
}
@media (min-width: 768px) {
.custom__option {
font-size: 1.25rem;
line-height: 1.25rem;
color: white;
font-weight: 300;
padding: 0 22px 0 20px;
}
.custom__option a {
color: white !important;
text-decoration: none;
}
}
.custom__option:hover {
cursor: pointer;
}
.custom__option.selected {
color: #005fec;
}
@media (min-width: 768px) {
.custom__option.selected {
color: #ffffff;
}
}
.custom__option.selected::before {
content: "•";
margin-left: -12px;
padding-right: 8px;
}
.empty-state {
width: 100%;
display: flex;
background: #005fec;
padding: 1rem;
border-radius: 4px;
align-items: center;
margin: 2rem 0.5rem;
}
.empty-state h4 {
color: white;
font-size: 1rem;
line-height: 1.5rem;
font-weight: 300;
margin-left: 0.5rem;
}
.empty-state h4 span {
color: white;
text-decoration: underline;
cursor: pointer;
}
.arrow {
position: relative;
height: 5px;
width: 3px;
margin-left: 0.5rem;
margin-bottom: 0.1rem;
}
.arrow::before, .arrow::after {
content: "";
position: absolute;
bottom: 0px;
width: 0.1rem;
height: 100%;
transition: all 0.45s;
}
.arrow::before {
left: 0px;
transform: rotate(45deg);
background-color: #005fec;
}
@media (min-width: 768px) {
.arrow::before {
left: 7px;
}
}
.arrow::after {
left: -2.5px;
transform: rotate(-45deg);
background-color: #005fec;
}
@media (min-width: 768px) {
.arrow::after {
left: 4.5px;
}
}
.open .arrow::before {
left: 0px;
transform: rotate(-45deg);
}
@media (min-width: 768px) {
.open .arrow::before {
left: 7px;
}
}
.open .arrow::after {
left: -2.5px;
transform: rotate(45deg);
}
@media (min-width: 768px) {
.open .arrow::after {
left: 4.5px;
}
}
<div class="container">
<nav>
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Products</a></li>
<li><a href="#">Sales</a></li>
<li><a href="#">Contact</a></li>
</ul>
</nav>
<section class="content">
<h2 class="title">Hello World</h2>
<h6 class="subtitle">Lorem ipsum dolor sit amet.</h6>
</section>
<section class="filter">
<div class="filter__settings">
<div class="custom__select-wrapper">
<h6>filter by</h6>
</div>
<div class="custom__select-wrapper">
<div class="custom__select story-sel selector" role="menubar">
<button class="custom__select-trigger" aria-haspopup="true" aria-expanded="false" id="storySelector">
<h6>Story Type</h6>
<div class="arrow"></div>
</button>
<ul class="custom__options dropdown story-selector" id="storyFilter" aria-label="submenu" role="menu" aria-labelledby="custom-dropdown">
<li role="menuitem" class="custom__option selected" data-type="all" id="storyItem_all"><a href="#">All</a>
</li>
<li role="menuitem" class="custom__option" data-type="news" id="storyItem_nm"><a href="#">News and
media</a></li>
<li role="menuitem" class="custom__option" data-type="analysis" id="storyItem_analysis"><a href="#">Analysis</a></li>
<li role="menuitem" class="custom__option" data-type="press" id="storyItem_pr"><a href="#">Press
releases</a></li>
</ul>
</div>
</div>
<div class="custom__select-wrapper">
<div class="custom__select year-sel selector">
<button type="button" class="custom__select-trigger" id="yearSelector">
<h6>Year</h6>
<div class=" arrow"></div>
</button>
<ul class="custom__options dropdown year-selector" id="yearSelection" aria-label="submenu" role="menu" aria-labelledby="custom-dropdown">
<li role="menuitem" class="custom__option selected" data-year="all"><a href="#">All</a></li>
<li role="menuitem" class="custom__option" data-year="2021"><a href="#">2021</a></li>
<li role="menuitem" class="custom__option" data-year="2020"><a href="#">2020</a></li>
<li role="menuitem" class="custom__option" data-year="2019"><a href="#">2019</a></li>
</ul>
</div>
</div>
</div>
</section>
</div>
The problem lies in your anchor tags. Specifically, setting the href
attribute to #
will cause the page to jump to the top.
From MDN:
You can use
href="#top"
or the empty fragment (href="#"
) to link to the top of the current page, as defined in the HTML specification.
In your case, simply remove the href
attribute. If you want to preserve navigation with the keyboard, set it to "javascript:void(0)"
for (const dropdown of document.querySelectorAll(".custom__select-wrapper:not(.clearFilter)")) {
dropdown.addEventListener("click", function () {
this.querySelector(".custom__select").classList.toggle("open");
});
}
for (const option of document.querySelectorAll(".custom__option")) {
option.addEventListener("click", function () {
if (!this.classList.contains("selected")) {
this.parentNode
.querySelector(".custom__option.selected")
.classList.remove("selected");
this.classList.add("selected");
this.closest(".custom__select").querySelector(
".custom__select-trigger h6"
).textContent = this.textContent;
if (this.getAttribute("data-type")) {
current_story = this.dataset["type"];
}
}
});
}
window.addEventListener("click", function (e) {
for (const select of document.querySelectorAll(".custom__select")) {
if (!select.contains(e.target)) {
select.classList.remove("open");
}
}
});
@charset "UTF-8";
nav ul {
list-style-type: none;
display: flex;
flex-direction: row;
width: 100%;
justify-content: space-evenly;
}
.content {
display: flex;
flex-direction: column;
align-items: center;
}
button.clear {
border: 0;
background: #fff;
}
#selectedFilter {
color: #005fec;
}
ul {
padding-left: 0;
margin: 0;
}
.filter {
padding-right: 15px;
padding-left: 15px;
margin-bottom: 2rem;
display: flex;
flex-direction: column;
}
@media (min-width: 768px) {
.filter__settings {
display: flex;
flex-direction: row;
border-top: 1px solid #E0E5EC;
border-bottom: 1px solid #E0E5EC;
}
}
.custom__select {
position: relative;
display: flex;
flex-direction: column;
}
@media (min-width: 768px) {
.custom::before, .custom__options {
transition: all 0.2s ease-in;
}
}
.custom__select-wrapper {
position: relative;
user-select: none;
padding: 0;
border-bottom: 1px solid #E0E5EC;
}
.custom__select-wrapper:last-child {
border: 0;
}
.custom__select-wrapper.clearFilter {
display: flex;
flex-direction: column;
justify-content: center;
}
.custom__select-wrapper .selected-clearFilter {
position: relative;
user-select: none;
padding: 1rem 0 !important;
}
@media (min-width: 768px) {
.custom__select-wrapper {
padding: 0 2em;
border: 0;
display: flex;
justify-content: center;
align-items: center;
}
.custom__select-wrapper:first-child, .custom__select-wrapper:last-child {
padding: 0;
}
}
.custom__select-wrapper h6 {
padding: 20px 3px;
color: #62668C;
font-weight: 300;
}
.custom__select-trigger {
position: relative;
display: flex;
align-items: center;
justify-content: space-between;
cursor: pointer;
}
@media (min-width: 768px) {
.custom__select-trigger {
justify-content: space-evenly;
margin-right: auto;
}
}
.custom__select-wrapper h6, .custom__select-trigger h6 {
font-size: 0.75rem;
line-height: 0.75rem;
letter-spacing: 1px;
text-transform: uppercase;
padding: 20px 0;
}
.custom__select-trigger h6 {
color: #005fec;
font-weight: 900;
}
.custom__select-wrapper #selectedFilter {
font-size: 12px;
line-height: 12px;
letter-spacing: 1px;
text-transform: uppercase;
color: #005fec;
font-weight: 800;
padding: 0;
}
.custom__options {
display: none;
top: 100%;
left: 0;
right: 0;
border-top: 0;
opacity: 0;
visibility: hidden;
pointer-events: none;
z-index: 2;
color: #E0E5EC;
}
@media (min-width: 768px) {
.custom__options {
display: unset;
position: absolute;
background-color: #005fec;
max-height: 320px;
overflow-y: scroll;
}
.custom__options#storyFilter {
overflow: hidden;
}
}
.custom__options.active {
display: block;
visibility: visible;
opacity: 1;
z-index: 10;
}
.custom__select-trigger, .custom__option {
letter-spacing: 1px;
font-weight: 800;
color: #005fec;
border: 0;
background: transparent;
}
@media (min-width: 768px) {
.custom__select.open::before {
content: "";
position: absolute;
bottom: 0;
left: 11px;
border-left: 11px solid transparent;
border-right: 11px solid transparent;
border-bottom: 11px solid #005fec;
}
}
.custom__select .custom__options {
min-width: 15rem;
}
.custom__select.open .custom__options {
display: block;
opacity: 1;
visibility: visible;
pointer-events: all;
color: #fff;
min-width: 15rem;
}
@media (min-width: 768px) {
.custom__select.open .custom__options {
display: unset;
box-shadow: 0px 12px 30px rgba(0, 0, 0, 0.12);
}
}
.custom__option {
position: relative;
display: block;
padding: 0 22px 0 12px;
font-weight: 400;
color: #62668C;
cursor: pointer;
font-size: 1rem;
line-height: 1rem;
margin: 1.5rem 0;
}
@media (min-width: 768px) {
.custom__option {
font-size: 1.25rem;
line-height: 1.25rem;
color: white;
font-weight: 300;
padding: 0 22px 0 20px;
}
.custom__option a {
color: white !important;
text-decoration: none;
}
}
.custom__option:hover {
cursor: pointer;
}
.custom__option.selected {
color: #005fec;
}
@media (min-width: 768px) {
.custom__option.selected {
color: #ffffff;
}
}
.custom__option.selected::before {
content: "•";
margin-left: -12px;
padding-right: 8px;
}
.empty-state {
width: 100%;
display: flex;
background: #005fec;
padding: 1rem;
border-radius: 4px;
align-items: center;
margin: 2rem 0.5rem;
}
.empty-state h4 {
color: white;
font-size: 1rem;
line-height: 1.5rem;
font-weight: 300;
margin-left: 0.5rem;
}
.empty-state h4 span {
color: white;
text-decoration: underline;
cursor: pointer;
}
.arrow {
position: relative;
height: 5px;
width: 3px;
margin-left: 0.5rem;
margin-bottom: 0.1rem;
}
.arrow::before, .arrow::after {
content: "";
position: absolute;
bottom: 0px;
width: 0.1rem;
height: 100%;
transition: all 0.45s;
}
.arrow::before {
left: 0px;
transform: rotate(45deg);
background-color: #005fec;
}
@media (min-width: 768px) {
.arrow::before {
left: 7px;
}
}
.arrow::after {
left: -2.5px;
transform: rotate(-45deg);
background-color: #005fec;
}
@media (min-width: 768px) {
.arrow::after {
left: 4.5px;
}
}
.open .arrow::before {
left: 0px;
transform: rotate(-45deg);
}
@media (min-width: 768px) {
.open .arrow::before {
left: 7px;
}
}
.open .arrow::after {
left: -2.5px;
transform: rotate(45deg);
}
@media (min-width: 768px) {
.open .arrow::after {
left: 4.5px;
}
}
<div class="container">
<nav>
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Products</a></li>
<li><a href="#">Sales</a></li>
<li><a href="#">Contact</a></li>
</ul>
</nav>
<section class="content">
<h2 class="title">Hello World</h2>
<h6 class="subtitle">Lorem ipsum dolor sit amet.</h6>
</section>
<section class="filter">
<div class="filter__settings">
<div class="custom__select-wrapper">
<h6>filter by</h6>
</div>
<div class="custom__select-wrapper">
<div class="custom__select story-sel selector" role="menubar">
<button class="custom__select-trigger" aria-haspopup="true" aria-expanded="false" id="storySelector">
<h6>Story Type</h6>
<div class="arrow"></div>
</button>
<ul class="custom__options dropdown story-selector" id="storyFilter" aria-label="submenu" role="menu" aria-labelledby="custom-dropdown">
<li role="menuitem" class="custom__option selected" data-type="all" id="storyItem_all"><a href="javascript:void(0);">All</a>
</li>
<li role="menuitem" class="custom__option" data-type="news" id="storyItem_nm"><a href="javascript:void(0);">News and
media</a></li>
<li role="menuitem" class="custom__option" data-type="analysis" id="storyItem_analysis"><a href="javascript:void(0);">Analysis</a></li>
<li role="menuitem" class="custom__option" data-type="press" id="storyItem_pr"><a href="javascript:void(0);">Press
releases</a></li>
</ul>
</div>
</div>
<div class="custom__select-wrapper">
<div class="custom__select year-sel selector">
<button type="button" class="custom__select-trigger" id="yearSelector">
<h6>Year</h6>
<div class=" arrow"></div>
</button>
<ul class="custom__options dropdown year-selector" id="yearSelection" aria-label="submenu" role="menu" aria-labelledby="custom-dropdown">
<li role="menuitem" class="custom__option selected" data-year="all"><a href="javascript:void(0);">All</a></li>
<li role="menuitem" class="custom__option" data-year="2021"><a href="javascript:void(0);">2021</a></li>
<li role="menuitem" class="custom__option" data-year="2020"><a href="javascript:void(0);">2020</a></li>
<li role="menuitem" class="custom__option" data-year="2019"><a href="javascript:void(0);">2019</a></li>
</ul>
</div>
</div>
</div>
</section>
</div>