I wrote a script that adapts HTML tabs for different screen resolutions. On a small screen it's an Accordion and on wider ones they're Tabs. The script is for a production site, and I'm not so good in JavaScript yet, so show me any weaknesses.
(function ($) {
// html structure
// div - selector
// // ul
// // // li.class - tabs
$.fn.tabslight = function () {
var classes = {
tabsTrigger: '.tab__trigger',
tabTypeAccordeon: 'tab-type-accordeon',
tabTypeTab: 'tab-type-tabs',
activeClass: 'current',
tabList: 'tab-list',
tabListItem: 'tab-list__item',
tabContent: 'tab-content',
tabContentItem: 'tab-content__item',
tabContent: 'tab__inner'
},
slideDuration = 300, //ms
container = $(this),
contentItems = container.find('.' + classes.tabContentItem),
isAccordeon = true,
tabsUpdate = function() {
var items = $('.' + classes.tabContentItem),
itemsTriger = $('.' + classes.tabListItem),
itemsContent = container.find('.' + classes.tabContent);
isAccordeon = ( $(window).width() <= '768' ? true : false );
if (isAccordeon) {
container.addClass( classes.tabTypeAccordeon ).removeClass( classes.tabTypeTab );
} else {
container.addClass( classes.tabTypeTab ).removeClass( classes.tabTypeAccordeon );
}
items // Set initial state for tabs
.eq(0)
.addClass(classes.activeClass) // Add active class to elements
.siblings() // find all siblings of this elements...
.removeClass(classes.activeClass); // .. and remove active class
itemsTriger // Set initial state for tab triggers
.eq(0)
.addClass(classes.activeClass) // Add active class to elements
.siblings() // find all siblings of this elements...
.removeClass(classes.activeClass); // .. and remove active class
itemsContent.removeAttr('style'); // Remove all previous styles for content (inline display: block/none after sliding animation on accordeon statement)
},
tabsList = function() {
var string ='<ul class="' + classes.tabList + '">';
$(classes.tabsTrigger).each(function(){
var item = this.outerHTML;
string += '<li class="' + classes.tabListItem + '">' + item + '</li>';
});
string += '</ul>';
container.prepend(string);// Prepend list tabs for desktop statemenm
tabsUpdate(); // First run tabs update function.
}(),
triggers = container.find(classes.tabsTrigger);
// Listen for resize, and update tabs type
window.addEventListener('resize', tabsUpdate);
triggers.on('click', function (e) {
e.preventDefault(); // Disable the default action on clicking item
if ( isAccordeon ) { // if accordeon
var item = $(this).parent(),
itemContent = item.find('.' + classes.tabContent),
items = item.siblings();
itemsContent = items.find('.' + classes.tabContent);
if ( ! item.hasClass( classes.activeClass ) ) { // if elem don't has current class
items.removeClass(classes.activeClass);
item.addClass(classes.activeClass);
itemsContent.stop(true, true).slideUp(slideDuration); // hide siblings content
itemContent.stop(true, true).slideDown(slideDuration); // show current content
} else { // if elem has current class
itemContent.stop(true, true).slideUp(slideDuration); // hide current content
item.stop(true, true).removeClass(classes.activeClass); // remove current class
}
} else { // if not accordeon
var itemTrigger = $(this).parent(),
itemTriggerSiblings = itemTrigger.siblings(),
itemTriggerNumber = itemTrigger.index(),
item = container.find('.' + classes.tabContentItem).eq(itemTriggerNumber);
itemContent = item.find('.' + classes.tabContent),
items = item.siblings();
itemsContent = items.find('.' + classes.tabContent);
if ( ! item.hasClass( classes.activeClass ) ) { // if don't has current class
itemTrigger
.add(item) // Add to set current tab content (to perform actions for both: tab and content)
.addClass(classes.activeClass) // Add active class to elements
.siblings() // find all siblings of this elements...
.removeClass(classes.activeClass); // ...and remove from them active class
}
}
});
};
$(document).ready(function(){
// Call the function
$('.tab').tabslight();
});
})(jQuery);
body {
font-family: Arial, "Helvetica Neue", Helvetica, sans-serif;
font-size: 16px; }
.wrap {
margin: 0 auto;
max-width: 1000px; }
.tab {
width: 100%; }
.tab-list, .tab-content {
list-style: none;
padding: 0;
margin: 0; }
.tab-list {
display: none; }
@media screen and (min-width: 768px) {
.tab-list {
display: flex; } }
.tab-list__item {
color: white;
margin-right: 1em;
cursor: pointer;
background-color: #666;
color: #fff;
text-decoration: none;
transition: all 0.5s ease-in; }
.tab-list__item.current, .tab-list__item:hover, .tab-list__item:active {
background-color: #aaa; }
.tab-list__item a {
display: block;
padding: .5em;
color: inherit;
text-decoration: none; }
.tab-content {
border: 2px solid #666; }
.tab-content__item .tab__inner {
display: none; }
.tab-content .tab__trigger {
background-color: #666;
color: #fff;
padding: .5em;
text-decoration: none;
transition: all 0.5s ease-in;
display: none; }
@media screen and (max-width: 767px) {
.tab-content .tab__trigger {
display: block; } }
.tab-content .tab__trigger:hover, .tab-content .tab__trigger:active {
background-color: #aaa; }
.tab-type-tabs .tab-content__item.current .tab__inner {
display: block; }
.tab-type-accordeon .tab-content__item:first-child .tab__inner {
display: block; }
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"/>
<title>tab</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">
<link rel="stylesheet" href="style.css" class="css">
</head>
<body>
<div class="wrap">
<div class="tab">
<ul class="tab-content">
<li class="tab-content__item tab1">
<a class="tab__trigger" href="#">Таб 1</a>
<div class="tab__inner">
<h2>tab 1</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dicta delectus hic, enim aperiam dolores facilis placeat quaerat dignissimos maxime minus eum, a architecto error accusamus esse debitis temporibus explicabo officia!</p>
</div>
</li>
<li class="tab-content__item tab2">
<a class="tab__trigger" href="#">Таб 2</a>
<div class="tab__inner">
<h2>tab 2</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Deleniti eligendi expedita nostrum. Maxime quaerat tempora laboriosam temporibus aspernatur impedit beatae deserunt molestias! Doloribus non adipisci nam amet commodi excepturi ut.</p>
</div>
</li>
<li class="tab-content__item tab3">
<a class="tab__trigger" href="#">Таб 3</a>
<div class="tab__inner">
<h2>tab 3</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Reiciendis animi optio quod enim ea magnam alias, quae. Quidem quaerat a tempora! In quas velit, illum aut consequuntur molestiae quidem ducimus.</p>
</div>
</li>
<li class="tab-content__item tab4">
<a class="tab__trigger" href="#">Таб 4</a>
<div class="tab__inner">
<h2>tab 4</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam, a laudantium incidunt odio nihil, corporis veniam totam ex. Amet necessitatibus, esse laudantium eius doloribus ex sunt rem, quaerat consectetur laborum.</p>
</div>
</li>
</ul><!-- .tab-list -->
</div><!-- .tab -->
</div><!-- .wrap -->
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script type="text/javascript" src="script.js"></script>
</body>
</html>