Добавление нескольких выпадающих меню рядом друг с другом с помощью JS, HTML и CSS

#javascript #html #css

Вопрос:

Я пытаюсь получить несколько выпадающих меню рядом друг с другом, однако я сталкиваюсь с проблемой. У меня есть две категории, которые я хочу иметь в раскрывающемся списке в заголовке, однако, похоже, работает только 1 из них. С нерабочим выпадающим меню ничего не происходит, когда я нажимаю на него.

 let click = document.querySelector('.click');
let list = document.querySelector('.list');

click.addEventListener("click", () => {
  list.classList.toggle('newlist');
}); 
 * {
  margin: 0;
  padding: 0;
  list-style: none;
  text-decoration: none;
}

.header {
  width: 100%;
  height: 100px;
  display: block;
  background-color: #F6D604;
  border-bottom: 3px solid black;
}

.header img {
  float: left;
  width: 180px;
  padding: 7px 20px;
  height: 80%;
  background: transparent;
}

img {
  image-rendering: auto;
  image-rendering: crisp-edges;
  image-rendering: pixelated;
}

.inner_header {
  width: 90%;
  height: 100%;
  display: block;
  margin: 0 auto;
}

.container {
  float: right;
  text-align: center;
  height: 100%;
  padding: 25px 5px;
  display: block;
  border-color: black;
}

.click {
  background-color: #F6D604;
  padding: 12px;
  font-size: 1.2em;
  font-family: sans-serif;
  border-color: black;
  outline: none;
  width: 150px;
  color: rgb(0, 0, 0);
  transition: 0.3s;
  border-radius: 10px;
}

.click:hover {
  background-color: #F6D604;
}

.links {
  border: none;
  outline: none;
  width: 150px;
  color: rgb(0, 0, 0);
  transition: 0.3s;
  padding: 12px;
  font-size: 1.2em;
  font-family: sans-serif;
  border-radius: 7px;
}

.list {
  position: absolute;
  transform: scaleY(0);
  transform-origin: top;
  transition: 0.3s;
  width: 150px;
  border-radius: 10px;
  border: 2px solid black;
  background-color: #fdfdfd;
}

.newlist {
  transform: scaleY(1);
  border-radius: 10px;
  border: 2px solid black;
}

.links {
  background-color: #fdfdfd;
  border-color: black;
}

.links:hover {
  background-color: #F6D604;
} 
 <div class="header">
  <div class="inner_header">
    <a href="../project/index.html">
      <div class="logo_container">
        <img src="assets/images/LOGO.png" alt="logo" />
      </div>
    </a>
    <div class="container">
      <button class="click">About</button>
      <div class="list">
        <button class="links">About us</button>
        <button class="links">Contact us</button>
      </div>
      <button class="click">Language</button>
      <div class="list">
        <button class="links">EN</button>
        <button class="links">NL</button>
      </div>
    </div>
  </div>
</div> 

Ответ №1:

querySelector подберет первый подходящий элемент, в то querySelectorAll время как получит коллекцию всех подходящих элементов. Вам нужно выполнить итерацию по элементам, чтобы применить прослушиватель. Это решение удаляет все открытые навигационные меню при нажатии на другое. Кроме того, он использует оператор [...] распространения для перебора элементов. Я добавил новый класс navitem , чтобы каждое подменю показывало, где оно должно быть.

 let click = document.querySelectorAll('.click');
let list = document.querySelectorAll('.list');
const showSub = (e) => {
    [...list].forEach(el => el.classList.remove('newlist')); // reset
    e.target.parentNode.querySelector('.list').classList.toggle('newlist');
    // this also works
    //e.target.nextElementSibling.classList.toggle('newlist');
  }
  [...click].forEach(el => el.addEventListener("click", showSub)); 
 * {
  margin: 0;
  padding: 0;
  list-style: none;
  text-decoration: none;
}

.header {
  width: 100%;
  height: 100px;
  display: block;
  background-color: #F6D604;
  border-bottom: 3px solid black;
}

.header img {
  float: left;
  width: 180px;
  padding: 7px 20px;
  height: 80%;
  background: transparent;
}

img {
  image-rendering: auto;
  image-rendering: crisp-edges;
  image-rendering: pixelated;
}

.inner_header {
  width: 90%;
  height: 100%;
  display: block;
  margin: 0 auto;
}

.container {
  float: right;
  text-align: center;
  height: 100%;
  padding: 25px 5px;
  display: block;
  border-color: black;
}

.click {
  background-color: #F6D604;
  padding: 12px;
  font-size: 1.2em;
  font-family: sans-serif;
  border-color: black;
  outline: none;
  width: 150px;
  color: rgb(0, 0, 0);
  transition: 0.3s;
  border-radius: 10px;
}

.navitem {
  width: 150px;
  display: inline-block;
}

.click:hover {
  background-color: #F6D604;
}

.links {
  border: none;
  outline: none;
  width: 150px;
  color: rgb(0, 0, 0);
  transition: 0.3s;
  padding: 12px;
  font-size: 1.2em;
  font-family: sans-serif;
  border-radius: 7px;
}

.list {
  position: absolute;
  transform: scaleY(0);
  transform-origin: top;
  transition: 0.3s;
  width: 150px;
  border-radius: 10px;
  border: 2px solid black;
  background-color: #fdfdfd;
}

.newlist {
  transform: scaleY(1);
  border-radius: 10px;
  border: 2px solid black;
}

.links {
  background-color: #fdfdfd;
  border-color: black;
}

.links:hover {
  background-color: #F6D604;
} 
 <div class="header">
  <div class="inner_header">
    <a href="../project/index.html">
      <div class="logo_container">
        <img src="assets/images/LOGO.png" alt="logo" />
      </div>
    </a>
    <div class="container">
      <div class='navitem'>
        <button class="click">About</button>
        <div class="list">
          <button class="links">About us</button>
          <button class="links">Contact us</button>
        </div>
      </div>
      <div class='navitem'>
        <button class="click">Language</button>
        <div class="list">
          <button class="links">EN</button>
          <button class="links">NL</button>
        </div>
      </div>

    </div>
  </div>
</div> 

Ответ №2:

Способ querySelector работы заключается в том, что он возвращает первый соответствующий элемент DOM. В вашем случае, поскольку вы используете click класс для обеих кнопок, прослушиватель привязан только к первой. Ознакомьтесь с соответствующей документацией (в заголовке возвращаемого значения).

В этом случае я бы предложил либо использовать два класса и добавлять слушателей к обоим отдельно, либо получить доступ к обеим кнопкам, используя что-то вроде:

 let clicks = document.querySelectorAll('.click');

for (let click of clicks) {
  click.addEventListener("click",()=>{
    list.classList.toggle('newlist');
  });
}
 

Комментарии:

1. Хотя вы правы в отношении querySelector, вам, вероятно, следует показать, что list относится к (поскольку существует несколько случаев)

Ответ №3:

Вам нужно forEach обратиться к каждой паре кнопок со списком.

Я считаю, что приведенный ниже код решает ваши проблемы с JavaScript. Отрегулируйте CSS по мере необходимости (я немного изменил исходный HTML).

 let drops = document.querySelectorAll('.drop');

drops.forEach(function(drop) {
  let click = drop.querySelector('.click');
  let list = drop.querySelector('.list');
  click.addEventListener("click", () => {
    list.classList.toggle('newlist');
  });
}); 
 * {
  margin: 0;
  padding: 0;
  list-style: none;
  text-decoration: none;
}

.header {
  width: 100%;
  height: 100px;
  display: block;
  background-color: #F6D604;
  border-bottom: 3px solid black;
}

.header img {
  float: left;
  width: 180px;
  padding: 7px 20px;
  height: 80%;
  background: transparent;
}

img {
  image-rendering: auto;
  image-rendering: crisp-edges;
  image-rendering: pixelated;
}

.inner_header {
  width: 90%;
  height: 100%;
  display: block;
  margin: 0 auto;
}

.container {
  text-align: center;
  height: 100%;
  padding: 25px 5px;
  display: block;
  border-color: black;
}

.drop {
  width: 150px;
  float: right;
  padding: 0 5px;
}

.click {
  background-color: #F6D604;
  padding: 12px;
  font-size: 1.2em;
  font-family: sans-serif;
  border-color: black;
  outline: none;
  width: 100%;
  color: rgb(0, 0, 0);
  transition: 0.3s;
  border-radius: 10px;
}

.click:hover {
  background-color: #F6D604;
}

.links {
  border: none;
  outline: none;
  width: 150px;
  color: rgb(0, 0, 0);
  transition: 0.3s;
  padding: 12px;
  font-size: 1.2em;
  font-family: sans-serif;
  border-radius: 7px;
}

.list {
  position: absolute;
  transform: scaleY(0);
  margin-top: 1px;
  transform-origin: top;
  transition: 0.3s;
  width: 150px;
  border-radius: 10px;
  border: 2px solid black;
  background-color: #fdfdfd;
}

.newlist {
  transform: scaleY(1);
  border-radius: 10px;
  border: 2px solid black;
}

.links {
  background-color: #fdfdfd;
  border-color: black;
}

.links:hover {
  background-color: #F6D604;
} 
 <div class="header">
  <div class="inner_header">
    <a href="../project/index.html">
      <div class="logo_container">
        <img src="assets/images/LOGO.png" alt="logo" />
      </div>
    </a>
    <div class="container">
      <div class="drop">
        <button class="click">Language</button>
        <div class="list">
          <button class="links">EN</button>
          <button class="links">NL</button>
        </div>
      </div>
      <div class="drop">
        <button class="click">About</button>
        <div class="list">
          <button class="links">About us</button>
          <button class="links">Contact us</button>
        </div>
      </div>
    </div>
  </div>
</div>