Активные ссылки с разными стилями. Чистый JS
Добрый день!
Есть список ссылок: <ul class="nav-list"> <li data-filter="red" class="nav-list__item" id="red">Красный</li> <li data-filter="green" class="nav-list__item" id="green">Зеленый</li> <li data-filter="blue" class="nav-list__item" id="blue">Синий</li> <li data-filter="gray" class="nav-list__item" id="gray">Сброс</li> </ul> Нужно, чтобы в активном (нажатом) состоянии к каждой ссылке применялся свой собственный стиль. Проблема: если указать для активной ссылки класс 'active', то все активные ссылки будут иметь один стиль, а это меня не устраивает. При клике на новую ссылку, класс 'active' удаляется у старой ссылки и добавляется к новой. Это меня устраивает. navItems.forEach(item => { item.addEventListener('click', event => { const filterValue = event.target.dataset.filter; navItems.forEach(item => { item.classList.remove('active'); event.target.classList.add('active'); }); }); }); Если вместо класса 'active' передавать значение dataset посредством переменной filterValue, к ссылкам применяются те классы, которые нужны. Это хорошо. Но при этом класс у старой ссылки не удаляется, и когда происходит клик по новой ссылке, обе ссылки становятся активными. Это плохо. navItems.forEach(item => { item.addEventListener('click', event => { const filterValue = event.target.dataset.filter; item.classList.remove(filterValue); event.target.classList.add(filterValue); }); }); Подскажите, пожалуйста, как можно решить эту проблему. |
<ul class="nav-list-1"> <li data-filter="red" class="nav-list__item">Красный</li> <li data-filter="green" class="nav-list__item">Зеленый</li> <li data-filter="blue" class="nav-list__item">Синий</li> <li data-filter="gray" class="nav-list__item">Сброс</li> </ul> <style> [data-filter="red"]:active { color: red } [data-filter="green"]:active { color: green } [data-filter="blue"]:active { color: blue } [data-filter="gray"]:active { color: gray } </style> <ul class="nav-list-2"> <li style="--active-color: red" class="nav-list__item">Красный</li> <li style="--active-color: green" class="nav-list__item">Зеленый</li> <li style="--active-color: blue" class="nav-list__item">Синий</li> <li style="--active-color: gray" class="nav-list__item">Сброс</li> </ul> <style> .nav-list-2 > li:active { color: var(--active-color); } </style> |
Спасибо за оперативный ответ!
Наверно, я не совсем точно описал проблему. При ховере и клике (hover и active) у меня всё работает. Мне надо, чтобы активная ссылка имела оформление не только в процессе клика, а на протяжении всего времени, пока юзер не кликнул на другую ссылку. Собственно, проблема в том, что если в JS я пишу ‘active’, то КО ВСЕМ ссылкам применяется ОДИН CSS класс .active. А мне нужно, чтобы У КАЖДОЙ ссылки было свое оформление. Если же в JS я меняю ‘active’ на переменную filterValue, я в принципе получаю желаемое: каждая ссылка имеет свое оформление: значение dataset совпадает с названием CSS класса. Но это оформление не отключается при клике на новую ссылку. Нажал на красную, красная ссылка стала красной, нажал на зеленую, зеленая стала зеленой. А мне надо, чтобы при клике на зеленую она стала зеленой, а красная перестала быть красной. Как-то так. |
ixiz,
<!DOCTYPE HTML> <html> <head> <title>Untitled</title> <meta charset="utf-8"> <style type="text/css"> .red { color: red; } .green { color: green; } .blue { color: blue; } .gray { color: gray; } </style> <script> document.addEventListener('DOMContentLoaded', () => { const nav = document.querySelector('.nav-list'); let active, filterValue; nav.addEventListener('click', ({ target }) => { if (target = target.closest('[data-filter]')) { if (active) { active.classList.remove(filterValue) } active = target; filterValue = target.dataset.filter; active.classList.add(filterValue) } }) }) </script> </head> <body> <ul class="nav-list"> <li data-filter="red" class="nav-list__item" id="red">Красный</li> <li data-filter="green" class="nav-list__item" id="green">Зеленый</li> <li data-filter="blue" class="nav-list__item" id="blue">Синий</li> <li data-filter="gray" class="nav-list__item" id="gray">Сброс</li> </ul> </body> </html> |
Цитата:
<!DOCTYPE HTML> <html> <head> <title>Untitled</title> <meta charset="utf-8"> <style type="text/css"> [data-filter="red"].active { color: red; } [data-filter="green"].active { color: green; } [data-filter="blue"].active { color: blue; } [data-filter="gray"].active { color: gray; } </style> <script> document.addEventListener('DOMContentLoaded', () => { const nav = document.querySelector('.nav-list'); let active; nav.addEventListener('click', ({ target }) => { if (target = target.closest('[data-filter]')) { if (active) { active.classList.remove('active') } active = target; active.classList.add('active') } }) }) </script> </head> <body> <ul class="nav-list"> <li data-filter="red" class="nav-list__item" id="red">Красный</li> <li data-filter="green" class="nav-list__item" id="green">Зеленый</li> <li data-filter="blue" class="nav-list__item" id="blue">Синий</li> <li data-filter="gray" class="nav-list__item" id="gray">Сброс</li> </ul> </body> </html> |
Можно меньше CSS
<!DOCTYPE HTML> <html> <head> <title>Untitled</title> <meta charset="utf-8"> <style type="text/css"> [data-filter].active { color: var(--link-color); } </style> <script> document.addEventListener('DOMContentLoaded', () => { const nav = document.querySelector('.nav-list'); let active; nav.addEventListener('click', ({ target }) => { if (target = target.closest('[data-filter]')) { active?.classList.remove('active') active = target; active.style.setProperty('--link-color', active.dataset.filter); active.classList.add('active') } }) }) </script> </head> <body> <ul class="nav-list"> <li data-filter="red" class="nav-list__item" id="red">Красный</li> <li data-filter="green" class="nav-list__item" id="green">Зеленый</li> <li data-filter="blue" class="nav-list__item" id="blue">Синий</li> <li data-filter="gray" class="nav-list__item" id="gray">Сброс</li> </ul> </body> </html> |
Спасибо большое за ответы!
|
ixiz, можно без js, но это уже на любителя:
<ul class="nav-list"> <label> <input type="radio" name="color"/> <li style="--active-color: red" class="nav-list__item"> Красный </li> </label> <label> <input type="radio" name="color"/> <li style="--active-color: green" class="nav-list__item"> Зеленый </li> </label> <label> <input type="radio" name="color"/> <li style="--active-color: blue" class="nav-list__item"> Синий </li> </label> <label> <input type="radio" name="color"/> <li style="--active-color: gray" class="nav-list__item"> Сброс </li> </label> </ul> <style> .nav-list input[type="radio"] { display: none; } .nav-list input[type="radio"]:checked + li { color: var(--active-color); } </style> Кстати возможно тебе бы хватило :target если ссылки по хэшу. |
Aetae,
Оно конечно браузерами пропускается, но валидаторы вопят благим матом. Дочерними элементами <ul> могут быть только <li> |
Часовой пояс GMT +3, время: 16:42. |