Перейти к содержимому

Как сделать табы javascript

  • автор:

Как реализовать табы на чистом Javascript

Разберем решение популярной задачи в веб-разработке – создание табов. Мы хотим чтобы они были реализованы без использования фреймворков вроде Bootstrap и jQuery, только чистый Javascript.

Как и обычно, напишем HTML табов:

 
Tab 1
Tab content 1

body < color: #666666; >a < color: #666666; >.nav-tabs < display: flex; >.nav-tab < font-size: 20px; margin-right: 10px; padding: 20px 30px 20px 30px; border: 2px solid#eeeeee; border-bottom: 0; text-decoration: none; >.nav-tab.active < background: #eeeeee; cursor: default; >.tab-content < font-size: 20px; background: #eeeeee; >.tab-pane < display: none; padding: 30px; >.tab-pane.active

А теперь реализуем логику.

var tabNavs = document.querySelectorAll(".nav-tab"); var tabPanes = document.querySelectorAll(".tab-pane"); for (var i = 0; i < tabNavs.length; i++) < tabNavs[i].addEventListener("click", function(e)< e.preventDefault(); var activeTabAttr = e.target.getAttribute("data-tab"); for (var j = 0; j < tabNavs.length; j++) < var contentAttr = tabPanes[j].getAttribute("data-tab-content"); if (activeTabAttr === contentAttr) < tabNavs[j].classList.add("active"); tabPanes[j].classList.add("active"); >else < tabNavs[j].classList.remove("active"); tabPanes[j].classList.remove("active"); >>; >); >

Идея в том, чтобы сравнивать data-атрибут целевого таба с data-атрибутом его содержимого. Если они совпадают содержимому присваиваем класс active , а все остальное скрываем.

Как создать вкладки на JavaScript

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

Рассмотрим самый простой способ создания вкладок на JavaScript, который заключается использовании data-атрибутов. Мы создадим HTML разметку, которая будет состоять из блока с навигацией по вкладкам и блоком с вкладками. Вкладкам мы задаем id с названием данной вкладки. Затем мы добавим data-атрибут data-tab к кнопкам со значением id вкладки, к которой они относятся. Далее при клике на кнопку мы будем добавлять класс _active нажатой кнопке и соответствующей вкладке.

Навигация по табам не обязательно должна быть кнопками, в зависимости от вашего проекта, это могу быть например карточки или тому подобное.

 
Контент 1
Контент 2
Контент 3
Контент 4

В CSS скрываем вкладки с контентом у которых нет класса _active

.tabs__item:not(._active)

И пишем JavaScript:

// получаем все кнопки навигации const tabsButtons = document.querySelectorAll('.tabs__button'); // Проходимся по всем кнопкам tabsButtons.forEach(btn => < // вешаем на каждую кнопку обработчик события клик btn.addEventListener('click', () => < // Получаем предыдущую активную кнопку const prevActiveItem = document.querySelector('.tabs__item._active'); // Получаем предыдущую активную вкладку const prevActiveButton = document.querySelector('.tabs__button._active'); // Проверяем есть или нет предыдущая активная кнопка if (prevActiveButton) < //Удаляем класс _active у предыдущей кнопки если она есть prevActiveButton.classList.remove('_active'); >// Проверяем есть или нет предыдущая активная вкладка if (prevActiveItem) < // Удаляем класс _active у предыдущей вкладки если она есть prevActiveItem.classList.remove('_active'); >// получаем id новой активной вкладки, который мы перем из атрибута data-tab у кнопки const nextActiveItemId = `#$`; // получаем новую активную вкладку по id const nextActiveItem = document.querySelector(nextActiveItemId); // добавляем класс _active кнопке на которую нажали btn.classList.add('_active'); // добавляем класс _active новой выбранной вкладке nextActiveItem.classList.add('_active'); >); >)

Если необходимо чтобы первая вкладка была сразу активна, то просто добавьте в разметке класс _active необходимой кнопке и вкладке.

Теперь вы знаете как сделать табы на чистом JavaScript. Остается дело за малым, стилизовать вкладки под свой проект.

Вариaнт адаптивных вкладок (tabs) на JavaScript

Для начала реализуем логику для вкладок, которые мы сверстали выше.

Вся логика сводится к тому, чтобы при переключении сравнивать значения data-атрибутов кнопок и блоков контента. Если значение data-атрибута у блока контента совпадает с data-атрибутом кнопки, то отображаем соответствующий блок контента

Отличие данного способа в том, что порядок расположения кнопок и порядок расположения блоков контента в HTML-структуре могут не совпадать, при этом переключение будет работать корректно, что невозможно при реализации вкладок по индексу

Код с комментариями

document.addEventListener('DOMContentLoaded', () => < // Структура страницы загружена и готова к взаимодействию const tabs = () => < // объявляем основную функцию для вкладок, чтобы вся логика была в одном месте const head = document.querySelector('.tabs__head') // ищем элемент с кнопками и записываем в константу const body = document.querySelector('.tabs__body') // ищем элемент с контентом и записываем в константу const getActiveTabName = () => < // объявляем функцию для получения названия активной вкладки return head.querySelector('.tabs__caption_active').dataset.tab // возвращаем значение data-tab активной кнопки >const setActiveContent = () => < // объявляем функцию для установки активного элемента контента if (body.querySelector('.tabs__content_active')) < // если уже есть активный элемент контента body.querySelector('.tabs__content_active').classList.remove('tabs__content_active') // то скрываем его >body.querySelector(`[data-tab=$]`).classList.add('tabs__content_active') // затем ищем элемент контента, у которого значение data-tab совпадает со значением data-tab активной кнопки и отображаем его > // проверяем при загрузке страницы, есть ли активная вкладка if (!head.querySelector('.tabs__caption_active')) < // если активной вкладки нет head.querySelector('.tabs__caption').classList.add('tabs__caption_active') // то делаем активной по-умолчанию первую вкладку >setActiveContent(getActiveTabName()) // устанавливаем активный элемент контента в соответствии с активной кнопкой при загрузке страницы head.addEventListener('click', e => < // при клике на .tabs__head const caption = e.target.closest('.tabs__caption') // узнаем, был ли клик на кнопке if (!caption) return // если клик был не на кнопке, то прерываем выполнение функции if (caption.classList.contains('tabs__caption_active')) return // если клик был на активной кнопке, то тоже прерываем выполнение функции и ничего не делаем if (head.querySelector('.tabs__caption_active')) < // если уже есть активная кнопка head.querySelector('.tabs__caption_active').classList.remove('tabs__caption_active') // то удаляем ей активный класс >caption.classList.add('tabs__caption_active') // затем добавляем активный класс кнопке, на которой был клик setActiveContent(getActiveTabName()) // устанавливаем активный элемент контента в соответствии с активной кнопкой >) > tabs() // вызываем основную функцию >) 

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

Чтобы избежать этого, создадим новую функцию на основе предыдущей, которая будет принимать значения переданных CSS классов и селекторов и подставлять эти значения в необходимых частях кода

Функция c параметрами

Добавим для примера еще один блок с вкладками

     Tabs    
Home
Portfolio
About
Home lorem ipsum dolor sit amet, consectetur adipisicing elit. Mollitia sit, repellat assumenda excepturi minima debitis atque nulla quibusdam iste eligendi voluptas, obcaecati nihil necessitatibus vel illum itaque ea molestias vero! Home lorem ipsum dolor sit amet, consectetur adipisicing elit. Mollitia sit, repellat assumenda excepturi minima debitis atque nulla quibusdam iste eligendi voluptas, obcaecati nihil necessitatibus vel illum itaque ea molestias vero!
Portfolio lorem ipsum dolor sit amet, consectetur adipisicing elit. Id magni sit, enim tenetur animi eius ea, similique optio nostrum quibusdam ex, dolores dolorem. Recusandae quo molestiae modi saepe ratione numquam!
About lorem ipsum dolor sit amet, consectetur adipisicing elit. Mollitia quibusdam nemo qui numquam magnam! In sunt, ut cum nulla, accusantium mollitia et illum voluptate repudiandae! Magnam alias, iure saepe animi.
Home
Portfolio
About
Contact
Home lorem ipsum dolor sit amet, consectetur adipisicing elit. Mollitia sit, repellat assumenda excepturi minima debitis atque nulla quibusdam iste eligendi voluptas, obcaecati nihil necessitatibus vel illum itaque ea molestias vero!
Portfolio lorem ipsum dolor sit amet, consectetur adipisicing elit. Id magni sit, enim tenetur animi eius ea, similique optio nostrum quibusdam ex, dolores dolorem. Recusandae quo molestiae modi saepe ratione numquam!
About lorem ipsum dolor sit amet, consectetur adipisicing elit. Mollitia quibusdam nemo qui numquam magnam! In sunt, ut cum nulla, accusantium mollitia et illum voluptate repudiandae! Magnam alias, iure saepe animi.
Contact lorem ipsum dolor sit amet, consectetur adipisicing elit. Quod, ullam ducimus et facere nisi a dicta, ea, quae minima sequi expedita facilis doloremque excepturi, earum soluta magni! Dolores, expedita, ea.

Теперь при объявлении функции tabs указываем параметры, которые будет принимать функция

При вызове функции, все параметры обязательны для ввода, и порядок передаваемых параметров должен соблюдаться

JavaScript код с комментариями

document.addEventListener('DOMContentLoaded', () => < // Структура страницы загружена и готова к взаимодействию const tabs = (tabsSelector, tabsHeadSelector, tabsBodySelector, tabsCaptionSelector, tabsCaptionActiveClass, tabsContentActiveClass) => < // объявляем основную функцию tabs, которая будет принимать CSS классы и селекторы const tabs = document.querySelector(tabsSelector) // ищем на странице элемент по переданному селектору основного элемента вкладок и записываем в константу const head = tabs.querySelector(tabsHeadSelector) // ищем в элементе tabs элемент с кнопками по переданному селектору и записываем в константу const body = tabs.querySelector(tabsBodySelector) // ищем в элементе tabs элемент с контентом по переданному селектору и записываем в константу const getActiveTabName = () =>< // функция для получения названия активной вкладки return head.querySelector(`.$`).dataset.tab // возвращаем значение data-tab активной кнопки > const setActiveContent = () => < // функция для установки активного элемента контента if (body.querySelector(`.$`)) < // если уже есть активный элемент контента body.querySelector(`.$`).classList.remove(tabsContentActiveClass) // то скрываем его > body.querySelector(`[data-tab=$]`).classList.add(tabsContentActiveClass) // затем ищем элемент контента, у которого значение data-tab совпадает со значением data-tab активной кнопки и отображаем его > // проверяем при загрузке страницы, есть ли активная вкладка if (!head.querySelector(`.$`)) < // если активной вкладки нет head.querySelector(tabsCaptionSelector).classList.add(tabsCaptionActiveClass) // то делаем активной по-умолчанию первую вкладку >setActiveContent(getActiveTabName()) // устанавливаем активный элемент контента в соответствии с активной кнопкой при загрузке страницы head.addEventListener('click', e => < // при клике на элемент с кнопками const caption = e.target.closest(tabsCaptionSelector) // узнаем, был ли клик на кнопке if (!caption) return // если клик был не на кнопке, то прерываем выполнение функции if (caption.classList.contains(tabsCaptionActiveClass)) return // если клик был на активной кнопке, то тоже прерываем выполнение функции и ничего не делаем if (head.querySelector(`.$`)) < // если уже есть активная кнопка head.querySelector(`.$`).classList.remove(tabsCaptionActiveClass) // то удаляем ей активный класс > caption.classList.add(tabsCaptionActiveClass) // затем добавляем активный класс кнопке, на которой был клик setActiveContent(getActiveTabName()) // устанавливаем активный элемент контента в соответствии с активной кнопкой >) > tabs('.section__tabs', '.tabs__head', '.tabs__body', '.tabs__caption', 'tabs__caption_active', 'tabs__content_active') // вызываем основную функцию tabs для синих вкладок .section__tabs tabs('.about__tabs', '.tabs__head', '.tabs__body', '.tabs__caption', 'tabs__caption_active', 'tabs__content_active') // вызываем основную функцию tabs для зелёных вкладок .about__tabs >) 

Получаем следующий результат — вкладки активны

Home lorem ipsum dolor sit amet, consectetur adipisicing elit. Mollitia sit, repellat assumenda excepturi minima debitis atque nulla quibusdam iste eligendi voluptas, obcaecati nihil necessitatibus vel illum itaque ea molestias vero! Home lorem ipsum dolor sit amet, consectetur adipisicing elit. Mollitia sit, repellat assumenda excepturi minima debitis atque nulla quibusdam iste eligendi voluptas, obcaecati nihil necessitatibus vel illum itaque ea molestias vero!

Portfolio lorem ipsum dolor sit amet, consectetur adipisicing elit. Id magni sit, enim tenetur animi eius ea, similique optio nostrum quibusdam ex, dolores dolorem. Recusandae quo molestiae modi saepe ratione numquam!

About lorem ipsum dolor sit amet, consectetur adipisicing elit. Mollitia quibusdam nemo qui numquam magnam! In sunt, ut cum nulla, accusantium mollitia et illum voluptate repudiandae! Magnam alias, iure saepe animi.

Home lorem ipsum dolor sit amet, consectetur adipisicing elit. Mollitia sit, repellat assumenda excepturi minima debitis atque nulla quibusdam iste eligendi voluptas, obcaecati nihil necessitatibus vel illum itaque ea molestias vero!

Portfolio lorem ipsum dolor sit amet, consectetur adipisicing elit. Id magni sit, enim tenetur animi eius ea, similique optio nostrum quibusdam ex, dolores dolorem. Recusandae quo molestiae modi saepe ratione numquam!

About lorem ipsum dolor sit amet, consectetur adipisicing elit. Mollitia quibusdam nemo qui numquam magnam! In sunt, ut cum nulla, accusantium mollitia et illum voluptate repudiandae! Magnam alias, iure saepe animi.

Contact lorem ipsum dolor sit amet, consectetur adipisicing elit. Quod, ullam ducimus et facere nisi a dicta, ea, quae minima sequi expedita facilis doloremque excepturi, earum soluta magni! Dolores, expedita, ea.

Вкладки на основе JavaScript классов

Для разнообразия/сравнения, можем также написать функциональность вкладок на основе JavaScript классов

Чтобы познакомиться с JavaScript классами, внизу статьи будут ссылки на документацию

В данном примере просто посмотрим еще один способ

В качестве параметров будем передавать JavaScript объект, а также выделим некоторую функциональность в отдельные методы

Код с комментариями

document.addEventListener('DOMContentLoaded', () => < // Структура страницы загружена и готова к взаимодействию class Tabs < // объявляем JavaScript класс Tabs constructor(config) < // специальный метод constructor принимает объект со значениями CSS классов и селекторов this.tabs = config.tabsSelector // записываем в экземпляр JavaScript класса переданный селектор основного элемента вкладок this.head = config.tabsHeadSelector // записываем в экземпляр JavaScript класса переданный селектор элемента c кнопками this.body = config.tabsBodySelector // записываем в экземпляр JavaScript класса переданный селектор элемента c контентом this.caption = config.tabsCaptionSelector // записываем в экземпляр JavaScript класса переданный селектор элемента кнопки this.captionActiveClass = config.tabsCaptionActiveClass // записываем в экземпляр JavaScript класса переданный активный CSS класс элемента кнопки this.contentActiveClass = config.tabsContentActiveClass // записываем в экземпляр JavaScript класса переданный активный CSS класс элемента контента >getActiveTabName(head) < // метод для получения названия активной вкладки return head.querySelector(`.$`).dataset.tab // возвращаем значение data-tab активной кнопки > setActiveContent(head, body) < // метод для установки активного элемента контента if (body.querySelector(`.$`)) < // если уже есть активный элемент контента body.querySelector(`.$`).classList.remove(this.contentActiveClass) // то скрываем его > body.querySelector(`[data-tab=$]`).classList.add(this.contentActiveClass) // затем ищем элемент контента, у которого значение data-tab совпадает со значением data-tab активной кнопки и отображаем его > onLoad(head, body) < // метод для описания логики при загрузке страницы // проверяем при загрузке страницы, есть ли активная вкладка if (!head.querySelector(`.$`)) < // если активной вкладки нет head.querySelector(this.caption).classList.add(this.captionActiveClass) // то делаем активной по-умолчанию первую вкладку >this.setActiveContent(head, body) // устанавливаем активный элемент контента в соответствии с активной кнопкой при загрузке страницы > onClick(head, body) < // метод для описания логики при клике на элемент с кнопками head.addEventListener('click', e =>< // при клике на элемент с кнопками const caption = e.target.closest(this.caption) // узнаем, был ли клик на кнопке if (!caption) return // если клик был не на кнопке, то прерываем выполнение метода if (caption.classList.contains(this.captionActiveClass)) return // если клик был на активной кнопке, то тоже прерываем выполнение метода и ничего не делаем if (head.querySelector(`.$`)) < // если уже есть активная кнопка head.querySelector(`.$`).classList.remove(this.captionActiveClass) // то удаляем ей активный класс > caption.classList.add(this.captionActiveClass) // затем добавляем активный класс кнопке, на которой был клик this.setActiveContent(head, body) // устанавливаем активный элемент контента в соответствии с активной кнопкой >) > init() < // основной метод для вызова других описанных методов const tabs = document.querySelector(this.tabs) // ищем на странице элемент по переданному селектору основного элемента вкладок и записываем в константу const head = tabs.querySelector(this.head) // ищем в элементе tabs элемент с кнопками по переданному селектору и записываем в константу const body = tabs.querySelector(this.body) // ищем в элементе tabs элемент с контентом по переданному селектору и записываем в константу this.onLoad(head, body) // вызываем метод onLoad и передаем в параметрах константы, объявленные выше this.onClick(head, body) // вызываем метод onClick и передаем в параметрах константы, объявленные выше >> new Tabs(< // создаем экземпляр JavaScript класса Tabs, и передаем значения CSS классов и селекторов элемента вкладок, которые нужно оживить - section__tabs tabsSelector: '.section__tabs', // основной элемент вкладок tabsHeadSelector: '.tabs__head', // элемент с кнопками tabsBodySelector: '.tabs__body', // элемент с контентом tabsCaptionSelector: '.tabs__caption', // элемент кнопки tabsCaptionActiveClass: 'tabs__caption_active', // активный класс кнопки tabsContentActiveClass: 'tabs__content_active', // активный класс элемента контента >).init() // вызываем основной метод init new Tabs(< // создаем экземпляр JavaScript класса Tabs, и передаем значения CSS классов и селекторов элемента вкладок, которые нужно оживить - about__tabs tabsSelector: '.about__tabs', // основной элемент вкладок tabsHeadSelector: '.tabs__head', // элемент с кнопками tabsBodySelector: '.tabs__body', // элемент с контентом tabsCaptionSelector: '.tabs__caption', // элемент кнопки tabsCaptionActiveClass: 'tabs__caption_active', // активный класс кнопки tabsContentActiveClass: 'tabs__content_active', // активный класс элемента контента >).init() // вызываем основной метод init >) 

Итоги

Данный вариант реализации всего лишь один из многих и не претендует на эталонность. Вы можете использовать как этот вариант, так и другие доступные.

В данной реализации кнопки и блоки контента можно располагать не соблюдая их порядок в HTML-структуре. Eсть проверка при загрузке страницы, если не установлена активная вкладка, то устанавливаем активной первую вкладку. Также не используются циклы, что уменьшает количество событий при переключении вкладок. При использовании CSS стилей из статьи эти вкладки логично адаптируются под любое разрешение экрана

Буду рад, если статья оказалась полезной

Спасибо за ваше внимание и уделённое время!

Табы (вкладки) для сайта на CSS и JavaScript – 3 способа

Табы (вкладки) для сайта на CSS и JavaScript – 3 способа

В этой статье рассмотрим примеры вкладок для сайта, выполненных как с использованием только CSS, так и с применением JavaScript.

Что такое вкладки (табы)?

Вкладки (табы) – это один из элементов пользовательского интерфейса, с помощью которого можно улучшить организацию контента на сайте. Осуществляют они это посредством разделения некоторого содержимого на части и показа нам в определённый момент времени только одной из них. Переход к другой части контента осуществляется посредством нажатия на соответствующий заголовок (название) вкладки.

Таким образом, табы позволяют нам очень экономично вывести много информации. Достигается это посредством того, что информация делится на значащие секции. А для показа одной секции требуется намного меньше места, чем для вывода всей информации сразу. В результате, если сделать всё точно, то пользователь будет интуитивно понимать, что и в какой вкладке находится. В конечном счёте это может сделать сайт более понятным и значительно упростить работу с ним.

Вкладки на CSS с использованием радиокнопок и :checked

Один из способов создать вкладки на CSS – это использовать радиокнопки( с type=»radio» ) и CSS-селектор :checked .

Без оформления минимальный код табов будет выглядеть следующим образом:

  
Содержимое 1.
Содержимое 2.
Содержимое 3.

Вкладки (табы) для сайта на чистом CSS, в основу работых которых положены радиокнопки и CSS-селектор :checked

В этом варианте радиокнопки связаны с определённым . Связь элемента с организована через атрибут for . Это действие необходимо для того, чтобы после скрытия элементов , управлять ими (устанавливать checked ) можно было через клики по .

Отображение и скрытие контента, связанного с вкладками, выполняется очень просто. По умолчанию элементы, содержащие контент, не отображаются. Показ того или иного элемента с контентом осуществляется только в том случае, если селектор в следующем правиле позволяет выбрать его:

#tab-btn-1:checked~#content-1, #tab-btn-2:checked~#content-2, #tab-btn-3:checked~#content-3 { display: block; }

Для выделения названия текущей (активной) вкладки можно использовать следующий код:

.tab > input[type="radio"]:checked + label { color: red; }

Табы на основе радиокнопок и CSS-селектора :checked, в которых добавлен ещё код для выделения активной вкладки

Здесь стилизация выбранного выполнена с использованием селектора .tab > input[type=»radio»]:checked + label . Он выбирает , который идёт сразу же после input[type=»radio»] , находящемся в состоянии checked .

Оформить вкладки можно по-разному. В следующем примере они визуально отображаются как кнопки:

.tab { display: flex; flex-wrap: wrap; } .tab > input[type="radio"] { display: none; } .tab-content { display: none; width: 100%; margin-top: 1rem; } #tab-btn-1:checked~#content-1, #tab-btn-2:checked~#content-2, #tab-btn-3:checked~#content-3 { display: block; } .tab > label { display: block; padding: 0.5rem 1rem; cursor: pointer; transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out; text-decoration: none; color: #0d6efd; border: 0; border-radius: 0.375rem; background: 0 0; } .tab > input[type="radio"]:checked + label { cursor: default; color: #fff; background-color: #0d6efd; }

Табы для сайта на основе радиокнопок и CSS-селектора :checked, которые имеют внешний вид кнопок

Вкладки с нижнем подчеркивание названий секций:

Табы для сайта на основе радиокнопок и CSS-селектора :checked, которые имеют нижнее подчёркивание названий секций

При необходимости вместо названий вкладок можно использовать хештеги:

Табы для сайта на основе радиокнопок и CSS-селектора :checked, которые в качестве названий вкладок имеют хештеги

Вкладки, которые имеют привычный вид (с использованием селектора :has() :

Табы для сайта на основе радиокнопок и CSS-селектора :checked, которые имеют привычный вид

Вкладки на CSS с использованием :target

Ещё создать вкладки только на CSS можно с использованием псевдокласса :target.

Без оформления минимальный код будет выглядеть следующим образом:

  
Содержимое 1.
Содержимое 2.
Содержимое 3.
Вкладка 1 Вкладка 2 Вкладка 3

Вкладки (табы) для сайта на чистом CSS, работающие на основе псевдокласса :target

Работа этих табов основана:

  • на добавлении хеша к URL-адресу страницы при нажатии на вкладку (ссылку);
  • на скрытии всех блоков ( display: none ) и отображении только одного их них, id которого сейчас находится в хеше URL-адреса.

С помощью псевдокласса :target мы можем также выбрать другие элементы, которые каким-то определённым образом связаны с ним. Например, можем это использовать, чтобы выделить активную (текущую) вкладку:

#content-1:target~.tab-nav>[href="#content-1"], #content-2:target~.tab-nav>[href="#content-2"], #content-3:target~.tab-nav>[href="#content-3"] { color: red; }

Вкладки (табы) для сайта на чистом CSS, в которых :target ещё используется для выделения активной вкладки

В HTML-код табов уже добавлены классы. Используя их мы можем стилизовать табы так, как нам нужно.

Пример вёрстки вкладок на Flexbox, которые имеют стандартный вид:

Табы для сайта на основе псевдокласса :target, которые имеют обычный вид

Пример оформления вкладок, которые имеют внешний вид кнопок:

Табы для сайта на основе псевдокласса :target, которые имеют внешний вид кнопок

При необходимости, их, например, можно сделать вертикальными:

Вертикальные табы для сайта на основе псевдокласса :target

Если необходимо, чтобы табы на разных классах устройств отображались по-разному, можно использовать медиа-запросы. Пример табов, у которых название вкладок на маленьких экранах отображаются горизонтально, а на остальных вертикально:

@media (min-width: 576px) { .tab { flex-direction: row; } .tab-nav { flex-direction: column; margin-right: 1rem; } }

Табы с использованием JavaScript

Сейчас рассмотрим реализацию табов на чистом JavaScript (без использования jQuery и каких-либо других библиотек). Этот вариант может потребоваться, когда мы хотим от табов больше, чем можно сделать с помощью CSS. Например, если мы хотим при открытии вкладки загружать туда контент через AJAX.

Код HTML и CSS без дополнительного оформления:

  
Содержимое 1.
Содержимое 2.
Содержимое 3.

К вкладке, которая должна быть активной по умолчанию необходимо добавить класс tab-btn-active . А к контенту, связанному с ней tab-pane-show .

JavaScript

const showTab = (elTabBtn) => { const elTab = elTabBtn.closest('.tab'); if (elTabBtn.classList.contains('tab-btn-active')) { return; } const targetId = elTabBtn.dataset.targetId; const elTabPane = elTab.querySelector(`.tab-pane[data-id="${targetId}"]`); if (elTabPane) { const elTabBtnActive = elTab.querySelector('.tab-btn-active'); elTabBtnActive.classList.remove('tab-btn-active'); const elTabPaneShow = elTab.querySelector('.tab-pane-show'); elTabPaneShow.classList.remove('tab-pane-show'); elTabBtn.classList.add('tab-btn-active'); elTabPane.classList.add('tab-pane-show'); } } document.addEventListener('click', (e) => { if (e.target && !e.target.closest('.tab-btn')) { return; } const elTabBtn = e.target.closest('.tab-btn'); showTab(elTabBtn); });

Табы для сайта на CSS и JavaScript

Если нужно программно открыть другую вкладку, то можно использовать функцию showTab() . Ей в качестве аргумента нужно передать ту вкладку ( ), которую необходимо сделать активной:

JavaScript

// получим все кнопки const elTabBtns = document.querySelectorAll('#tab-1 .tab-btn'); // показать первую вкладку showTab(elTabBtns[0]); // показать вторую вкладку showTab(elTabBtns[1]); // показать третью вкладку showTab(elTabBtns[2]);

Как работает JavaScript код табов?

Центральное место в коде JavaScript занимает функция showTab() . Она имеет параметр elTabBtn .

Сначала внутри функции мы получаем элемент .tab , который содержит elTabBtn . Если вкладка уже активна, то дальше ничего не делаем и завершаем функцию с помощью инструкции return . В противном случае получаем значение атрибута data-target-id с помощью следующего кода:

JavaScript

const targetId = elTabBtn.dataset.targetId;

После этого, получаем элемент .tab-pane , используя targetId :

JavaScript

const elTabPane = elTab.querySelector(`.tab-pane[data-id="$"]`);

Затем проверяем наличие элемента elTabPane , который мы получили в предыдущем шаге с помощью метода querySelector . Если элемент существует, то удаляем классы tab-btn-active и tab-pane-show у элементов, который в данный момент их содержат:

JavaScript

const elTabBtnActive = elTab.querySelector('.tab-btn-active'); elTabBtnActive.classList.remove('tab-btn-active'); const elTabPaneShow = elTab.querySelector('.tab-pane-show'); elTabPaneShow.classList.remove('tab-pane-show');

В конце добавляем к элементам elTabBtn и elTabPane соответственно классы tab-btn-active и tab-pane-show :

JavaScript

lTabBtn.classList.add('tab-btn-active'); elTabPane.classList.add('tab-pane-show');

Обработку события click выполняем с помощью следующего кода:

JavaScript

document.addEventListener('click', (e) => < if (e.target && !e.target.closest('.tab-btn')) < return; >const elTabBtn = e.target.closest('.tab-btn'); showTab(elTabBtn); >);

Примеры

1. Пример, в котором данные о последней открытой вкладки таба будем сохранять в LocalStorage, а затем использовать эту информацию при открытии страницы для переключения на неё:

JavaScript

const showTab = (elTabBtn) => < // . if (elTabPane) < // . // сохраняем состояние вкладки в LocalStorage const tabStorage = JSON.parse(localStorage.getItem('tab') ?? '<>'); tabStorage[elTab.id] = targetId; localStorage.setItem('tabs', JSON.stringify(tabStorage)); > > // . // восстанавливаем состояние вкладок из LocalStorage const updateTabs = (tabStorage) => < Object.keys(tabStorage).forEach((tabId) =>< const elTab = document.querySelector(`#$`); const elTabBtn = elTab.querySelector(`.tab-btn[data-target-id="$"]`); showTab(elTabBtn); >); > const tabStorage = JSON.parse(localStorage.getItem('tabs') ?? '<>'); updateTabs(tabStorage);

2. Пример синхронизации вкладок на разных открытых страницах, относящихся к одному источнику (через LocalStorage):

JavaScript

window.onstorage = (e) => < if (e.key === 'tabs') < const tabStorage = JSON.parse(e.newValue); updateTabs(tabStorage); >>

3. Пример, в котором показано как на одной странице можно вывести несколько табов с сохранением их состояний (активных вкладок) в LocalSorage:

.
.

4. Табы, содержащие видео с YouTube. При переходе на другую вкладку будет приостанавливаться воспроизведение текущего видео.

Табы, содержащие YouTube ролики

 

В элементах .player атрибут data-video-id определяет videoId ролика, а data-width и data-height — ширину и высоту iframe .

Загрузку API IFrame Player будем выполнять асинхронно. Для этого напишем следующий код:

JavaScript

const elScript = document.createElement('script'); elScript.src = 'https://www.youtube.com/iframe_api'; document.head.append(elScript);

Создание и проигрывателя YouTube будем выполнять после загрузки кода API посредством функции onYouTubeIframeAPIReady :

JavaScript

const players = <>; function onYouTubeIframeAPIReady() < document.querySelectorAll('.player').forEach(el => < players[el.id] = new YT.Player(el.id, < height: el.dataset.height, width: el.dataset.width, videoId: el.dataset.videoId, playerVars: < origin: location.origin, >>); >) >

Приостанавливает воспроизведение видео будем посредством метода pauseVideo , который будем выполнять при открытии вкладки (используя для этого событие tab.itc.show ):

JavaScript

document.addEventListener('tab.itc.show', (e) => < const elTabPanePrev = e.detail.elTabPanePrev; if (elTabPanePrev) < const player = elTabPanePrev.querySelector('.player'); player ? players[player.id].pauseVideo() : null; >>);

Если статья понравилась, то поделитесь ей в социальных сетях:

Комментарии: 67

18.04.2023, 11:29

Добрый день! Помогите пожалуйста , не могу понять почему выдает ошибку ((

.tab_links::after < content: ''; width: 0; height: 5px; background-color: crimson; position: absolute; left:0; bottom: -8px; transition: 0.5s ease-in-out; >.tab_links.active-link::after < width: 100%; >.tab_contents ul li < list-style: none; margin: 10px 0; >.tab_contents ul li span < color: crimson; font-size: 18px; >.tab_contents < display: none; >.tab_contents.active_tab

JavaScript:

let tablinks = document.getElementsByClassName('tab_links'); let tabcontents = document.getElementsByClassName('tab_contents'); function opentab(tabname) < for (tablink of tablinks) < tablink.classList.remove('active-link'); >for (tabcontent of tabcontents) < tabcontent.classList.remove('active-tab'); >event.currentTarget.classList.add('active-link'); document.getElementById(tabname).classList.add('active-tab'); >

Александр Мальцев
19.04.2023, 11:55

Привет! Поправил ошибки в JavaScript-коде:

let tablinks = document.getElementsByClassName('tab_links'); let tabcontents = document.getElementsByClassName('tab_contents'); function opentab(tabname) < for (let tablink of tablinks) < tablink.classList.remove('active-link'); >for (let tabcontent of tabcontents) < tabcontent.classList.remove('active_tab'); >event.currentTarget.classList.add('active-link'); document.getElementById(tabname).classList.add('active_tab'); >

22.04.2022, 12:22

Отличная статья — всё, что я искал, в одном месте и компактно.
Вопросы:
1. Как осуществить вариант №1 (radio button), если input и label все вместе спрятаны внутрь отдельного блока?
Типа:

   . 2. В варианте №2 (:target) при первичной загрузке страницы содержимое не отображается никакое)

Александр Мальцев
26.04.2022, 14:07

Спасибо!
1. Можно только с использованием :has(), как-то по-другому только на CSS не получится
2. С :target этот момент можно доделать, чтобы по умолчанию отображалась, например, 1 вкладка (пример)

23.03.2022, 23:36

Здравствуйте Александр, а как реализовать такую задачку, я сделал страницу с алфавитом и брендами на базе бутстрап табов, при выборе вкладки открывается то или иное содержание, пример тут https://laraves.ru/baseshop/brand/, а как сделать так чтоб была возможность сразу выбрать несколько вкладок, допустим A и B и S и соответственно открыть их содержание, и также чтоб поочердно при клике можно было снимать выделения? штатно есть только «ИЛИ», а хотелось бы «И»

15.03.2022, 10:53

Доброго дня, Александр.

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

У меня вопрос следующего рода: как сделать «табы в табах»
Пример: на сайте по продаже пластиковых окон нужно вывести информацию в виде:
Табы (Уровень 1): типы конструкций, всего 4 типа конструкций;
В зависимости от типа выбранной конструкции подгрузить картинку (с этим разобрался) и блок с табами «виды комплектаций», их 7 штук

Табы (Уровень 2): виды комплектаций, всего 7 видов комплектаций.

Могли бы вы такой пример подробно рассмотреть, буду вам очень признателен.

Александр Мальцев
19.03.2022, 14:46

Привет! Благодарю за отзыв.
Сделал пример, если конечно правильно понял и сделал то что нужно (правда пришлось немного JavaScript код табов изменить): перейти.

21.03.2022, 12:23

Александр, благодарю за огромную работу и помощь! Вы мне очень помогли! Это именно то, что нужно, хочу спросить следующее как вкладкам 1.1. 1.4 присвоить другой класс в CSS, чтобы потом навесить на них другие свойства CSS, тем самым, чтобы они визуально выглядели по другому?

19.10.2021, 03:49

Я пытаюсь добавить два слайдера через шорткод в разные табы. После перезагрузки один работает (группа из 5 картинок, опционально вывожу только 3 с возможностью их прокручивать), а при переходе в следующий таб второй — нет (отображается только одна картинка из группы в увеличенном виде и не реагирует прокрутка). Причём, как только меняется разрешение экрана (через responsive в инспекторе) оба слайдера начинают работать прекрасно (если быть точнее, то тот, который во втором табе), но при очередной перезагрузке опять один работает, второй — нет. В чём может быть причина?

Александр Мальцев
20.10.2021, 13:18

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

10.09.2021, 23:12

Здравствуйте, допустим на сайте есть блок с карточками товаров. Как при нажатии на таб показывать не одну карточку, а несколько? пока только смог реализовать через дублировании html-кода, но это наверное такой себе вариант…

07.08.2021, 12:33

Добрый день, Александр

Подскажите, столкнулся с такой проблемой.
Взял пример реализации через JS.

Если кликаю на свободное место вкладки, то работает, если кликаю к примеру по тексту вкладки, то нет.
Как реализовать, чтобы по клику на любой элемент внутри родителя сработало переключение?

Александр Мальцев
08.08.2021, 10:05
Привет! Код JavaScript поправил в примере: tabs-v1
08.08.2021, 12:25
Большое спасибо!
12.07.2021, 13:00

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

Александр Мальцев
08.08.2021, 10:10
Поправил код JavaScript в примере: tabs-v1
Alex Maker
31.05.2021, 13:18

Здравствуйте, скажите что из выше перечисленного может помочь в решении моей проблемы?
Есть табы с категориями, в каждой из категорий есть табы с товаром, переключение между категориями и товарами написано на чистом Javascript, а теперь проблема. Необходимо чтобы по ссылке с другой страницы открывалась необходимая категория и товар. Дайте пример пожалуйста, я не силен в js((

Александр Мальцев
08.08.2021, 10:36

Привет! Для этого можно, например, передавать в составе URL номер вкладки, которую нужно открыть:
Эта ссылка (https://itchief.ru/examples/lab.php?topic=javascript&file=tabs-08&tab=2) откроет вторую вкладку, а эта (https://itchief.ru/examples/lab.php?topic=javascript&file=tabs-08&tab=3) — третью.

Сам код тут будет простой, нужно получить значение GET-параметра tab и передать его значение функции которая переключает вкладки:

 const tabs = $tabs('.tabs'); const urlParams = new URLSearchParams(location.search); const tabTo = urlParams.get('tab'); if (tabTo) { tabs.switchTabTo(tabTo); } 

19.05.2021, 09:42

Доброго времени суток друзья.
Очень интересные и полезные примеры работы скриптов, но к сожалению для решения свой задачи ничего подходящего не нашёл.
Возможно похожее есть решение с синхронизацией табов на разных страница как на примере itchief.ru/examples/lab.php?topic=javascript&file=tabs-v3, но немного не то что надо.
Александр, может Вы как мастер сможете помочь с реализацией моей задачи.
У меня на сайте есть 2 отдельный блока div.
В одном блоке содержится информация от квадроциклах, те. Есть цена и характеристики, а во втором блоке есть табы, в которых есть информация о предоставляемых услугах, в каждом табе разная услуга.
Зада состоит в том, чтобы при клике на каждом табе справа менялась цена.
Например:
Клик по табу №1 справа менялась цена в левом блоке и так при нажатии на каждый таб. пример на картинке

Буду очень признателен за помощь.

Александр Мальцев
08.08.2021, 11:11
Привет! Можно добавить к вкладкам data-атрибут с ценой:

 
Вкладка 1 Вкладка 2 Вкладка 3
 const tabs = $tabs('.tabs'); function updatePrice(tabsLink) { const price = tabsLink.dataset.price; document.querySelector('.price').textContent = price; } updatePrice(document.querySelector('.tabs__link_active')); document.addEventListener('tab.show', function(e) { updatePrice(e.detail.querySelector('.tabs__link_active')); }); 

14.04.2021, 15:26

То что надо. Спасибо автору большое!
Ребят. Использую Табы с использованием JavaScript. Главный код сначала в посте. Без дополнений.

У меня важный вопрос:
У меня табы с плеерами (iframe).
Так вот, как остановить подзагрузку и воспроизведение видео, при переходе на другую вкладку.
А то открываю другую, а на первой идет все и не останавливается. И соответственно грузятся сразу все вкладки.

Если бы разрешить загружать основную только, а остальные при переключении, останавливая первую…

Заранее благодарю, если есть решение!

Александр Мальцев
20.04.2021, 09:23

Пожалуйста!
Добавил в статью пример табов, содержащие YouTube видео. При переключении видео приостанавливается.
Открыть пример

30.04.2021, 20:05
Просто красавчик!
Спасибо огромное.
Александр Сидоров
01.04.2021, 14:58

Добрый день Александр!

Вопрос такой: не подскажите как можно задействовать табы в вопросе, когда необходимо сделать подобный блок:

— листающийся слайдер с категориями товара;
— ниже блок с первым товаром из выбранной категории товаров и в этом блоке без перезагрузки страницы можно выбрать другой товар (торговое предложение по типу SKU битрикс), с другой ценой и например расцветкой, но относящийся к основному товару.
Меняются фото, цена и описание.

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

Как копать в сторону аякса — это тоже на данный момент по знаниям проблематично…

19.03.2021, 17:10

Здравствуйте! Подскажите как сделать несколько блоков с табами на одной странице их мне нужно 4 (https://itchief.ru/assets/uploadify/9/8/8/9889f32d8a70fb4e1dc8bd505ace4887.jpg). Пробую вариант с отображением как кнопки. У меня только две вкладки, в каждом блоке разное содержание, название вкладок одинаковое.

Александр Мальцев
20.03.2021, 15:14

Привет! Связывание вкладок с содержимым выполняется через id, название может быть любым. Тут всё просто, проблем не должно быть. Как сделать: пример.

21.03.2021, 07:49
Просто огромное спасибо, все работает как надо.
15.12.2020, 06:12

Здравствуйте.
Подскажите, пожалуйста, как реализовать возможность переключения сразу нескольких табов кнопкой?
Для примера: у меня 5 блоков, в каждом по 2 вкладке. Над ними 2 кнопки, которые должны переключить сразу все табы.

Александр Мальцев
17.12.2020, 13:24
Привет!
Можно например так (открыть пример):

 1 2  

05.12.2020, 18:02

А как сделать кнопку «Добавить новую вкладку»? К примеру, чтобы скопировало содержание вкладки с чистым независимым input от копируемой вкладки

Александр Мальцев
06.12.2020, 16:15

Лучше наверно не копировать, а самостоятельно определять контент, например, с помощью функции getTabsPaneContent.
Для этого необходимо (открыть пример):
1. Добавить кнопку:

 

2. Создать функцию getTabsPaneContent, которая должна будет возвращать то, что мы хотим увидеть в новой вкладке:

const getTabsPaneContent = (counter) => { return `Содержимое ${counter}.

`; }

3. Получить в JavaScript саму кнопку и привязать к ней обработчик события click, который будет добавлять новую вкладку с контентом, определяемым функцией getTabsPaneContent:

const $addNewTab = document.querySelector('#add-new-tab'); $addNewTab.onclick = function () { const $tabsNav = document.querySelector('.tabs__nav'); const counter = $tabsNav.children.length + 1; // вставляем новый tabs__link const $tabsLink = `Вкладка ${counter}` $tabsNav.insertAdjacentHTML('beforeend', $tabsLink); // вставляем новый tabs__content const $tabsContent = document.querySelector('.tabs__content'); $tabsContent.insertAdjacentHTML('beforeend', getTabsPaneContent(counter)); }

05.10.2020, 18:31
Супер! как всегда просто и понятно! Спасибо!
Александр Мальцев
08.10.2020, 13:19
Пожалуйста!
26.08.2020, 18:09

еще есть вопросик, при нажатии на вкладку страница прокручивается к началу вкладку сверху alutat.com.ua/ а как отменить это?

Александр Мальцев
02.09.2020, 14:19

Так вы это реализовали в виде отдельных страниц, а не на одной странице. А новая страница по умолчанию всегда открывается сначала. Чтобы это реализовать, вам нужно дополнительно добавить скрипт на страницу, который будет её прокручивать до этого состояния.

19.08.2020, 18:09

Сперва, спасибо за полезную статью )

Хочу использовать вот эти вертикальные табы itchief.ru/examples/lab.php?topic=css&file=tabs-v4 на сайте, но не могу решить вопрос с отображением сразу контента первой вкладки. Знаю, что можно страницу itchief.ru/examples/output.php#content-1 открывать, но они у меня на главной будут сразу и нужно чтобы сразу была активна первая вкладка.

Как такое можно реализовать?

Буду признателен за ответ.

Александр Мальцев
20.08.2020, 04:01

Здравствуйте! На сколько понимаю вы хотите без JavaScript. На CSS это можно выполнить, если только разместить содержимое вкладки, которая по умолчанию должна быть открытой, после остальных.

А также внести необходимые изменения в CSS. Готовый пример можно посмотреть здесь.
20.08.2020, 08:18
супер! спасибо большое!
11.04.2020, 20:36

Доброго времени Александр! Подскажите как в данном скрипте добавить localStorage или cookie или sessionStorage, чтобы при F5 остаться на той же самой вкладке?

Александр Мальцев
12.04.2020, 08:32
Привет! Пример как это сделать с помощью localStorage добавил в статью.
12.04.2020, 13:09
12.04.2020, 20:47

А для двух табов подряд на странице не работает почему-то, код инициализации сразу всех вкладок делает нерабочим скрипт. Только если убрать один из двух табов, тогда да, сохранение в LocalStorage отрабатывает великолепно!

13.04.2020, 13:28
Разобрался, все работает!
Александр Мальцев
13.04.2020, 14:16
13.04.2020, 14:30
Правда как-то очень интересно работает))) Пока еще не понял, но вроде «через раз»
Александр Мальцев
13.04.2020, 14:41
Может что-то не учёл. Пример как это можно сделать для нескольких вкладок в статью добавил.
13.04.2020, 14:44
Сейчас проанализирую, сравню
14.04.2020, 02:25

Нашел одну причину, почему скрипт «ломало», банальная невнимательность, лишний раз обернул в дивы tabs, то, что вообще не надо было оборачивать.
Остальные примеры в статье разобрал, проверил на своем сайте, все работает как положено, кроме одного загадочного для меня явления))) Одни табы с одним контентом у меня на одной странице, другие с другим контентом на совершенно другой странице. Футер где скрипт, на всем сайте один и тот же. Табы работают, но допустим в хроме на одной странице с табами вкладка остаётся после F5 которую открыл, на другой local storage не срабатывает. В мозилле наоборот, та которая не работала в хроме, работает. «Мудрый» код скрипта покажу завтра

14.04.2020, 02:50
Код скрипта такой:

  

Александр Мальцев
14.04.2020, 16:36

Так корректно работать не будет. В mytabs будет находится результат вызова функции $tabs('.tabs') для первого таба. Кроме этого в этом случае в LocalStorage нужно сохранять не просто href ссылку, а, например, их в виде некоторого объекта, как в этом примере.
Как этот пример работает? В этом примере к табам добавляется id:

 Далее выполняем их инициализацию следующим образом 
var mytabs = { 'tabs-1': $tabs('#tabs-1'), 'tabs-2': $tabs('#tabs-2') }, .

Теперь у нас в mytabs['tabs-1'] и mytabs['tabs-2'] находятся результаты соответственно вызова $tabs для первого и второго tabs.
Сохранение данных в LocalStorage в этом примере выполняется в таком формате:

{"tabs-2":"#content-6","tabs-1":"#content-2"}

Вам нужно написать что-то подобное.
14.04.2020, 17:13

Наверно я что-то не недопонимаю, когда мы вызываем функцию $tabs('.tabs') и происходит инициализация определенного id с помощью:

var mytabs = { 'tabs-1': $tabs('#tabs-1'), 'tabs-2': $tabs('#tabs-2') }

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

Александр Мальцев
15.04.2020, 04:07

В этом случае его можно сделать более динамичным (пример обновил в статье). Теперь он будет сохранять состояния в LocalStorage и восстанавливать открытые вкладки только для тех табов, которые имеют id.

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

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