← Назад в «Блог»
11 714

Табы на JQuery и JavaScript


Сегодня разберем как делаются вкладки (табы) на JQuery и JavaScript .

Весь код для копирования в конце статьи.

Можете посмотреть демо чтобы увидеть как будет выглядеть результат. В колонке JS сверху расположен код JQuery, ниже JavaScript.

В самом начале объясню схему, по которой мы будем делать табы:

  1. Добавим вкладкам и блокам с их содержимым классы с приставкой js- для обращения к ним из JavaScript.
  2. Добавим data атрибут data-tab для идентификации наших табов. Некоторые делают табы по индексу элемента в dom-дереве, я так делать не буду, это не гибкая конструкция.
  3. При клике на вкладку, удалим активный класс у всех вкладок, добавим той, по которой кликнули, удалим активный класс у всех блоков с содержимым и добавим тому, у которого значение атрибута data-tab такое же как у атрибута data-tab нашей вкладки.

Про приставку js.
Мы добавляем отдельный класс для манипуляций из js потому что, на один класс могут быть завязаны стили, которые в дальнейшем могут быть заменены. Приставка js даст вам или другому разработчику понять что этот элемент, в частности класс, участвует в интерактивности, на нем завязаны только события javascript. Таким образом этот класс всегда будет у элемента, не смотря на стили.

В нескольких проектах я это правило игнорировал и потом на исправление багов я тратил время.

Первым делом создадим разметку для наших табов.

<!-- Общий контейнер для табов -->
<div class="tabs">
   
   <!--  Контейнер с вкладками   -->
   <ul class="tab-header">
      <li class="tab-header__item js-tab-trigger active" data-tab="1">Первая</li>
      <li class="tab-header__item js-tab-trigger" data-tab="2">Вторая</li>
      <li class="tab-header__item js-tab-trigger" data-tab="3">Третья</li>
   </ul>
   
   <!--  Контейнер с блоками, которые содержат контент вкладок   -->
   <ul class="tab-content">
      <li class="tab-content__item js-tab-content active" data-tab="1">
         Далеко-далеко за словесными, горами в стране гласных и согласных живут рыбные тексты.
      </li>
      <li class="tab-content__item js-tab-content" data-tab="2">
         Lorem ipsum, dolor sit amet consectetur adipisicing elit. Dolorum rem laboriosam cum repudiandae natus corrupti?
      </li>
      <li class="tab-content__item js-tab-content" data-tab="3">
         Далеко-далеко за словесными горами.
      </li>
   </ul>
</div>

Первой вкладке и её содержимому мы добавили класс active, чтобы по-умолчанию эти два элемента были активны. Остальные вкладки оставляем неактивными, а блоки с контентом скрываем.

Стили:

.tabs {
   width: 100%;
   max-width: 500px;
}

/* Стили для списка вкладок */
.tab-header {
   list-style: none;
   padding-left: 0;
   display: flex;
   align-items: center;
   justify-content: flex-start;
   margin: 0;
}

/* Стили для вкладки */
.tab-header__item {
   padding: 10px 20px;
   margin-right: 5px;
   cursor: pointer;
   border: 1px solid #ddd;
}

/* Стили для активной вкладки */
.tab-header__item.active {
   color: red;
   border-bottom: none;
   position: relative;
   background-color: #fff;
}

/* Стиль для списка контейнеров с содержимым вкладок */
.tab-content {
   list-style: none;
   padding: 0;
   margin: 0;
}

/* Стили для контейнера с содержимым вкладки. По умолчанию скрыт. */
.tab-content__item {
   display: none;
   padding: 20px;
   border: 1px solid #ddd;
   margin-top: -1px;
}

/* Стили для активного контейнера вкладки */
.tab-content__item.active {
   display: block;
}

Стилизовать — дело вкуса, если вы не против я стилизовал на свой вкус.

Здесь мы определили вид наших вкладок и контенеров с содержимым. Важным для понимания будут стили для вкладок, активной вкладки, контенеров, активного контейнера.

Тут все довольно просто. Активной вкладке добавляем изменение цвета, остальные остаются с серым цветом. Активный блок показываем, остальные скрываем.

Разберем Jquery код:

Итак, первое что нужно сделать, обработак клик по каждому элементу.

$('.js-tab-trigger').click(function() {
     // клик! 
})

Теперь нам нужно получить идентификатор нашей вкладки и найти контент с таким же значением data-tab.

$('.js-tab-trigger').click(function() {
   var id = $(this).attr('data-tab'), // 1
       content = $('.js-tab-content[data-tab="'+ id +'"]'); // 2
});
  1. Получили значение атрибута data-tab у текущего элемента
  2. Здесь происходит конкатенация (соединение) строк. В селекторе jquery мы разрываем строку и вставляем туда значение нашей переменной id с помощью операторов сложения «+». Если вы складываете строки, оператор «+» соединит их. В результате конкатенации строк мы получили такой селектор: ‘.js-tab-content[data-tab="3″]’ (содержимое data-tab меняется в зависимости от вкладки).
    Подробнее здесь.

Отлично, теперь мы знаем и вкладку по которой мы кликнули и контейнер с содержимым этой вкладки. Теперь дело за малым, поработать с классами. Дополним наш предыдущий код.


$('.js-tab-trigger').click(function() {
   var id = $(this).attr('data-tab'),
       content = $('.js-tab-content[data-tab="'+ id +'"]');
   
   $('.js-tab-trigger.active').removeClass('active'); // 1
   $(this).addClass('active'); // 2
   
   $('.js-tab-content.active').removeClass('active'); // 3
   content.addClass('active'); // 4
});
  1. Удалили класс active у активной вкладки
  2. Добавили класс active вкладке по которой кликнули
  3. Удалили класс active у активного контейнера с содержимым
  4. Добавили класс active контейнеру который должен быть активным

Вот и все, код на JQuery занял у нас всего лишь 10 строк кода. Рассмотрим JavaSсript.

Код на JavaScript не сложнее чем jquery код. Когда я начинал знакомиться с JQuery, в одном из проектов она не хотела работать, там была сложная структура битрикс сайта и я потратил много времени чтобы заставить её работать. После безрезультатных попыток я психанул и написал табы на JavaScript, до этого я боялся его, но написав табы без JQuery удивился, это не так сложно как кажется.

Разберем JavaScript код:

Прежде чес обработать клик по вкладке, объявим несколько переменных для наших вкладок и контенеров с содержимым.

var jsTriggers = document.querySelectorAll('.js-tab-trigger'),
    jsContents = document.querySelectorAll('.js-tab-content');

Теперь можно обработать клик по вкладкам.

jsTriggers.forEach(function(trigger) { // 1
   trigger.addEventListener('click', function() { // 2
      // клик!
   });
});
  1. Циклом перебираем элементы в массива. В массиве у нас лежат dom-элементы, то есть наши вкладки.
  2. Каждому элементу добавляем функцию-обработчик при событии клика.

Теперь в функции-обработчике объявим несколько переменных для удобной манипуляции. Все можно сделать и без переменных, но мы будем делать по-хорошему.

var id = this.getAttribute('data-tab'), // 1
    content = document.querySelector('.js-tab-content[data-tab="'+id+'"]'), // 2
    activeTrigger = document.querySelector('.js-tab-trigger.active'), // 3
    activeContent = document.querySelector('.js-tab-content.active'); // 4
  1. Получаем идентификатор вкладки.
  2. Ищем контейнер с таким же значением атрибута data-tab.
  3. Ищем активную вкладку.
  4. Ищем активный контейнер.

В заключении поработаем с классами:

var jsTriggers = document.querySelectorAll('.js-tab-trigger'),
    jsContents = document.querySelectorAll('.js-tab-content');

jsTriggers.forEach(function(trigger) {
   trigger.addEventListener('click', function() {
      var id = this.getAttribute('data-tab'),
          content = document.querySelector('.js-tab-content[data-tab="'+id+'"]'),
          activeTrigger = document.querySelector('.js-tab-trigger.active'),
          activeContent = document.querySelector('.js-tab-content.active');
      
      activeTrigger.classList.remove('active'); // 1
      trigger.classList.add('active'); // 2
      
      activeContent.classList.remove('active'); // 3
      content.classList.add('active'); // 4
   });
});
  1. Удалили класс active у активной вкладки
  2. Добавили класс active вкладке по которой кликнули
  3. Удалили класс active у активного блока с содержимым
  4. Добавили класс active контейнеру который должен быть активным

Итоговый код

HTML

<!-- Общий контейнер для табов -->
<div class="tabs">
   
   <!--  Контейнер с вкладками   -->
   <ul class="tab-header">
      <li class="tab-header__item js-tab-trigger active" data-tab="1">Первая</li>
      <li class="tab-header__item js-tab-trigger" data-tab="2">Вторая</li>
      <li class="tab-header__item js-tab-trigger" data-tab="3">Третья</li>
   </ul>
   
   <!--  Контейнер с блоками, которые содержат контент вкладок   -->
   <ul class="tab-content">
      <li class="tab-content__item js-tab-content active" data-tab="1">
         Далеко-далеко за словесными, горами в стране гласных и согласных живут рыбные тексты.
      </li>
      <li class="tab-content__item js-tab-content" data-tab="2">
         Lorem ipsum, dolor sit amet consectetur adipisicing elit. Dolorum rem laboriosam cum repudiandae natus corrupti?
      </li>
      <li class="tab-content__item js-tab-content" data-tab="3">
         Далеко-далеко за словесными горами.
      </li>
   </ul>
</div>

CSS

.tabs {
   width: 100%;
   max-width: 500px;
}

/* Стили для списка вкладок */
.tab-header {
   list-style: none;
   padding-left: 0;
   display: flex;
   align-items: center;
   justify-content: flex-start;
   margin: 0;
}

/* Стили для вкладки */
.tab-header__item {
   padding: 10px 20px;
   margin-right: 5px;
   cursor: pointer;
   border: 1px solid #ddd;
}

/* Стили для активной вкладки */
.tab-header__item.active {
   color: red;
   border-bottom: none;
   position: relative;
   background-color: #fff;
}

/* Стиль для списка контейнеров с содержимым вкладок */
.tab-content {
   list-style: none;
   padding: 0;
   margin: 0;
}

/* Стили для контейнера с содержимым вкладки. По умолчанию скрыт. */
.tab-content__item {
   display: none;
   padding: 20px;
   border: 1px solid #ddd;
   margin-top: -1px;
}

/* Стили для активного контейнера вкладки */
.tab-content__item.active {
   display: block;
}

jQuery или

Не забудьте подключить библиотеку jQuery. Я подключаю через cdnjs — https://cdnjs.com/libraries/jquery

$('.js-tab-trigger').click(function() {
   var id = $(this).attr('data-tab'),
       content = $('.js-tab-content[data-tab="'+ id +'"]');
   
   $('.js-tab-trigger.active').removeClass('active');
   $(this).addClass('active');
   
   $('.js-tab-content.active').removeClass('active');
   content.addClass('active');
});

JavaScript

var jsTriggers = document.querySelectorAll('.js-tab-trigger'),
    jsContents = document.querySelectorAll('.js-tab-content');

jsTriggers.forEach(function(trigger) {
   trigger.addEventListener('click', function() {
      var id = this.getAttribute('data-tab'),
          content = document.querySelector('.js-tab-content[data-tab="'+id+'"]'),
          activeTrigger = document.querySelector('.js-tab-trigger.active'),
          activeContent = document.querySelector('.js-tab-content.active');
      
      activeTrigger.classList.remove('active');
      trigger.classList.add('active');
      
      activeContent.classList.remove('active');
      content.classList.add('active');
   });
});
Полезно
31
1
Непонятно
19
Поделиться
Отправить
Линкануть
Вотсапнуть

Подпишись на крутой канал о фрилансе

Я делюсь там фишками о фрилансе: деньги, клиенты, автоматизация, фриланс. Раньше это был закрытый материал с платным доступом. Сейчас он открыт. Иногда подписчикам будет открываться платные материалы. Подписаться

← Назад в «Блог»

15 комментария

Спасибо за понятный скрипт и объяснения

спасибо за статью, помогите справиться с проблемой размещения двух табов на одной странице. работает только первый

Добрый день. Хорошая статья, большое спасибо.

Быть можете подскажите каким образом реализовать открытие нужного таба при клике на ссылку.

site.ru/#tab-1 — при переходе откроется первый таб

site.ru/#tab-2 — при переходе откроется второй таб

Учитывая то, что табы на этой же странице, можно в href оставить только #tab-1.

Если так, что вы просто достаёте из атрибута href значения и ищете контейнеры с data-tab=»#tab-1″.

<a href=»#tab-1″>tab</a>

<div data-tab=»#tab-1″>container</div>

Можно же вообще обойтись без JS и сделать то же самое на чистом CSS с помощью radio:checked

Как сделать что-бы выбранная вкладка, не сбрасывалась после перезагрузке странице , на исходную вкладку ? а оставалась на выбранной кладке ???

Хорошее решение, но так же интересует возможность размещение несколько табов на страницу на jquery!

Спасибо за статью!
Можете дать ссылку для пояснения вот этого обращения .js-tab-content[data-tab=»‘+id+'»]?

спасибо большое! ваш код здорово меня выручил!

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *