المعرفة:: JavaScript الحالة::مؤرشفة المراجع:: The Complete JavaScript Course 2022 From Zero to Expert
- Use Event Delegation while attaching an event listener instead of a attaching it to every button element.
- Use guard clause to handle clicks on empty spaces between child elements.
- Control visibility by adding/removing classes.
- Remove active classes before adding to the clicked element.
HTML
<div class="operations">
<div class="operations__tab-container">
<button
class="btn operations__tab operations__tab--1 operations__tab--active"
data-tab="1">
<span>01</span>Section
</button>
<button class="btn operations__tab operations__tab--2" data-tab="2">
<span>02</span>Section
</button>
<button class="btn operations__tab operations__tab--3" data-tab="3">
<span>03</span>Section
</button>
</div>
<div
class="operations__content operations__content--1 operations__content--active"
>
<div class="operations__icon operations__icon--1">
<svg>
<use xlink:href="img/icons.svg#icon-upload"></use>
</svg>
</div>
<h5 class="operations__header">
Header.
</h5>
<p>
Content.
</p>
</div>
<div class="operations__content operations__content--2">
<div class="operations__icon operations__icon--2">
<svg>
<use xlink:href="img/icons.svg#icon-home"></use>
</svg>
</div>
<h5 class="operations__header">
Header.
</h5>
<p>
Content.
</p>
</div>
<div class="operations__content operations__content--3">
<div class="operations__icon operations__icon--3">
<svg>
<use xlink:href="img/icons.svg#icon-user-x"></use>
</svg>
</div>
<h5 class="operations__header">
Header.
</h5>
<p>
Content.
</p>
</div>
</div>
CSS
/* OPERATIONS */
.operations {
max-width: 100rem;
margin: 12rem auto 0 auto;
background-color: #fff;
}
.operations__tab-container {
display: flex;
justify-content: center;
}
.operations__tab {
margin-right: 2.5rem;
transform: translateY(-50%);
}
.operations__tab span {
margin-right: 1rem;
font-weight: 600;
display: inline-block;
}
.operations__tab--1 {
background-color: var(--color-secondary);
}
.operations__tab--1:hover {
background-color: var(--color-secondary-darker);
}
.operations__tab--3 {
background-color: var(--color-tertiary);
margin: 0;
}
.operations__tab--3:hover {
background-color: var(--color-tertiary-darker);
}
.operations__tab--active {
transform: translateY(-66%);
}
.operations__content {
display: none;
/* JUST PRESENTATIONAL */
font-size: 1.7rem;
padding: 2.5rem 7rem 6.5rem 7rem;
}
.operations__content--active {
display: grid;
grid-template-columns: 7rem 1fr;
column-gap: 3rem;
row-gap: 0.5rem;
}
.operations__header {
font-size: 2.25rem;
font-weight: 500;
align-self: center;
}
.operations__icon {
display: flex;
align-items: center;
justify-content: center;
height: 7rem;
width: 7rem;
border-radius: 50%;
}
.operations__icon svg {
height: 2.75rem;
width: 2.75rem;
}
.operations__content p {
grid-column: 2;
}
.operations__icon--1 {
background-color: var(--color-secondary-opacity);
}
.operations__icon--2 {
background-color: var(--color-primary-opacity);
}
.operations__icon--3 {
background-color: var(--color-tertiary-opacity);
}
.operations__icon--1 svg {
fill: var(--color-secondary-darker);
}
.operations__icon--2 svg {
fill: var(--color-primary);
}
.operations__icon--3 svg {
fill: var(--color-tertiary);
}
JavaScript
tabsContainer.addEventListener('click', function (e) {
const clicked = e.target.closest('.operations__tab');
// Guard clause
if (!clicked) return;
// Remove active classes
tabs.forEach(t => t.classList.remove('operations__tab--active'));
tabsContent.forEach(c => c.classList.remove('operations__content--active'));
// Activate tab
clicked.classList.add('operations__tab--active');
// Activate content area
document
.querySelector(`.operations__content--${clicked.dataset.tab}`)
.classList.add('operations__content--active');
});