首页 > 解决方案 > Javascript & CSS - 打开菜单有故障过渡

问题描述

当菜单在彼此之上展开时,我有一些代码最初会出现故障。

如果您在第一个菜单中选择选项二,则会出现第二个选项。如果您然后打开第一个菜单,您会看到它在打开时出现故障 - 几乎有类似快门的延迟。也许它与 z 索引设置有关,我不确定?

在 Firefox 和 chrome 中,没有(明显的)故障。在 safari 中,下面的片段,有一个小故障。

为什么会出现故障?

const selected = document.querySelectorAll(".selected");
const optionsContainer = document.querySelectorAll(".options-container");

for (let i = 0; i < selected.length; i++) {
  selected[i].addEventListener("click", () => {
    optionsContainer[i].classList.toggle("open");
    selected[i].classList.toggle("open");

    for (let j = 0; j < selected.length; j++) {

      if (i != j && selected[j].classList.contains("open")) {
        optionsContainer[j].classList.toggle("open");
        selected[j].classList.toggle("open");
      }
    }
  });
}

for (let i = 0; i < optionsContainer.length; i++) {
  let optionsList = optionsContainer[i].querySelectorAll(".options");

  for (let j = 0; j < optionsList.length; j++) {
    optionsList.forEach(o => {
      o.addEventListener("click", () => {
        selected[i].innerHTML = o.querySelector("label").innerHTML;
        optionsContainer[i].classList.remove("open");
        selected[i].classList.remove("open");
        if (document.getElementById("level").innerText.indexOf('one') === -1) {
          document.getElementById("tier").style.display = "grid";
        } else {
          document.getElementById("tier").style.display = "none";
        }
      });
    });
  }
}
.filter-filterbox-row {
  display: grid;
  grid-template-columns: auto auto;
  grid-template-areas: "question select-box";
  padding: 5px 5px;
  margin-top: -2px;
}

.filter-filterbox-row .question {
  grid-template-areas: "question";
  width: 100px;
  padding-top: 5px;
  padding-bottom: 10px;
  padding-left: 15px;
  text-align: right;
}

.filter-filterbox-row .select-box {
  margin-left: -100px;
  grid-template-areas: "select-box";
}

.select-box {
  width: 200px;
}

.select-box .options-container {
  background: #fff;
  width: 200px;
  display: none;
  transition: all 0.4s;
  position: absolute;
  max-height: 240px;
  border: 1px solid #253e5c;
  border-radius: 0 0 4.5px 4.5px;
}

.selected {
  position: relative;
  border: 1px solid #cdcccc;
  border-radius: 4.5px;
  padding: 4px 15px;
  cursor: pointer;
  transition: all 0.4s;
}

.selected.open {
  border-bottom: none;
  border-radius: 4.5px 4.5px 0 0;
  transition: all 0.4s;
  border-color: #253e5c
}

.selected::after {
  content: "";
  background: url(media/dropdown-black.png);
  background-size: contain;
  background-repeat: no-repeat;
  position: absolute;
  height: 100%;
  width: 12px;
  right: 13px;
  top: 10px;
  transition: all 0.4s;
}

.selected.open::after {
  transform: rotateX(180deg);
  top: -11px;
}

.select-box .options-container.open {
  border-color: #253e5c;
  display: block;
  z-index: 99;
}

.select-box .options-container.open .options:nth-child(n+2) {
  border-top: 1px solid #253e5c;
}

.select-box .options-container .options {
  padding-top: 5px;
  padding-bottom: 5px;
  padding-left: 15px;
}

.select-box .options:hover {
  background: #76bc6b;
  cursor: pointer;
}

.select-box label {
  cursor: pointer;
}

.select-box .options .radio {
  display: none;
}

#tier {
  display: none;
}
<div class="filter-filterbox-row" id="level">
  <div class="question"> Level </div>
  <div class="select-box">
    <div class="selected">
      Select level
    </div>

    <div class="options-container">

      <div class="options">
        <input type="radio" class="radio" id="1" name="level">
        <label for="1">one</label>
      </div>

      <div class="options">
        <input type="radio" class="radio" id="2" name="level">
        <label for="2">two</label>
      </div>
    </div>
  </div>
</div>

<div class="filter-filterbox-row" id="tier">
  <div class="question"> Select tier </div>
  <div class="select-box">
    <div class="selected">
      Select tier
    </div>

    <div class="options-container">

      <div class="options">
        <input type="radio" class="radio" id="bronze" name="tier">
        <label for="bronze">Bronze</label>
      </div>

      <div class="options">
        <input type="radio" class="radio" id="silver" name="tier">
        <label for="silver">silver</label>
      </div>
    </div>
  </div>
</div>

标签: javascriptcssz-index

解决方案


使用 CSS 进行设置时,在 Safari 浏览器中设置 z-index 会有延迟。

使用 JavaScript 设置它可以解决问题:

document.getElementsByClassName('select-box')[0].style.zIndex = 99;

片段:

const selected = document.querySelectorAll(".selected");
const optionsContainer = document.querySelectorAll(".options-container");

for (let i = 0; i < selected.length; i++) {
  selected[i].addEventListener("click", () => {
    optionsContainer[i].classList.toggle("open");
    selected[i].classList.toggle("open");
    document.getElementsByClassName('select-box')[0].style.zIndex = 99;
    for (let j = 0; j < selected.length; j++) {
      if (i != j && selected[j].classList.contains("open")) {
        optionsContainer[j].classList.toggle("open");
        selected[j].classList.toggle("open");
      }
    }
  });
}

for (let i = 0; i < optionsContainer.length; i++) {
  let optionsList = optionsContainer[i].querySelectorAll(".options");

  for (let j = 0; j < optionsList.length; j++) {
    optionsList.forEach(o => {
      o.addEventListener("click", () => {
        selected[i].innerHTML = o.querySelector("label").innerHTML;
        optionsContainer[i].classList.remove("open");
        selected[i].classList.remove("open");
        if (document.getElementById("level").innerText.indexOf('one') === -1) {
          document.getElementById("tier").style.display = "grid";
        } else {
          document.getElementById("tier").style.display = "none";
        }
      });
    });
  }
}
.filter-filterbox-row {
  display: grid;
  grid-template-columns: auto auto;
  grid-template-areas: "question select-box";
  padding: 5px 5px;
  margin-top: -2px;
}

.filter-filterbox-row .question {
  grid-template-areas: "question";
  width: 100px;
  padding-top: 5px;
  padding-bottom: 10px;
  padding-left: 15px;
  text-align: right;
}

.filter-filterbox-row .select-box {
  margin-left: -100px;
  grid-template-areas: "select-box";
}

.select-box {
  width: 200px;
}

.select-box .options-container {
  background: #fff;
  width: 200px;
  display: none;
  transition: all 0.4s;
  position: absolute;
  max-height: 240px;
  border: 1px solid #253e5c;
  border-radius: 0 0 4.5px 4.5px;
}

.selected {
  position: relative;
  border: 1px solid #cdcccc;
  border-radius: 4.5px;
  padding: 4px 15px;
  cursor: pointer;
  transition: all 0.4s;
}

.selected.open {
  border-bottom: none;
  border-radius: 4.5px 4.5px 0 0;
  transition: all 0.4s;
  border-color: #253e5c
}

.selected::after {
  content: "";
  background: url(media/dropdown-black.png);
  background-size: contain;
  background-repeat: no-repeat;
  position: absolute;
  height: 100%;
  width: 12px;
  right: 13px;
  top: 10px;
  transition: all 0.4s;
}

.selected.open::after {
  transform: rotateX(180deg);
  top: -11px;
}

.select-box .options-container.open {
  border-color: #253e5c;
  display: block;
  z-index: 99;
}

.select-box .options-container.open .options:nth-child(n+2) {
  border-top: 1px solid #253e5c;
}

.select-box .options-container .options {
  padding-top: 5px;
  padding-bottom: 5px;
  padding-left: 15px;
}

.select-box .options:hover {
  background: #76bc6b;
  cursor: pointer;
}

.select-box label {
  cursor: pointer;
}

.select-box .options .radio {
  display: none;
}

#tier {
  display: none;
}
<div class="filter-filterbox-row" id="level">
  <div class="question"> Level </div>
  <div class="select-box">
    <div class="selected">
      Select level
    </div>

    <div class="options-container">

      <div class="options">
        <input type="radio" class="radio" id="1" name="level">
        <label for="1">one</label>
      </div>

      <div class="options">
        <input type="radio" class="radio" id="2" name="level">
        <label for="2">two</label>
      </div>
    </div>
  </div>
</div>

<div class="filter-filterbox-row" id="tier">
  <div class="question"> Select tier </div>
  <div class="select-box">
    <div class="selected">
      Select tier
    </div>

    <div class="options-container">

      <div class="options">
        <input type="radio" class="radio" id="bronze" name="tier">
        <label for="bronze">Bronze</label>
      </div>

      <div class="options">
        <input type="radio" class="radio" id="silver" name="tier">
        <label for="silver">silver</label>
      </div>
    </div>
  </div>
</div>


推荐阅读