Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript & CSS - opening menu has glitchy transition

I have some code that glitches initially when menus are expanded on top of each other.

If you select option two in the first menu, the second option appears. If you then go to open the first menu, you will see it glitches as it opens - there is almost a shutter-like delay. Maybe it has something to do with the z index setting, I'm not sure?

In firefox and chrome, there is no (apparent) glitch. In safari, the snippet below, there is a glitch.

Why is it glitching?

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>
like image 943
code noob Avatar asked Apr 09 '20 15:04

code noob


People also ask

What is the JavaScript used for?

JavaScript is a text-based programming language used both on the client-side and server-side that allows you to make web pages interactive. Where HTML and CSS are languages that give structure and style to web pages, JavaScript gives web pages interactive elements that engage a user.

Which is better HTML or JavaScript?

JavaScript simply adds dynamic content to websites to make them look good. HTML work on the look of the website without the interactive effects and all. HTML pages are static which means the content cannot be changed. It adds interactivity to web pages to make them look good.

Is JavaScript and HTML same?

Both of these are computer languages that help in programming, but there is a major difference between JavaScript and HTML. While JavaScript (abbreviated as JS) is a scripting language, HTML is a markup language. We use HTML to create web pages or web applications.

Is JavaScript easy to learn?

Arguably, JavaScript is one of the easiest programming languages to learn, so it serves as a great first language for anyone brand new to coding. Even the most complex lines of JavaScript code can be written one by one, in fragments. It can also be tested in the web browser at the same time.


1 Answers

Adding the position: relative; to the class .filter-filterbox-row would fix it immediately for Safari:

.filter-filterbox-row {
  display: grid;
  grid-template-columns: auto auto;
  grid-template-areas: "question select-box";
  padding: 5px 5px;
  margin-top: -2px;
  position: relative;
}

position: static; is the default normal flow of the document if not explicitly stated. Since you've declared a z-index: 99 on the child div:

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

...stating the z-index assumes the div is in absolute position, thus we need to declare a position for the parent div which is the .filter-filterbox-row. Furthermore, adding the position: absolute; on the child div is required if you need to state the top, bottom, left or right properties.

Declaring an explicit position for the parent div is one way to prevent different browser behavior glitches such as this. The same practice we always do when we declare a z-index on the child div and state the position as relative, the parent div should be declared as well with the position if relative or absolute for the child div to behave accordingly.

like image 128
Anne Avatar answered Oct 06 '22 01:10

Anne