代码之家  ›  专栏  ›  技术社区  ›  Millhorn

如何在做出选择后将注意力集中在自定义下拉列表上?

  •  0
  • Millhorn  · 技术社区  · 5 年前

    我有一个自定义的下拉菜单,我已经在下拉菜单和其中的项目上设置了焦点状态。但是,当我从第一个菜单中选择一个项目时,焦点会转到导航,而不是下一个下拉菜单。有没有办法将目标锁定在第一个下拉列表之后的第二个下拉列表?

    这是一个 Codepen 如果你愿意的话。

    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>
    1 回复  |  直到 5 年前
        1
  •  0
  •   Spectric amamoto    5 年前

    问题出在你的锚点标签上。具体而言,设置 href 把某事归因于某人 # 将导致页面跳转到顶部。

    从…起 MDN :

    您可以使用 href="#top" 或者空片段( href="#" )要链接到当前页面的顶部, as defined in the HTML specification .

    在您的情况下,只需删除 href 属性如果要保留键盘导航,请将其设置为 "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>