JSFiddle - React, Tailwind, and code Playground
by aka_SKIff
HTML
<div class="tabs-cnt" data-tabs-list>
<div class="tabs__list" data-tabs data-target="_login_">
<a href="#_login_1" class="tabs__item active" data-tabs-trigger>У МЕНЯ ЕСТЬ АККАУНТ</a>
<a href="#_login_2" class="tabs__item" data-tabs-trigger>У МЕНЯ НЕТ АККАУНТА</a>
</div>
</div>
<div class="tabs__content" data-tabs-content id="_login_">
<div class="tabs__pane active" data-tabs-pane id="_login_1">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ex rerum ratione nihil, dolor maxime rem ducimus pariatur doloremque. Nihil, molestias. Blanditiis tempora facere dicta assumenda rem enim nisi, labore fugit.
</div>
<div class="tabs__pane" data-tabs-pane id="_login_2">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Voluptatem architecto repudiandae obcaecati dolor saepe nesciunt quod asperiores adipisci eligendi, eius laborum unde aliquam sed vel illum neque soluta, dicta ut. Lorem ipsum dolor sit amet, consectetur
adipisicing elit. Perferendis numquam dolor, iste aperiam natus modi illum explicabo odit fuga atque voluptatem amet sapiente, nihil libero cum dolore velit. Eveniet, quaerat.
</div>
</div>
SCSS
[data-tabs-content] {
position: relative;
}
[data-tabs-pane] {
position: relative;
left: 0;
top: 0;
display: none;
&.active {
display: block;
}
}
.tabs-cnt {
position: relative;
}
.tabs__list {
border-bottom: 1px solid rgba(35, 31, 32, 0.1);
text-align: center;
}
.tabs__item {
font-size: 14px;
color: black;
text-transform: uppercase;
letter-spacing: 2px;
margin-left: 15px;
margin-right: 15px;
display: inline-block;
vertical-align: middle;
padding-bottom: 25px;
border-bottom: 2px solid transparent;
margin-bottom: -2px;
&.active {
border-bottom: 2px solid #000;
[data-tabs-list] & {
border-bottom: 2px solid transparent;
}
}
}
.tabs__item--letters {
margin-left: 0;
margin-right: 0;
font-size: 16px;
line-height: 20px;
width: 30px;
text-align: center;
padding-bottom: 14px;
&:first-child {
width: auto;
margin-right: 28px;
}
&:last-child {
width: 50px;
}
}
.tabs__underline {
height: 2px;
position: absolute;
left: 50%;
background: black;
width: 200px;
bottom: -1px;
transition: left 0.4s, width 0.4s;
}
JavaScript
function closest(el, selector) {
const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector;
while (el) {
if (matchesSelector.call(el, selector)) {
break;
}
el = el.parentElement;
}
return el;
}
const events = {
handleTabTriggerClick: function(e) {
e.preventDefault();
const _this = this;
if (this.classList.contains('active')) return false;
const _tabs = closest(_this, '[data-tabs]');
const _triggers = _tabs.querySelectorAll('[data-tabs-trigger]');
const needleId = _this.getAttribute('href').substr(1);
const _panesCnt = document.querySelector('#' + _tabs.getAttribute('data-target'));
const _panes = _panesCnt.querySelectorAll('[data-tabs-pane]');
const _targetPane = document.querySelector('#' + needleId);
for (let _trigger of _triggers) {
_trigger.classList.remove('active');
}
for (let _pane of _panes) {
_pane.classList.remove('active');
}
_this.classList.add('active');
_targetPane.classList.add('active');
setActiveTab(_this);
return false;
}
}
function initTabs() {
const _tabs = Array.prototype.slice.call(document.querySelectorAll('[data-tabs]'));
if (_tabs.length) {
_tabs.forEach(function(_tab) {
const _tabTriggers = Array.prototype.slice.call(_tab.querySelectorAll('[data-tabs-trigger]'));
_tabTriggers.forEach(function(_tabTrigger) {
_tabTrigger.addEventListener('click', events.handleTabTriggerClick);
if (_tabTrigger.classList.contains('active')) {
setActiveTab(_tabTrigger);
}
});
});
}
}
function setActiveTab(tabTrigger) {
const cnt = closest(tabTrigger, '[data-tabs-list]');
const triggerWidth = tabTrigger.scrollWidth;
const triggerleft = tabTrigger.offsetLeft;
let underline = cnt.querySelector('.tabs__underline');
if (!underline) {
underline = document.createElement('i');
...