В данном уроке мы создадим стильные табы на JS. Сделаем их на чистом JS и CSS, без использования библиотек. В процессе вы поймете как сделать табы, сможете стилизовать их под свои требования.
Также я добавил в код CSS-переменную, которая содержит количество табов. Эта переменная меняется динамически благодаря скрипту. И если в дальнейшем вы добавите новые табы, но вам не придется делать изменения в коде.
Полезные ссылки
Объяснение кода можете найти в видеоуроке.
Стартовый проект для работы скачивайте на GitHub.
Пример работы табов смотрите по ссылке.
HTML разметка
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="reset.css" />
<link rel="stylesheet" href="style.css" />
<title>Document</title>
</head>
<body>
<div class="tab">
<div class="tab__btns">
<div class="tab__btn"><i class="fab fa-windows"></i> Windows</div>
<div class="tab__btn"><i class="fab fa-linux"></i> Linux</div>
<div class="tab__btn"><i class="fab fa-apple"></i> iOS</div>
<div class="tab__btn"><i class="fab fa-android"></i> Android</div>
</div>
<div class="tab__indicator" id="tab_indicator"></div>
<div class="tab__body">
<div class="tab__slide">
<h1>Windows App</h1>
<p>
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Fugiat
quas quia at laudantium corrupti quidem temporibus cupiditate
voluptatum eius quo tenetur, perspiciatis quis? Voluptates cumque
reiciendis aspernatur exercitationem assumenda sed sequi totam
pariatur quo nostrum quod laudantium mollitia illum soluta
voluptatem, ad modi repellat optio saepe tenetur nisi. Tenetur,
optio.
</p>
<a href="#">Download on Windows Store</a>
</div>
<div class="tab__slide">
<h1>Linux App</h1>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Ullam
accusamus voluptatem placeat fuga asperiores molestiae sapiente
omnis repellendus? Itaque voluptatum, dolore, aliquid reiciendis
sequi error ex quidem quod possimus laboriosam modi ad, ducimus
neque blanditiis? Ea adipisci omnis modi accusantium sapiente
facilis quis, deserunt veniam perferendis aspernatur ullam ex nulla!
</p>
<a href="#">Download on repository</a>
</div>
<div class="tab__slide">
<h1>iOS App</h1>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Eveniet,
soluta ad! Dolorum expedita laboriosam tempore illum, magni minus
sed nulla dicta ipsum doloribus alias exercitationem at placeat
saepe odit maiores aliquam accusantium eveniet officia aut quas
velit. Fugiat quam sed, sint aliquam dolorum debitis nemo adipisci,
natus beatae perspiciatis qui.
</p>
<a href="#">Dowload on App Store</a>
</div>
<div class="tab__slide">
<h1>Android App</h1>
<p>
Lorem ipsum dolor sit, amet consectetur adipisicing elit. Qui
aliquam doloremque a illum autem, suscipit unde, expedita voluptates
deserunt quam ullam ad mollitia velit accusamus. A, corrupti dicta
aut exercitationem minima quod fugiat temporibus eius, tempore in
doloremque molestias ut itaque, omnis molestiae rerum expedita
consequatur suscipit soluta vitae id.
</p>
<a href="#">Download on Play Market</a>
</div>
</div>
</div>
<script
src="https://kit.fontawesome.com/fce9a50d02.js"
crossorigin="anonymous"
></script>
<script src="app.js"></script>
</body>
</html>
CSS стили
@import url("https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap");
:root {
--num-btns: 0;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
*,
*::after,
*::before {
box-sizing: inherit;
}
body {
font-family: "Roboto", sans-serif;
font-size: 16px;
line-height: 1.2;
width: 100%;
min-height: 100vh;
background-color: #f0f8ff;
}
.tab {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: #fff;
width: 600px;
height: 400px;
overflow: hidden;
border-radius: 10px;
box-shadow: 4px 4px 8px 0px rgba(34, 60, 80, 0.2);
padding: 20px 30px;
}
.tab__btns {
display: flex;
height: 60px;
align-items: center;
}
.tab__btns > div {
width: calc(100% / var(--num-btns));
text-align: center;
color: #778899;
font-size: 18px;
font-weight: 600;
cursor: pointer;
outline: none;
}
.tab__btns > div > i {
display: block;
margin-bottom: 5px;
}
.tab__btns > div.active {
color: #9370db;
}
.tab__indicator {
position: relative;
left: 0;
height: 3px;
background-color: #9370db;
width: calc(100% / var(--num-btns));
transition: 0.2s;
}
.tab__body {
position: relative;
height: calc(100% - 60px);
padding: 10px 5px;
}
.tab__body > div {
position: absolute;
top: -200%;
opacity: 0;
transform: scale(0.9);
transition: opacity 500ms ease-in-out 0ms, transform 500ms ease-in-out 0ms;
}
.tab__body > div.active {
top: 0;
opacity: 1;
transform: scale(1);
}
.tab__body > div > h1 {
font-size: 25px;
font-weight: 600;
color: #2f4f4f;
margin-top: 40px;
margin-bottom: 20px;
}
.tab__body > div > p {
color: #778899;
font-size: 20px;
margin-bottom: 20px;
}
.tab__body > div > a {
color: #4169e1;
text-decoration: none;
font-size: 20px;
}
JS скрипт
const tabBtns = Array.from(document.querySelectorAll(".tab__btn"));
const tabIndicator = document.querySelector("#tab_indicator");
const tabSlide = Array.from(document.querySelectorAll(".tab__slide"));
const root = document.querySelector(":root");
const numBtns = tabBtns.length;
root.style.setProperty("--num-btns", numBtns);
tabBtns[0].classList.add("active");
tabSlide[0].classList.add("active");
let activeBtn = tabBtns[0];
let activeSlide = tabSlide[0];
tabBtns.forEach((el) => {
el.addEventListener("click", onTabBtnClick);
});
function onTabBtnClick(e) {
e.preventDefault();
const btn = e.target.closest(".tab__btn");
changeBtn(btn);
}
function changeBtn(btn) {
if (btn.classList.contains("active")) {
return;
}
activeBtn.classList.remove("active");
btn.classList.add("active");
activeBtn = btn;
changeIndicator(btn);
}
function changeIndicator(btn) {
const indexBtn = tabBtns.indexOf(btn);
tabIndicator.style.left = `calc(${indexBtn}*100%/${numBtns})`;
changeSlide(indexBtn);
}
function changeSlide(index) {
activeSlide.classList.remove("active");
tabSlide[index].classList.add("active");
activeSlide = tabSlide[index];
}