Как получить соседние элементы без jQuery
В jQuery есть метод siblings()
, который позволяет получить соседние элементы. В этой статье посмотрим, как добиться того же результата на чистом JavaScript.
Имея доступ до соседних элементов, можно получить довольно интересные эффекты
Посмотреть результат в живую можно на Codepen
Создаём структуру
Если вы подписаны на telegram-канал блога, то этот пример будет уже знаком. Если не подписаны, то присоединяйтесь
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Practice</title>
<link rel="stylesheet" href="css/bootstrap-reboot.min.css"/>
<link rel="preconnect" href="https://fonts.gstatic.com"/>
<link href="https://fonts.googleapis.com/css2?family=Lora:wght@700&family=Roboto:wght@300;400&display=swap" rel="stylesheet"/>
<link rel="stylesheet" href="css/main.css"/>
</head>
<body>
<section class="cards">
<div class="container">
<div class="cards__grid">
<div class="cards__card card">
<div class="card__image"><img src="img/image1.jpg" alt=""/></div>
<div class="card__body">
<div class="card__category">Fruits</div>
<div class="card__grow">
<div class="card__title"><a href="">Red Dragonfruit</a></div>
<div class="card__text">These fruits are commonly known in English as "dragon fruit", a name used since around 1963, apparently resulting from the leather-like skin and prominent scaly spikes on the fruit exterior. English as "dragon fruit", a name used since around 1963.</div>
</div>
<div class="card__bottom">
<div class="card__author card-author">
<div class="card-author__avatar"><img src="img/avatar1.png" alt=""/></div>
<div class="card-author__name">Anny</div>
</div>
<div class="card__time card-time">
<div class="card-time__icon">
<svg class="icon">
<use xlink:href="#time"></use>
</svg>
</div>
<div class="card-time__value">5 min read</div>
</div>
</div>
</div>
</div>
<div class="cards__card card card_accent">
<div class="card__image"><img src="img/image2.jpg" alt=""/></div>
<div class="card__body">
<div class="card__category">Fruits</div>
<div class="card__grow">
<div class="card__title"><a href="">Violet Fruit</a></div>
<div class="card__text">These fruits are commonly known in English as "dragon fruit", a name used since around 1963, apparently resulting</div>
</div>
<div class="card__bottom">
<div class="card__author card-author">
<div class="card-author__avatar"><img src="img/avatar2.png" alt=""/></div>
<div class="card-author__name">Den</div>
</div>
<div class="card__time card-time">
<div class="card-time__icon">
<svg class="icon">
<use xlink:href="#time"></use>
</svg>
</div>
<div class="card-time__value">3 min read</div>
</div>
</div>
</div>
</div>
<div class="cards__card card">
<div class="card__image"><img src="img/image3.jpg" alt=""/></div>
<div class="card__body">
<div class="card__category">Fruits</div>
<div class="card__grow">
<div class="card__title"><a href="">Very loooong orange title in two lines</a></div>
<div class="card__text">These fruits are commonly known in English as "dragon fruit", a name used since around 1963, apparently resulting from the leather-like skin and prominent scaly spikes on the fruit exterior.</div>
</div>
<div class="card__bottom">
<div class="card__author card-author">
<div class="card-author__avatar"><img src="img/avatar3.png" alt=""/></div>
<div class="card-author__name">Peter</div>
</div>
<div class="card__time card-time">
<div class="card-time__icon">
<svg class="icon">
<use xlink:href="#time"></use>
</svg>
</div>
<div class="card-time__value">11 min read</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<svg class="hidden" width="0" height="0">
<symbol id="time" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path d="M9.992 1.667c-4.6 0-8.325 3.733-8.325 8.333s3.725 8.333 8.325 8.333c4.608 0 8.341-3.733 8.341-8.333S14.6 1.667 9.992 1.667zm.008 15A6.665 6.665 0 013.333 10 6.665 6.665 0 0110 3.333 6.665 6.665 0 0116.667 10 6.665 6.665 0 0110 16.667z"></path>
<path d="M10.417 5.833h-1.25v5l4.375 2.625.625-1.025-3.75-2.225V5.833z"></path>
</symbol>
</svg>
<script src="js/main.js"></script>
</body>
</html>
Добавим стилей
Стилизуем структуру, используя БЭМ, CSS-переменные, CSS Grid Layout, SVG Sprite, Flexbox и так далее
body {
font-family: 'Roboto', sans-serif;
}
.container {
max-width: 1120px;
padding: 0 32px;
margin: 0 auto;
}
.cards {
padding: 96px 0;
background: #484c56;
}
.cards__grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
grid-gap: 64px 32px;
gap: 64px 32px;
}
.card {
--dark-gray: #484c56;
--light-gray: #9ca9b9;
--orange: #cc5a53;
--white: #f6f5f5;
display: flex;
flex-direction: column;
align-items: center;
border-radius: 8px;
background: var(--white);
transition: 0.24s;
}
.card:hover {
transform: scale(1.04);
}
.card_sibling {
transform: scale(0.96);
opacity: 0.8;
-webkit-filter: grayscale(64%);
filter: grayscale(64%);
}
.card__image {
width: calc(100% - 32px);
border-radius: 8px;
overflow: hidden;
margin-top: -32px;
box-shadow: 0 8px 16px rgba(0,0,0,0.5);
height: 220px;
}
.card__image img {
display: block;
width: 100%;
height: 100%;
-o-object-fit: cover;
object-fit: cover;
}
.card__body {
flex: 1;
padding: 24px;
display: flex;
flex-direction: column;
}
.card__category {
font-size: 12px;
line-height: 1.333333333333333;
text-transform: uppercase;
margin-bottom: 12px;
color: var(--orange);
}
.card__grow {
flex: 1;
margin-bottom: 32px;
}
.card__title {
line-height: 1.333333333333333;
margin-bottom: 12px;
}
.card__title a {
font-weight: 700;
font-size: 18px;
text-decoration: none;
color: var(--dark-gray);
font-family: 'Lora', serif;
transition: 0.24s;
}
.card__title a:hover {
color: var(--orange);
}
.card__text {
font-size: 14px;
line-height: 1.428571428571429;
font-weight: 300;
color: var(--dark-gray);
}
.card__bottom {
display: flex;
justify-content: space-between;
align-items: center;
}
.card-author {
display: flex;
align-items: center;
}
.card-author__avatar {
margin-right: 8px;
height: 32px;
width: 32px;
border-radius: 50%;
overflow: hidden;
}
.card-author__avatar img {
width: 100%;
height: 100%;
-o-object-fit: cover;
object-fit: cover;
display: block;
}
.card-author__name {
font-size: 14px;
color: var(--light-gray);
}
.card-time {
display: flex;
align-items: center;
font-size: 14px;
line-height: 1.428571428571429;
color: var(--light-gray);
}
.card-time__icon {
margin-right: 8px;
}
.card-time__icon svg.icon {
width: 20px;
height: 20px;
fill: var(--light-gray);
}
.card_accent {
--dark-gray: #f6f5f5;
--light-gray: #f6f5f5;
--orange: #f6f5f5;
--white: #cc5a53;
}
.hidden {
display: none;
}
Пишем логику на JavaScript
За поиск соседних элементов будет отвечать функция всего лишь в одну строку
const siblings = el => [].slice.call(el.parentNode.children).filter(child => (child !== el));
Теперь посмотрим, как применить эту функцию на практике
document.addEventListener('DOMContentLoaded', () => {
const siblings = el => [].slice.call(el.parentNode.children).filter(child => (child !== el)); // объявляем функцию, которая будет возвращать соседние элементы
const cards = document.querySelectorAll('.card') // получаем все карточки
cards.forEach(card => { // для каждой карточки
card.addEventListener('mouseenter', () => { // при наведении на карточку
siblings(card).forEach(el => { // для каждого соседнего элемента
el.classList.add('card_sibling') // добавляем активный класс, который визуально ставит соседние карточки на задний план
})
})
card.addEventListener('mouseleave', () => { // если убираем курсор с карточки
siblings(card).forEach(el => { // для каждого соседнего элемента
el.classList.remove('card_sibling') // удаляем активный класс
})
})
})
})
Посмотреть результат в живую можно на Codepen
Итоги
Теперь, чтобы получить соседние элементы на чистом JavaScript, вы знаете как это сделать ;)
Буду рад, если статья оказалась полезной
Спасибо за ваше внимание и уделённое время!