Верстка табов с помощью <dl>
Когда-то возникла необходимость сделать табы на странице. Это довольно типовая задача, поэтому, чтобы не изобретать велосипед, полез в Гугл посмотреть, как народ делает.
Все реализация, которые я увидел, выглядели довольно стандартно, примерно так:
<div class="tabs">
<ul class="nav">
<li>Tab 1</li>
<li>Tab 2</li>
<li>Tab 3</li>
<li>Tab 4</li>
<li>Tab 5</li>
</ul>
<ul class="content">
<li>Tab content 1</li>
<li>Tab content 2</li>
<li>Tab content 3</li>
<li>Tab content 4</li>
<li>Tab content 5</li>
</ul>
</div>
То есть два независимых списка, в одном заголовки, во втором — содержимое.
Лично меня такая структура не устраивает, главным образом из-за того, что отсутствует семантическая связь между заголовком и содержимым. Хоть я и не страдаю наркозависимостью верстать все «валидно и семантично» ради респекта и уважухи гиков, тут отсутствие четкой связи было все-таки недостатком.
Во-первых, данные из бэкэкнда придется выводить в два цикла (сначала заголовки, а потом контент), а не одним. Это хоть немного, но увеличивает объем кода и явно не добавляет производительности.
Во-вторых, клиентский скрипт для переключения табов тоже будет больше и сложнее, особенно с учетом того, что на странице может быть несколько блоков с табами.
Решил попробовать избавиться от этих проблем, а заодно размять мозги ? При выборе структуры элементов первым делом выбор пал на -список, который как нельзя лучше подходит для этой задачи. Думаю, не я первый решил попробовать сделать табы с помощью этого списка.
Вот что у меня получилось.
See the Pen Верстка табов с помощью by mihdan (@mihdan) on CodePen.
Чтобы приведенный пример не стал очередным источником бездумного копи-пэйста, давайте рассмотрим, за счет чего это работает.
Предположим, у нас есть набор элементов, которым указан float: left
:
А что будет, если одному из элементов этой последовательности указать float: right
?
Уже неплохо: элементы, следующие за , встали ровно за предыдущими. Но нам нужно, чтобы содержимое таба растягивалось на всю ширину, поэтому прописываем этому элементу width: 100%
:
Как и ожидалось, элемент разорвал поток. Размышляем так: если элемент прижат к правому краю контейнера, значит при изменении ширины будет изменяться левый край элемента (то есть растет справа налево). Значит, нам нужно подавить влияние левого края элемента. Сделать это можно с помощью margin-left: -100%
:
Осталось сместить элемент вниз, сделать это можно с помощью margin-top
:
Вот и все. По умолчанию все -элементы скрываем с помощью display: none
, выбранному элементу говорим display: block
. Скрипт переключения табов на jQuery выглядит совсем уж просто:
jQuery( function( $ ) {
$( 'dl.tabs dt' ).click( function() {
$( this )
.siblings()
.removeClass( 'selected' )
.end()
.next( 'dd' )
.andSelf()
.addClass( 'selected' );
} );
} );
Способ получился не супергибким (есть привязка к точному размеру закладки таба), однако позволяет решать большинство подобных задач.
https://codepen.io/mihdan/pen/Nmmbjg/
.andSelf() was deprecated in jQuery 1.8 and removed in jQuery 3.0. .addBack() should be used instead from jQuery 1.8 onward.
Да, такое бывает, что старые методы умирают
я нашел статью полезной. наверное, стать можно подправить/обновить. и обновить пример кода.
https://codepen.io/bonddesign/pen/gOOXyJL
Простая замена andSelf() на addBack() вываливает фатал.