Почему после окончания действия условия @media-запроса, стиль не возвращается к исходному виду?
Вот сам проект: https://codepen.io/Coder10000000000/pen/NWjjqyb
Есть адаптивное меню, пункты выводятся горизонтально ("display:flex")
При ширине экрана меньше 1024, меню отображается вертикально, становится "display: block"
@media screen and (max-width: 1024px) {
.btn--menu {
display: block;
cursor: pointer;
}
#show-menu:checked ~ .navigation .menu-list{
display: block;
}
.menu-list {
display: none;
position: absolute;
top: 100px;
left: 53px;
& .menu-sublist {
position: initial;
padding-left: 10px;
}
}
}
Так же, в правом верхнем углу появляется иконка, которая скрывает/раскрывает пункты меню
Казалось бы, всё работает. Но проблема в том, что если на узком экране (в режиме "display:block"), открыть меню, а после этого, не закрывая его, расширить экран больше 1024px, то меню так и остаётся в режиме display:block
То есть, при возврате экрана в широкое состояние, стиль после @media запроса не возвращается к исходному виду
Я решил проблему с помощью такой записи:
@media screen and (min-width: 1025px) {
.menu-list{
display: flex !important;
}
}
Но этот подход мне кажется очень топорным
1) Почему после возврата к широкому экрану, стиль не возвращается к исходному виду? Нормально ли это?
2) Какие есть адекватные способы решения проблемы? (дополнительный медиа-запрос и !important выглядят очень плохим подходом)
Ответы (2 шт):
У Вас по ссылке в codepen опечатка в 13-й строке, должно быть:
#show-menu:checked ~ .navigation .menu-list{
display: flex;
}
У Вас
#show-menu:checked ~ .navigation .menu-list{
display: block;
}
Логика - в 13-й строке вы задаете вид меню по умолчанию - display: flex, в частном случае, при < 1024px задаете как display: block
body{
background-color: #000;
font-family: 'Montserrat', sans-serif;
font-size: 16px;
color: #fff;
}
#show-menu {
display: none;
}
#show-menu:checked ~ .navigation .menu-list{
display: flex; /* ОПЕЧАТКА должен быть flex у вас block*/
}
.btn--menu{
width: 50px;
height: 50px;
display: none;
position: absolute;
right: 15px;
background-color: #fff;
& img {
width: 50px;
height: 50px;
}
}
.navigation {
z-index: 1;
& a {
display: inline-block;
padding: 10px 20px;
color: #fff;
text-decoration: none;
text-transform: uppercase;
line-height: 1.3;
&:hover {
background-color: #131d4a;
border-radius: 2px;
}
}
}
.menu-list {
display: flex;
position: relative;
& li:hover > .menu-sublist{
visibility: visible;
opacity: 1;
max-height: initial;
}
& li:hover > .ico-caret:after {
transform: rotate(90deg);
}
}
.menu-sublist {
position: absolute;
visibility: hidden;
opacity: 0;
max-height: 0;
& .menu-sublist {
position: initial;
padding-left: 10px;
}
}
@media screen and (max-width: 1024px) {
.btn--menu {
display: block;
cursor: pointer;
}
#show-menu:checked ~ .navigation .menu-list{
display: block;
}
.menu-list {
display: none;
position: absolute;
top: 100px;
left: 53px;
& .menu-sublist {
position: initial;
padding-left: 10px;
}
}
}
<input type="checkbox" id="show-menu">
<label for="show-menu" class="btn--menu"><img src="https://cdn4.iconfinder.com/data/icons/wirecons-free-vector-icons/32/menu-alt-512.png" alt=""></label>
<nav class="navigation">
<ul class="menu-list">
<li><a href="#">Меню1</a></li>
<li><a href="#">Меню1</a>
<ul class="menu-sublist">
<li><a href="#">Меню2</a></li>
<li><a href="#">Меню2</span></a>
<ul class="menu-sublist">
<li><a href="#">Меню3</a></li>
<li><a href="#">Меню3</a></li>
<li><a href="#">Меню3</a></li>
</ul>
</li>
<li><a href="#">Меню2</a></li>
</ul>
</li>
<li><a href="#">Меню1</a></li>
<li><a href="#">Меню1</a></li>
<li><a href="#">Меню1</a></li>
</ul>
</nav>
UPD:
Подскажите, пожалуйста, почему такая запись работает: #show-menu:checked ~ .navigation .menu-list{ display: flex; } А если просто указать нужный класс для манипуляций, то не работает? #show-menu:checked .menu-list{ display: flex; }
Дело все в селекторе (точнее комбинаторе) ~
Строка #show-menu:checked ~ .navigation .menu-list нам говорит найти все соседние элементы с классом .navigation к элементу с id show-menu и в состояни :cheked и далее во всех найденых элементах найти элементы с классом menu-list. Визульно это выглядит так:
div{
width: 50px;
height: 50px;
border: 1px solid green;
}
#show-menu:checked ~ .navigation{
border: 1px solid red;
}
<div><!-- какой то родитель или body -->
<div class="navigation"></div> <!-- этот элемент не подходит под условие так как стоит до элемента с id show-menu-->
<input id="show-menu" type="checkbox" checked>
<div class="navigation"> <!-- Соседний элемент с классом navigation-->
</div>
<div class="someclass"></div>
<div class="navigation"> <!-- Соседний элемент с классом navigation-->
</div>
</div>
А запись #show-menu:checked .menu-list означает что элемент .menu-list находится внутри элемента #show-menu. Визуально:
<!-- Визуализация вот такой #someid .navigation записи-->
<div id="someid">
<div class="navigation"></div>
</div>
Вам мешает эта часть кода
#show-menu:checked ~ .navigation .menu-list{
display: block;
}
Эта часть Вашего кода переопределяет свойство display: flex потому что элемент #show-menu остается в состоянии checked если вы раскроете меню на видимой области менее 1024px и увеличите видимую область.
Если вам нужно, чтобы #show-menu переходило в исходное состояние, то у Вас есть два варианта:
Не использовать состояние
checked, а добавлять классchecked(при появлении которого применяются нужные Вам стили) кshow-menuс помощью JavaScript, например, так:document.querySelector("#show-menu").classList.toggle("checked");Убирать состояние
checkedэлемента#show-menu(ставить значениеfalse) при размере окна более 1024px кода JavaScript.document.querySelector("#show-menu").checked = false;
Поищите информацию здесь - Размеры окна