Как обратиться к элементам, расположенным рядом с выбранным селектором?

Как создать стили для предыдущих и последующих элементов списка при наведении курсора на средний элемент без использования JavaScript? Я видел видео на YouTube, где была представлена реализация с помощью :has или :not, но не могу найти это видео сейчас. Может быть, кто-то помнит, как это можно сделать?
  • 11 февраля 2024 г. 22:18
Ответы на вопрос 2
Для стилизации элементов, находящихся непосредственно рядом с выбранным элементом, можно использовать CSS-соседние селекторы:

- `+` - селектор непосредственно следующего соседа, который выбирает элемент, следующий непосредственно за указанным.
- `~` - селектор общих следующих соседей, который выбирает всех соседей на том же уровне вложенности, что и указанный.

Примеры использования селекторов:
```css
/* Стили для элемента, следующего непосредственно за h1 */
h1 + p {
  color: red;
}

/* Стили для всех элементов p, следующих за h1 на том же уровне */
h1 ~ p {
  color: blue;
}
```

Что касается стилизации предыдущих и последующих элементов при наведении на средний элемент, тут сложнее, так как CSS по своей природе "однонаправлен": он может воздействовать вниз по DOM-дереву, но не вверх. Однако, селектор `:has()` в новых спецификациях CSS4 позволял бы выполнить такое задание, если бы он был полностью реализован и поддерживался в браузерах. На момент знания нашего временного среза (2023 год), `:has()` ещё не имеет широкой поддержки в основных браузерах и его использование ограничено.

Тем не менее, предполагая, что `:has()` стал доступен, можно было бы попробовать что-то похожее на это:

```css
/* Стили для предыдущих элементов */
li:hover ~ li:not(:has(li:hover + li)) {
  background-color: yellow; /* или любой другой стиль */
}

/* Стили для последующих элементов */
li:not(:has(li:hover + li)) ~ li:hover {
  background-color: green; /* или любой другой стиль */
}
```

Обратите внимание, что этот код работал бы, если бы `:has()` был реализован для использования в контекстах стилизации и поддерживался бы браузерами (что, скорее всего, на момент вашего обращения, не так).

Для решения вашей задачи без использования JavaScript и без поддержки `:has()` невозможно стилизовать предыдущие элементы списка при наведении на средний элемент исключительно средствами CSS. Поэтому в реальной ситуации данную задачу решают, используя JavaScript:

```javascript
let listItems = document.querySelectorAll('li');

listItems.forEach(function (item) {
  item.addEventListener('mouseover', function () {
    // Последующие элементы
    let nextSibling = item.nextElementSibling;
    while (nextSibling) {
      nextSibling.classList.add('highlight');
      nextSibling = nextSibling.nextElementSibling;
    }
    
    // Предыдущие элементы
    let prevSibling = item.previousElementSibling;
    while (prevSibling) {
      prevSibling.classList.add('highlight');
      prevSibling = prevSibling.previousElementSibling;
    }
  });

  item.addEventListener('mouseout', function () {
    document.querySelectorAll('.highlight').forEach(function (highlightedItem) {
      highlightedItem.classList.remove('highlight');
    });
  });
});
```

И соответствующий стиль в CSS:

```css
.highlight {
  background-color: #ececec; /* Цвет подсветки */
}
```

Внесите это код в свой проект, и предыдущие и последующие элементы будут подсвечиваться при наведении на элемент списка.
Похожие вопросы