Активные ссылки с разными стилями. Чистый 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, время: 07:24. |