Как делать табы на jQuery

8 октября 2008, 18:36 Павел Марковнин JavaScript рейтинг +28-

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

Я постараюсь все расписывать довольно подробно, чтобы не было непонимания. Нетерпеливые могут сразу посмотреть живой пример.

Итак, для начала нам нужен HTML. Скажем, у нас будет всего 3 таба (соотвественно и 3 вида содержимого). Пишем следующий код:

<h1>Цитаты</h1>
<div class="tabs">
<!-- Это сами вкладки -->
<ul class="tabNavigation">
<li><a class="" href="#first">Д.Огилви</a></li>
<li><a class="" href="#second">Миллер</a></li>
<li><a class="" href="#third">Черчилль</a></li>
</ul>
<!-- Это контейнеры содержимого -->
<div id="first">
<h2>Д.Огилви</h2>
<p>Лучший способ превратить работника в генератор идей это возложить на него самую высокую ответственность.</p>
</div>
<div id="second">
<h2>Миллер</h2>
<p>Деньги не имеют значения — пока они у вас есть.</p>
</div>
<div id="third">
<h2>Черчилль</h2>
<p>Пессимист видит трудности при каждой возможности; оптимист в каждой трудности видит возможности.</p>
</div>
</div>

Обратите внимание, что имя якоря ссылки таба соотвестсвует id дива.

Теперь добавим сюда стилей по вкусу:

div.tabs {
background: #333;
padding: 1em;
}

div.container {
margin: auto;
width: 90%;
margin-bottom: 10px;
}

ul.tabNavigation {
list-style: none;
margin: 0;
padding: 0;
}

ul.tabNavigation li {
display: inline;
}

ul.tabNavigation li a {
padding: 3px 9px;
background-color: #666;
color: #000;
text-decoration: none;
}

ul.tabNavigation li a.selected,
ul.tabNavigation li a.selected:hover {
background: #FFF;
color: #000;
}

ul.tabNavigation li a:hover {
background: #ccc;
color: #000;
}

ul.tabNavigation li a:focus {
outline: 0;
}

div.tabs div {
padding: 5px;
margin-top: 3px;
border: 1px solid #FFF;
background: #FFF;
}

div.tabs div h2 {
margin-top: 0;
}

Финальным штрихом будет JavaScript код:

$(function () {
var tabContainers = $('div.tabs > div'); // получаем массив контейнеров
tabContainers.hide().filter(':first').show(); // прячем все, кроме первого
// далее обрабатывается клик по вкладке
$('div.tabs ul.tabNavigation a').click(function () {
tabContainers.hide(); // прячем все табы
tabContainers.filter(this.hash).show(); // показываем содержимое текущего
$('div.tabs ul.tabNavigation a').removeClass('selected'); // у всех убираем класс 'selected'
$(this).addClass('selected'); // текушей вкладке добавляем класс 'selected'
return false;
}).filter(':first').click();
});

Теперь остается посмотреть, что у нас получилось.

Надо сказать, что сегодня мы изобрели велосипед (плагинов для табов огромное количество), но зато посмотрели как работают селекторы jQuery. Еще к плюсам можно отнести то, что при отключенном JS пользователь все равно увидит информацию из табов.

На сегодня все. Вопросы и замечания — в комментариях. Пока.

Обновление, 28 марта 2009: По многочисленным просьбам трудящихся я сделал пример, как делать несколько блоков с табами на странице.

Рекламное место, которое может стать вашим

Понравилась статья?

Тогда подпишись на обновления через RSS или воспользуйся
другими способами подписки.

Читать в Яндекс.Ленте Добавить в Google Добавить в Netvibes
  •  

Комментарии — 66

RSS
  • Аватарка
    8 октября 2008 в 20:30 ]]>sergy]]>
    спасибо, довольно неплохо и познавательно
  • Аватарка
    9 октября 2008 в 8:51 Андрей [Sam] Несвой
    Спасибо
  • Аватарка
    9 октября 2008 в 10:23 ]]>Ney]]>
    Полезная статья, спасибо. Ожидал увидеть обзор одного из плагинов, сначала немного смутился, когда увидел, что Вы всё сами реализовали :)
  • Аватарка
    9 октября 2008 в 14:36 ]]>Вадим]]>
    Спасибо. Как раз искал простой аякс таб..
  • Аватарка
    9 октября 2008 в 18:17 ]]>Grin]]>
    Вадим, сейчас это не аякс, но переделать не сложно )
  • Аватарка
    9 октября 2008 в 18:26 ]]>Вадим]]>
    Grin, Чем сейчас и занимаюсь :-)
  • Аватарка
    10 октября 2008 в 4:33 ]]>kikaha]]>
    сорри за занудство, однако абсолютно все версии табов, что я где либо видел, предусматривают размещение собственно селекторов прямо над областью, где сами табы и переключаются. инерция мышления, ни в одном примере не видел чтобы табы были отделены от переключаемой области. например, при 2-колоночной верстке - в навигационной колонке селекторы, во 2-й, контентной колонке - сами табы...
  • Аватарка
    10 октября 2008 в 18:58 ]]>Shimon]]>
    Interesnyi primer. V svoe vremya vyuchil jQuery izza togo chto ne mog naiti podhodyaschego legkogo i udobnogo plagina dlya tabov... V rezul'tate napisal svoi. @kikaha - Na apple.com/safari zakladki realizovany sboku. A voobsche eto vopros dizaina, a implementaciya odna i tazhe.
  • Аватарка
    10 октября 2008 в 21:25 ]]>kikaha]]>
    @Shimon - ну занудный я, понятно что это вопрос дизайна, просто новички видят все примеры единообразно и считают что только таким образом и можно реализовать данный эффект, и никак иначе, то есть это замечание к оформлению примеров, не претензия ни в коем случае :)
  • Аватарка
    12 октября 2008 в 14:55 Денис Чистяков
    Хороший обзор, только смущает принудительное использование якорей в ссылках, я лично предпочитаю, что бы там были прямые ссылки на ресурсы расположенные в табах, что бы они были доступны и с JS и без них, и по клику средней кнопкой. Но это в принципе не сильно меняет идею ) 2 kikaha по сути если они будут расположены в разных местах, то поменяется лишь селектор контейнера.
  • Аватарка
    13 октября 2008 в 17:11 ]]>Grin]]>
    Денис, все зависит от того, как вы показываете содержимое табов. Если оно грузится аяксом, то да, ваш вариант правильный. Если же содержимое уже находится на этой странице (как у нас), то нет смысла делать ссылки, якори в этом случае самое то
  • Аватарка
    13 октября 2008 в 17:13 ]]>Grin]]>
    Еще в качестве улучшения можно предложить создавать сами закладки (те, что надо контентом) динамически на JS. Тогда при отключенных скриптах будет просто 3 области без ненужных табов
  • Аватарка
    25 ноября 2008 в 21:34 Накукрыскин
    Тоже самое бы и для вертикальных табов... Ибо с js не очень хорошо дружу, разбираться с jquery в подробностях времени нет, а сделать нужно...
  • Аватарка
    6 декабря 2008 в 18:02 Антон
    а вертикальные табы можно сделать? т.е., чтобы табы были не сверху, а, например, слева или справа.
  • Аватарка
    16 декабря 2008 в 9:06 ]]>Зайва Игорь Леонидович]]>
    Спасибо, только что и себе прикрутил... :) Но появился такой вопрос: можно ужать код, если ставить 3-5 блоков, в каждом по 2-3 таба ? Я не сильно пока разбираюсь в Джиквери, но вроде бы чуток сократил... Все равно получается код почти в 20 строк, если не сложно, приведите, пожалуйста, пример, хотя бы на 2 блока.

    Странно, что скрипт (поставил в комменты), который просто раздвигается/задвигается занимает всего(!) 1-3 строчки ??? :)
  • Аватарка
    18 декабря 2008 в 0:13 ]]>Создатель веба]]>
    спс!!
  • Аватарка
    30 декабря 2008 в 23:26 anree@pisem.net
    Спасибо за решение. Но у меня возник вопрос: как в данном примере правильно сделать запоминание текущего таба с помощью плагина "Cookie for jQuery"? Если можно покажите пример с кодом.
    Спасибо.
  • Аватарка
    31 декабря 2008 в 3:25 anree@pisem.net (Андрей Шкодяк / Украина, Хмельницкий)
    Ну в общем отвечу сам на свой предыдущий пост. Использовал стандартный Cookie плагин для jQuery, и немного изменив код примера добился "запоминания" последней выбранной вкладки после перезагрузки страницы записывая индекс вкладки в кукисы. Т.к. я только учусь возможно мое решение неверное но оно работает. Было бы интересно увидеть другой вариант реализации.

    var tabContainers = $('div.tabs > div');
    var saved_tab = parseInt($.cookie('saved_tab')) || 0;

    tabContainers.hide().filter(':eq('+saved_tab+')').show();
    $('div.tabs ul.tabNavigation a').click( function () {

    var index = $('div.tabs ul.tabNavigation a').index(this);
    $.cookie('saved_tab', index);
    tabContainers.hide();
    tabContainers.filter(':eq('+index+')').show();
    $('div.tabs ul.tabNavigation a').removeClass('selected');
    $(this).addClass('selected');
    return false;
    }).filter(':eq('+saved_tab+')').click();
  • Аватарка
    5 января 2009 в 16:27 ]]>Трейсер]]>
    Простите, немного занудно выглядит, но куда вставлять javascript
  • Аватарка
    5 января 2009 в 16:47 ]]>Grin]]>
    Трейсер, в принципе нет особой разницы куда вы его вставите
  • Аватарка
    2 февраля 2009 в 17:43 Сергей
    Подскажите пож-та, может конечно не по данной теме, но все же спрошу.
    Мне нужно сделать что-то типа табов, но только все гораздо проще. К примеру есть вот такой текст: 1. Текст1 2. Текст2 3. Текст3 Нужно, чтобы когда нажимаешь на Текст1 под ним (между Текст1 и Текст2) открывалась некая инфа1. Нажимаешь на Текст2 инфа1 исчезала и появлялась инфа2 между Текст2 и Текст3. надеюсь понятно объяснил. спасибо
  • Аватарка
    2 февраля 2009 в 17:44 Сергей
    Текст1 и тд идут в столбик
  • Аватарка
    2 февраля 2009 в 20:50 Сергей
    Спасибо, уже нашел )))
  • Аватарка
    22 марта 2009 в 9:39 Сергей
    Скажите пожалуйста!
    Вот на одной странице стоит несколько блоков, и при нажатии на одну вкладку открывается она во всех блоках! Как сделать чтоб каждый блок работал по отдельности!
  • Аватарка
    22 марта 2009 в 19:06 ]]>Grin]]>
    Сергей, смотри, у тебя сейчас разные группы с табами и их содержимым рассматривает как одно целое, хотя они и стоят в разных местах страницы.
    var tabContainers = $('div.tabs > div');
    ...
    $('div.tabs ul.tabNavigation a')

    Чтобы этого не происходило, можно оборачивать каждую из групп блоков в див с каким-то айди, например:
    <div id="tabs-block-wrapper-N">
    ...
    // а тут уже сами табы
    ...
    </div>

    А потом уже для каждого блока в отдельности вызывать функцию вот так:
    var tabContainers = $('#tabs-block-wrapper-N div.tabs > div');
    ...
    $('#tabs-block-wrapper-N div.tabs ul.tabNavigation a')

    Все дело в том, что изначальный код был только для одного набора табы-содержимое на странице.
  • Аватарка
    22 марта 2009 в 21:15 Сергей
    Grin, будь добр напиши полнустью код на 2 блока,а то я не разбирусь!
    Спасибо!
  • Аватарка
    28 марта 2009 в 15:16 Сергей
    ну помогите если не трудно!
  • Аватарка
    28 марта 2009 в 15:34 ]]>Grin]]>
    Сергей, попробуй сделать, как я написал. Если не получиться, будем вместе разбираться ;-)
  • Аватарка
    8 апреля 2009 в 12:19 Logonet
    Добрый день. есть вопрос
    как заставить открыватся не первую вкладку по умолчанию а например вторую? заранее спасибо!
  • Аватарка
    8 апреля 2009 в 12:51 ]]>Grin]]>
    Logonet, вот так. Вот эту строчку:
    tabContainers.hide().filter(':first').show();

    заменяем на вот такок
    tabContainers.hide();
    tabContainers[1].show();
  • Аватарка
    2 июня 2009 в 14:58 Integra
    я Открыла ваш "живой пример", но он не работает :(
    я вижу все содержимое на одной вкладке. А поидее должно быть так: выбрал вкладку Черчель и там должен открыься блок с описанием Черчеля. Я правильно понимаю? Если да, то почему же у меня вашпример не правильно отборажается :(
    Мне нужно написать подобную менюшку на табах только 2х-уровневую, то есть на выделенной вкладке должна появляться еще одна менюшка со вкладками.
    Помогите пожалуйста...
  • Аватарка
    2 июня 2009 в 15:18 Integra
    живой пример так и не работает, но написанный вами код работает :)
    Осталось теперь на свою верстку его переложить и мне будет сщастье...
  • Аватарка
    3 июня 2009 в 1:48 ]]>Grin]]>
    Integra, теперь все работает ;-)
  • Аватарка
    3 июня 2009 в 7:49 Integra
    :) спасибо. подскажите еще пожалуйста где можно проверить верску на соответствие доктайпа?
  • Аватарка
    3 июня 2009 в 12:46 ]]>Grin]]>
  • Аватарка
    5 июня 2009 в 12:53 Integra
    :( Эта менюшка неработает у меня в ие6. У кого-нибудь что-то подобное случалось? Что можно сделать?
  • Аватарка
    5 июня 2009 в 14:47 Servekon
    Выкладываю рабочий пример который корректно запоминает последнюю открытую вкладку используя куки. Правда для этого необходимо подключить библиотеку jQuery.cookie
    
    var lastTabIndex = parseInt($.cookie("lastTab"));
    $("#element").tabs(lastTabIndex, {fxAutoHeight: true, onShow: function()
    {
     $.cookie('lastTab', $('#menuType').activeTab());
    }
    }
    );
    
  • Аватарка
    5 июня 2009 в 14:48 Servekon
    Сори, в предыдущем посте ошибка. Вот рабочий код:
    
    var lastTabIndex = parseInt($.cookie("lastTab"));
    $("#element").tabs(lastTabIndex, {fxAutoHeight: true, onShow: function()
    {
     $.cookie('lastTab', $('#element').activeTab());
    }
    }
    );
    
  • Аватарка
    6 июня 2009 в 15:05 Integra
    спасибо большое :)
    А кто-нить Граватаркой пользуется? я зарегилась и теперь нужно имя выбрать, я ввожу имя и после этого нажимаю ок. Но ничего не происходит, просто перезагружается страничка и все. И никаких ошибок, ничего не появляется...
  • Аватарка
    6 июня 2009 в 15:09 ]]>Grin]]>
    Integra, регишься и закачиваешь аватарку. Ну а потом на сайтах, использующих Граватар, вводишь мыло, с которым регистрировалась — вот и все ;-)
  • Аватарка
    6 июня 2009 в 15:27 Integra
    зарегится не могу...
    мне письмо пришло:
    To activate your account, simply click on the link below or paste into the url field on your favorite browser: и ссылка. вот тут нужно придумать ник и пароль. я все ввожу но ничего не сохраняется.
  • Аватарка
    6 июня 2009 в 15:28 ]]>Grin]]>
    И не пишется, в чем ошибка?
  • Аватарка
    6 июня 2009 в 15:33 Integra
    нет :( просто обнуляются поля. Я уже в 2 браузерах попробовала - но не помогает
  • Аватарка
    6 июня 2009 в 15:37 ]]>Grin]]>
    Integra, я только что проверил, все работает
  • Аватарка
    6 июня 2009 в 16:01 Integra
    получилось. видимо просто ник был занят, но обычно о таком пишут об ошибке, а тут тишина...
  • Аватарка
    6 июня 2009 в 16:05 Integra
    я сижу через браузере opera AC, и тут есть возможность растягивать картинки. Когда растягиваешь аватарки то они начинают размножаться(мостится) :) Интересно, это из-за чего?
  • Аватарка
    6 июня 2009 в 17:23 Integra
    о великие гуру jquery, у меня есть к вам еще один вопрос. В этой менюшке блоки с описанием вкладок находятся в 3 дивах. Мне нужно сделать так что бы сами кнопки лежали в отдельном блоке (как сейчас), а весь контент лежал в одном диве . Тоесть эти три дива


      перенести в один что бы было так

    ...
    ...
    ...

    что нужно исправить в js?
  • Аватарка
    6 июня 2009 в 17:25 Integra
    чет ненаписалось...
    в общем все три дива должны лежать в каком то одном, куда будет програмно выводится весь контент.
  • Аватарка
    6 июня 2009 в 17:55 Integra
    
    <div class="tabs">
     <ul class="tabNavigation">
         <li><a class="" href="#first">Д.Огилви</a></li>
         <li><a class="" href="#second">Миллер</a></li>
         <li><a class="" href="#third">Черчилль</a></li>
     </ul>
    </div>
    <div id=content>
      <div id="first"> ...</div>
      <div id="second">...</div>
      <div id="third">...</div>
    </div>
    
    вот типа такого требуют от меня, не знаю где исправить в js что б работало ...
  • Аватарка
    7 июня 2009 в 14:06 ]]>Grin]]>
    Integra, див tabs закрой после закрытия дива с айди content
  • Аватарка
    7 июня 2009 в 17:42 ]]>Женя]]>
    И еще id content возьми в кавычки
  • Аватарка
    8 июня 2009 в 10:42 Integra
    ага, ошибки. Но от того что их исправишь работать все равно это не будет. Нужно в скрипте чо-то менять.

    А еще я хочу сделать 2-х уровневую менюшку, нажимаешь на вкладку и внизу появляется еще один уровень с такими вкладками. Мне сказали что это табами сделать можно. Кто-нибудь делал такое? Подскажите где можна стырить код такой менюшки :), а то сроки поджимают, надо как-то уже что-то сделать...
  • Аватарка
    3 сентября 2009 в 9:58 Masta
    Уважаемый автор! Я скопировал приведенный в статье код и запустил его. И у меня все три контейнера отображаются одновременно - друг под другом. Помогите пожалуйста решить проблему. Спасибо.
  • Аватарка
    12 октября 2009 в 22:22 LittleHorn
    Спасибо большое за статью:) Всё просто и понятно. Мне очень помогло и довольно быстро получилось прикрутить:)
  • Аватарка
    24 октября 2009 в 20:27 ]]>romashulya]]>
    Попробовала поставить. Всё, вроде, видно, но все три вкладки открываются почему-то одновременно, одна под другой, и соответственно не переключаются... И ещё после клика по вкладке выкидывает вниз страницы. :( В чём может быть проблема? Вгот ссылка на сайт http://www.lyalya.mk.ua/index.php
  • Аватарка
    21 ноября 2009 в 18:58 Evil Raven
    Если использовать приведенный п "живом примере" код, то строку
    <script src='/files/js/jquery.js' type='text/javascript'></script>
    нужно исправить на
    <script src='./files/js/jquery.js' type='text/javascript'></script>
    т.е. просто добавить точку в ссылке, иначе jquery не подгружается.
  • Аватарка
    18 декабря 2009 в 14:55 Alex
    tabContainers.hide().filter(':first').show();
    эту сторочку можно закомметить, все работает.

    Спасибо большое за статью. Очень помог!
  • Аватарка
    14 января в 7:15 Дмитрий
    Здравствуйте меня интересует такой вопрос? Ссылки которые будут находится в контенте вкладок будут видны поисковым роботам,
  • Аватарка
    14 января в 12:07 ]]>Grin]]>
    Дмитрий, да, будут.
  • Аватарка
    18 февраля в 16:19 Ralf
    Мне надо добавлять свойство hover к выделенному элементу li (просто надо ;)).

    $(function () {
    var tabContainers = $('div.tabs > div');
    tabContainers.hide().filter(':first').show();
    $('div.tabs ul.tabNavigation li').click(function () {
    tabContainers.hide();
    tabContainers.filter(this.hash).show();
    $('div.tabs ul.tabNavigation li').removeClass('hover');
    $(this).addClass('hover');
    return false;
    }).filter(':first').click();
    });

    Я заменил a на li и все получилось, но.. перестала отображаться информация из табов, т.е. я щелкаю по элементам меню. Они весело выделяются hover'ом, но информация не отображается. Как реализовать это корректно?
  • Аватарка
    20 февраля в 18:09 Ralf
    Опишу проблему подробнее.

    Имеется, приведенный в данном примере, код:
    
    <div class='tabs'>
      <div id=tab0>Страница 1</div>
      <div id=tab1>Страница 2</div>
      <div id=tab2>Страница 3</div>
    </div>
    
    <div class='tabs'>
      <ul class='tabNavigation'>
        <li><a href='#tab0'>Меню 1</a></li>
        <li><a href='#tab1'>Меню 2</a></li>
        <li><a href='#tab2'>Меню 3</a></li>
      </ul>
    </div>
    


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

    
      <script type='text/javascript'>
        $(function () {
          var tabContainers = $('div.tabs > div');
          tabContainers.hide().filter(':first').show();
          $('div.tabs ul.tabNavigation a').click(function () {
            tabContainers.hide();
            tabContainers.filter(this.hash).show();
            $('div.tabs ul.tabNavigation a').removeClass('hover');
            $(this).addClass('hover');
            return false;
          }).filter(':first').click();
        });
      </script>
    


    Я так полагаю, что данный код добавляет/удаляет класс hover непосредственно к тэгу ссылки a. Мне же нужно, чтобы добалялся класс не к ссылке, а к элементу списка. Я пробовал заменить
    div.tabs ul.tabNavigation a
    на
    div.tabs ul.tabNavigation li
    , но в таком случае табы перестают работать. В любом случае нужно обрабатывать click на а, но добавлять класс к li. Видимо надо что-то с
    $(this).addClass('hover');
    сделать, но если
    $(this).addClass('hover');
    заменить на
    $('div.tabs ul.tabNavigation li').addClass('hover');
    , то hover добавится ко всем элементам списка (что, впрочем, очевидно). Помогите пожалуйста решить проблему, очень нужно. Спасибо.
  • Аватарка
    25 марта в 16:12 Сергей
    Все нечего но столкнулся одной проблемой скрипт работает,почти до полной загрузки страницы,вроде и стоит в самом начале,а все-же,есть варианты как это поправить ?
  • Аватарка
    28 марта в 16:34 Одиночка Айс
    >Надо сказать, что сегодня мы изобрели велосипед

    Не согласен :) Данный пример НАМНОГО легче тех, что приведены на большинстве сайтов, где я был. Правда вот с семантикой, говорят, проблемы ;)
  • Аватарка
    28 марта в 16:38 ]]>Одиночка Айс]]>
    Кстати, чуть не забыл, при попытке переименовать "нумерацию" дивов (то есть first и прочее поменять на что-то другое и в аяксе и в верстке), вкладки с текстом пропадают (((
  • Аватарка
    31 марта в 0:08 Дмитрий
    А скажите пожалуйста - как модифицировать код, чтобы в сам заголовок таба, можно было вставлять ссылку вида http://site.ru например.

    Спасибо за ответ, если кто ответит )
  • Аватарка
    1 апреля в 14:56 ]]>Одиночка Айс]]>
    Дмитрий, а надо ли? Ведь по клику мы ссылаемся на див с айдишником, но раз надо, попробуйте через onclick сделать?
  • Эл. почта (используется для Граватарки)
  • Домашняя страница
  • Имя в Твиттере
  • Разрешенные теги Текст сообщения (надо бы заполнить это поле)
  • как выглядит какой тег
    жирный текст <b>жирный текст</b>
    курсивный тект <i>курсивный тект</i>
    зачеркнутый текст <s>зачеркнутый текст</s>
    подчеркнутый текст <u>подчеркнутый текст</u>
    ссылка <a href="адрес">ссылка</a>
    function foo() { ... }
    <pre><code>function foo() { ... } </code></pre>