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

Что такое табы?

На странице очень часто бывает необходимо вывести большое количество информации.

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

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

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

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

Вкладки на чистом CSS

Рассмотрим несколько способов создания табов на CSS.

Первый способ построен на радиокнопках (input с type="radio") и CSS селекторе checked.

HTML и CSS код таба:

<style>
.tabs {
  font-size: 0;
}

.tabs>input[type="radio"] {
  display: none;
}

.tabs>div {
  /* скрыть контент по умолчанию */
  display: none;
  border: 1px solid #e0e0e0;
  padding: 10px 15px;
  font-size: 16px;
}

/* отобразить контент, связанный с вабранной радиокнопкой (input type="radio") */
#tab-btn-1:checked~#content-1,
#tab-btn-2:checked~#content-2,
#tab-btn-3:checked~#content-3 {
  display: block;
}

.tabs>label {
  display: inline-block;
  text-align: center;
  vertical-align: middle;
  user-select: none;
  background-color: #f5f5f5;
  border: 1px solid #e0e0e0;
  padding: 2px 8px;
  font-size: 16px;
  line-height: 1.5;
  transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out;
  cursor: pointer;
  position: relative;
  top: 1px;
}

.tabs>label:not(:first-of-type) {
  border-left: none;
}

.tabs>input[type="radio"]:checked+label {
  background-color: #fff;
  border-bottom: 1px solid #fff;
}
</style>

<div class="tabs">
  <input type="radio" name="tab-btn" id="tab-btn-1" value="" checked>
  <label for="tab-btn-1">Вкладка 1</label>
  <input type="radio" name="tab-btn" id="tab-btn-2" value="">
  <label for="tab-btn-2">Вкладка 2</label>
  <input type="radio" name="tab-btn" id="tab-btn-3" value="">
  <label for="tab-btn-3">Вкладка 3</label>

  <div id="content-1">
    Содержимое 1...
  </div>
  <div id="content-2">
    Содержимое 2...
  </div>
  <div id="content-3">
    Содержимое 3...
  </div>
</div>
Табы для сайта на чистом CSS

Посмотреть

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

Стилизация выбранного элемента label в этом примере выполнена с использованием селектора input[type="radio"]:checked+label. Этот селектор выбирает элемент label, который расположен сразу же после элемента input[type="radio"], находящимся в состоянии checked.

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

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

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

CSS код для создания адаптивных вкладок в виде кнопок:

.tabs>input[type="radio"] {
  display: none;
}

.tabs>input[type="radio"]:checked+label {
  background-color: #bdbdbd;
}

.tabs>div {
  /* скрыть контент по умолчанию */
  display: none;
  border: 1px solid #eee;
  padding: 10px 15px;
  border-radius: 4px;
}

/* отобразить контент, связанный с вабранной радиокнопкой (input type="radio") */
#tab-btn-1:checked~#content-1,
#tab-btn-2:checked~#content-2,
#tab-btn-3:checked~#content-3 {
  display: block;
}

.tabs>label {
  display: inline-block;
  text-align: center;
  vertical-align: middle;
  user-select: none;
  background-color: #eee;
  border: 1px solid transparent;
  padding: 2px 8px;
  font-size: 16px;
  line-height: 1.5;
  border-radius: 4px;
  transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out;
  margin-right: 6px;
  cursor: pointer;
  margin-bottom: 10px;
}

.tabs>label:first-of-type {
  margin-left: 0;
}
Табы для сайта на чистом CSS

Посмотреть

В этом примере вкладки визуально представлены в виде хэштегов:

.tabs>input[type="radio"] {
  display: none;
}

.tabs>input[type="radio"]:checked+label {
  font-weight: bold;
  cursor: default;
}

.tabs>div {
  display: none;
  border-top: 1px solid #eee;
  padding: 10px 15px;
}

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

.tabs>label {
  display: inline-block;
  text-align: center;
  vertical-align: middle;
  user-select: none;
  padding: 2px 8px;
  font-size: 14px;
  line-height: 1.5;
  transition: color 0.15s ease-in-out;
  margin-left: 6px;
  cursor: pointer;
  margin-bottom: 4px;
}

.tabs>label:first-of-type {
  margin-left: 0;
}
Табы для сайта на чистом CSS

Посмотреть

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

Пример HTML и CSS кода для создания адаптивных вкладок, механизм работы которых организован через :target:

<style>
  .tabs {
    display: flex;
    flex-direction: column;
  }

  .tabs__links {
    display: flex;
    width: 100%;
    overflow-x: auto;
    overflow-y: hidden;
    margin-left: auto;
    margin-right: auto;
    margin-bottom: 10px;
    order: 0;
    white-space: nowrap;
    background-color: #fff;
    border: 1px solid #e3f2fd;
    box-shadow: 0 2px 4px 0 #e3f2fd;
  }

  .tabs__links>a {
    display: inline-block;
    text-decoration: none;
    padding: 6px 10px;
    text-align: center;
    color: #1976d2;
  }

  .tabs__links>a:hover {
    background-color: rgba(227, 242, 253, 0.3);
  }

  .tabs>#content-1:target~.tabs__links>a[href="#content-1"],
  .tabs>#content-2:target~.tabs__links>a[href="#content-2"],
  .tabs>#content-3:target~.tabs__links>a[href="#content-3"] {
    background-color: #bbdefb;
    cursor: default;
  }

  .tabs>div:not(.tabs__links) {
    display: none;
    order: 1;
  }

  .tabs>div:target {
    display: block;
  }
</style>

<div class="tabs">
  <div id="content-1">
    Содержимое 1...
  </div>
  <div id="content-2">
    Содержимое 2...
  </div>
  <div id="content-3">
    Содержимое 3...
  </div>

  <div class="tabs__links">
    <a href="#content-1">Вкладка 1</a>
    <a href="#content-2">Вкладка 2</a>
    <a href="#content-3">Вкладка 3</a>
  </div>
</div>
Табы для сайта на чистом CSS

Посмотреть

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

Например, выбрать вкладку, которая должна быть активной для элемента на который указывает :target можно так:

.tabs>#content-1:target~.tabs__links>a[href="#content-1"],
.tabs>#content-2:target~.tabs__links>a[href="#content-2"],
.tabs>#content-3:target~.tabs__links>a[href="#content-3"] {
  background-color: #bbdefb;
  cursor: default;
}

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

Например, чтобы сделать вкладки вертикальными их код можно изменить на следующий:

.tabs {
  display: flex;
  flex-direction: column;
}

.tabs__links {
  display: flex;
  flex-direction: row;
  order: 0;
  white-space: nowrap;
  margin-bottom: 15px;
  background-color: #fff;
  border: 1px solid #e3f2fd;
  box-shadow: 0 2px 4px 0 #e3f2fd;
}

.tabs__links>a {
  display: inline-block;
  text-decoration: none;
  color: #1976d2;
  padding: 6px 10px;
  text-align: center;
}

.tabs__links>a:hover {
  background-color: rgba(227, 242, 253, 0.3);
}

.tabs>#content-1:target~.tabs__links>a[href="#content-1"],
.tabs>#content-2:target~.tabs__links>a[href="#content-2"],
.tabs>#content-3:target~.tabs__links>a[href="#content-3"] {
  background-color: #bbdefb;
  cursor: default;
}

.tabs>div:not(.tabs__links) {
  display: none;
  order: 1;
  flex-grow: 1;
}

@media (min-width: 576px) {
  .tabs {
    flex-direction: row;
  }

  .tabs__links {
    flex-direction: column;
    border: none;
    box-shadow: none;
  }

  .tabs__links>a {
    border: 1px solid #e3f2fd;
    box-shadow: 0 2px 4px 0 #e3f2fd;
    margin-bottom: 8px;
  }

  .tabs__links>a:last-child {
    margin-bottom: 0;
  }

  .tabs>div:not(.tabs__links) {
    padding-left: 15px;
  }
}

.tabs>div:target {
  display: block;
}
Табы для сайта на чистом CSS

Посмотреть

При этом табы отображаются вертикально только на больших экранах, а на маленьких (мобильных) они отображаются горизонтально. Адаптивность табов в коде реализуется с помощью медиа-запросов.

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

В этом разделе разберём как можно создать табы на чистом JavaScript (без использования библиотеки jQuery).

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

HTML и CSS код вкладок:

<style>
  .tabs {
    border: 1px solid lightgray;
  }

  .tabs__nav {
    display: flex;
    flex-wrap: wrap;
    list-style-type: none;
    background: #f8f8f8;
    margin: 0;
    border-bottom: 1px solid lightgray;
  }

  .tabs__link {
    padding: 0.5rem 0.75rem;
    text-decoration: none;
    color: black;
    text-align: center;
    flex-shrink: 0;
    flex-grow: 1;
  }

  .tabs__link_active {
    background: lightgray;
    cursor: default;
  }

  .tabs__link:not(.tabs__link_active):hover,
  .tabs__link:not(.tabs__link_active):focus {
    background-color: #efefef;
  }

  .tabs__content {
    padding: 1rem;
  }

  .tabs__pane {
    display: none;
  }

  .tabs__pane_show {
    display: block;
  }    
</style>

<div class="tabs">
  <div class="tabs__nav">
    <a class="tabs__link tabs__link_active" href="#content-1">Вкладка 1</a>
    <a class="tabs__link" href="#content-2">Вкладка 2</a>
    <a class="tabs__link" href="#content-3">Вкладка 3</a>
  </div>
  <div class="tabs__content">
    <div class="tabs__pane tabs__pane_show" id="content-1">
      Содержимое 1...
    </div>
    <div class="tabs__pane" id="content-2">
      Содержимое 2...
    </div>
    <div class="tabs__pane" id="content-3">
      Содержимое 3...
    </div>
  </div>
</div>

JavaScript код:

var tabs = (function () {
  return function (selector, config) {
    var
      _tabsContainer = (typeof selector === 'string' ? document.querySelector(selector) : selector);

    var _showTab = function (tabsLinkTarget) {
      var tabsPaneTarget, tabsLinkActive, tabsPaneShow;
      tabsPaneTarget = document.querySelector(tabsLinkTarget.getAttribute('href'));
      tabsLinkActive = tabsLinkTarget.parentElement.querySelector('.tabs__link_active');
      tabsPaneShow = tabsPaneTarget.parentElement.querySelector('.tabs__pane_show');
      // если следующая вкладка равна активной, то завершаем работу
      if (tabsLinkTarget === tabsLinkActive) {
        return;
      }
      // удаляем классы у текущих активных элементов
      if (tabsLinkActive !== null) {
        tabsLinkActive.classList.remove('tabs__link_active');
      }
      if (tabsPaneShow !== null) {
        tabsPaneShow.classList.remove('tabs__pane_show');
      }
      // добавляем классы к элементам (в завимости от выбранной вкладки)
      tabsLinkTarget.classList.add('tabs__link_active');
      tabsPaneTarget.classList.add('tabs__pane_show');
      var eventTabShow = new CustomEvent('tab.show', { bubbles: true, detail: { tabsLinkPrevious: tabsLinkActive } });
      tabsLinkTarget.dispatchEvent(eventTabShow);
    }

    var _switchTabTo = function (tabsLinkIndex) {
      var tabsLinks = _tabsContainer.querySelectorAll('.tabs__link');
      if (tabsLinks.length > 0) {
        if (tabsLinkIndex > tabsLinks.length) {
          tabsLinkIndex = tabsLinks.length;
        } else if (tabsLinkIndex < 1) {
          tabsLinkIndex = 1;
        }
        _showTab(tabsLinks[tabsLinkIndex - 1]);
      }
    }

    var _setupListeners = function () {
      _tabsContainer.addEventListener('click', function (e) {
        var tabsLinkTarget = e.target;
        // завершаем выполнение функции, если кликнули не по ссылке
        if (!tabsLinkTarget.classList.contains('tabs__link')) {
          return;
        }
        // отменяем стандартное действие
        e.preventDefault();
        _showTab(tabsLinkTarget);
      });
    }

    _setupListeners();

    return {
      switchTabTo: function (index) {
        _switchTabTo(index);
      }
    }
  }
}());

tabs('.tabs');
Адаптивные вкладки на CSS и JavaScript

Посмотреть

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

tabs('.tabs');

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

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

var listTabs = document.querySelectorAll('.tabs');
for (var i = 0; i <= listTabs.length; i++) {
  tabs(listTabs[i]);
}

Кроме этого, если результат вызова функции tabs сохранить в переменную, то можно использовать метод, который она представляет.

Например:

var tab1 = ('.tabs');
// программно переключиться на 2 вкладку (2 – номер вкладки, на которую нужно перейти)
tabs1.switchToTab(2);

Описание исходного JavaScript кода

Исходный JavaScript код состоит из функции tabs. Внутри этой функции имеется переменная _tabsContainer и функции _showTab, _switchTabTo, _setupListeners. Переменная _tabsContainer хранит DOM элемент, предоставляющий собой контейнер с вкладками. Метод _showTab предназначен для скрытия текущей (активной) вкладки и отображения другой в зависимости от переданной ему ссылки. Метод _switchTabTo используется для переключения вкладки по её порядковому номеру. Установка обработчиков событий для tabs содержится в _setupListeners и выполняется в момент её вызова.

Вне функции доступен только метод switchTabTo. Он позволяет программно перейти на вкладку по её порядковому номеру.