Легкий аккордеон используя CSS и jQuery
В этой статье я покажу как используя CSS и jQuery, можно сделать легкий и красивый аккордеон. Для его создания понадобиться написать лишь пару строчек кода на jQuery и немного на CSS, и для красоты будем использовать немного CSS3. И сразу хочу отметить, что в этой статье я рассказываю не как создать плагин для jQuery, а просто аккордеон, но если же тема будет востребовательна, тогда напишу статью как создать плагин :)
И так начнем с HTML каркаса, давайте создадим его. У нас будет общий контейнер, он будет самим аккордеоном, в нем будет последовательно идти, заголовок H3, блок, H3, блок и т.д. Где H3 это заголовок секции, а блок это её содержимое. Вот такой HTML у нас должен получится:
<div id="accordion"> <h3 class="head">Секция #1</h3> <div class="block">Текст для секции #1</div> <h3 class="head">Секция #2</h3> <div class="block">Текст для секции #2</div> <h3 class="head">Секция #3</h3> <div class="block">Текст для секции #3</div> </div>
Теперь когда у нас есть готовый каркас, нужно определить для него стили. Из разряда CSS3 для заголовка и для блока определим скругленные углы на 3 пикселя (свойство border-radius), для заголовка отдельно определим тень (свойство text-shadow).
#accordion h3.head {
margin: 1px 0; padding: 5px 10px;
font-size: 17px; font-family: Tahoma; font-weight: normal; color: #fff;
background: #333;
cursor: pointer;
border-radius: 3px;
-o-border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
text-shadow: 1px 1px 0px #000;
-o-text-shadow: 1px 1px 0px #000;
-moz-text-shadow: 1px 1px 0px #000;
-webkit-text-shadow: 1px 1px 0px #000;
}
#accordion div.block {
padding: 10px; margin: 0;
font-size: 13px; font-family: Tahoma; font-weight: normal; color: #888;
background: #efefef;
border: 1px solid #ccc;
border-radius: 3px;
-o-border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
}
Также необходимо определить стиль для активной секции, например сделаем фон синего цвета. Добавим в конец CSS эти строчки:
#accordion h3.active {
background: #369;
}
Ну вот вроде бы со стилями и все, теперь можно перейти ко вкусному, к jQuery :) И так не большой алгоритм: при загрузки страницы скрываем все секции кроме первой, делаем первую секцию активной, а также вешаем обработчик события на клик по секции. Вот собственно сам js-файл аккордеона:
// Когда страница полностью загружена
$(window).ready(function() {
// Скрываем все секции кроме первой
$('#accordion > div:not(:first)').hide();
// Делаем первую секцию активной
$('#accordion h3:first, #accordion div:first').addClass('active');
// Если пользователь кликнул на секцию
$('#accordion > h3').click(function() {
// Сбрасываем все секции
$('#accordion > h3').removeClass('active');
$('#accordion > div').hide();
// Делаем активной на которую кликнули
$(this).addClass('active');
$(this).next().addClass('active').show();
});
});
Ну вот, теперь наш аккордеон полноценно работает. Но, все же чего-то в нем не хватает, давайте добавим анимации для наглядности.
// Когда страница полностью загружена
$(window).ready(function() {
// запоминаем высоту и отступы каждого блока
$('#accordion > div').each(function() {
$(this).data('height', $(this).height());
$(this).data('padding-top', $(this).css('padding-top'));
$(this).data('padding-bottom', $(this).css('padding-bottom'));
});
// Скрываем все секции кроме первой
$('#accordion > div:not(:first)').hide();
// Делаем первую секцию активной
$('#accordion h3:first, #accordion div:first').addClass('active');
// Если пользователь кликнул на секцию
$('#accordion > h3').click(function() {
// Сбрасываем все секции
$('#accordion > h3').removeClass('active');
$('#accordion > div:visible').animate({
height: 0,
'padding-top': 0,
'padding-bottom': 0
}, 500, function() { $(this).hide() });
// Делаем активной на которую кликнули
$(this).addClass('active');
box = $(this).next().addClass('active');
$(box).animate({
height: $(box).data('height'),
'padding-top': $(box).data('padding-top'),
'padding-bottom': $(box).data('padding-bottom')
}, 500);
});
});
Вот теперь у нас готов небольшой и в тоже время симпатичный аккордеон. Не бойтесь его стилизировать, думаю можно добиться гораздо более красивого эффекта, все в ваших руках.
$(‘#accordion > div’).slideUp();
Когда контента много слайдер прыгает..очень bad.
Поправил, теперь работает нормально. Пришлось прибегнуть к ручным средствам, так как slideUp и slideDown не всегда работают на ура.
$(this).data(‘padding-top’, $(this).css(‘padding-top’));
$(this).data(‘padding-bottom’, $(this).css(‘padding-bottom’));
Зачем запоминать значения паддингов, разве они не одинаковые для всех блоков?
Предполагается, что человек может для каждого блока задать разные паддинги :)
Господа, а как сделать так чтобы все секции были закрыты? первая по умолчанию всегда открыта…
Убери из кода эти строчки:
// Скрываем все секции кроме первой
$(‘#accordion > div:not(:first)’).hide();
// Делаем первую секцию активной
$(‘#accordion h3:first, #accordion div:first’).addClass(‘active’);
ОГРОМНЕЙШЕЕ СПАСИБО ЗА СТАТЬЮ ! Я начал делать перввые успехи , и как оказалось , готовые ВИДЖЕТЫ только усуглубляют понимание и их настройку под себя . А вы показали простой сухой код .Еще раз СПАСИБО ОГРОМНОЕ ! Я люблю работать с TOGGLE переключалкой. Поэтомумне так ценна Ваша статья . $(#Andrew39).appendTo(.*)
у меня почемуто с другими jquery плагинами этот не хочет вместе работать .. все глючит!!! почему?? помогите..
Ошибки в JS есть какие нить? Я не могу помочь не видя, кинь ссылку, где ты его используешь.
неплохо смотрится, но мне этого функционала оказалось мало.
допустим у меня все секции помечены якорями:
нужно сделать, что бы при загрузки странице по ссылке вида: accrdion.html#Section2 , активной активной оказывалась соответствующая секция.
Ну собственно на DOM Ready поставить событие, которое будет проверять хеш, и находить секцию с именем.
Используй Печенье! :)
winch, если решил проблему с открытией секции по ссылке с якорем, напиши плиз
В общем. Каждой секции ставим имя, например так:
На DOM Ready вешает событие с таким кодом:
var $section = $(location.hash); if ($section.length) { $section.addClass('active').next().show().addClass('active'); }Код на работоспособность не проверял, так что если что-то не так пишите.
Не работало (2ой пример), пока не добавил перед строкой 31
$(box).show();
У всех так или только у меня? В принципе логика понятна.
А! и да, автору респект.
По сути должно работать! jQuery должен сам проставить
display: block.Добрый день.
Опишите пожалуйста более подробно про ***На DOM Ready вешает событие с таким кодом:*** — где это прописывать на странице, как точно писать и т.д. данная функция отслеживания ссылок является основной для навигации )))
Вот здесь (http://api.jquery.com/ready/) почитайте.
Доброго дня.Что нужно изменть,что бы сделать горизонтальный аккордеон?Спасибо.
Подскажите, пожалуйста, какие строчки нужно добавить, чтобы при нажатии на уже активную секцию она сворачивалась (становилась не активной). И что нужно сделать, чтобы вначале, «Когда страница полностью загружена», открытой была не первая секция, а уже активная на данный момент. Т.е. — вначале все секции закрыты, затем мы выбираем одну из секций, она становится активной, нужно, чтобы при обновлении страницы эта секция оставалась активной.
Такая ошибка:
$(this).data is not a function
$(this).data(‘height’, $(this).height());
(firebug)
Хммм, проверил в FF 3.5, 3.6, и 4й версии, проблем не обнаружил :)
Спасибо. Вы бы знали, сколько я искала. Много материала, но нет понятного. Вот, например — карусель от Финна Рудольфа так мне и не далась — нет знаний. Вы первый, чья работа помогла мне, как новичку. Сегодня вы сделали меня счастливой, я закрыла десятидневный этап работы.
Всегда пожалуйста :)
Спасибо за статью. Очень полезно для новичков вроде меня. Скажите, а можно сделать так, чтобы по какой-нибудь кнопке (типа «Показать все») разворачивались одновременно все блоки и находились в открытом состоянии пока не нажмешь еще раз на эту же кнопку (или на другую кнопку (типа «Скрыть все»)). Очень жду ответ.
Да можно, надо выполнить следующий код по нажатию на кнопку «показать все»:
$('#accordion > h3, #accordion > div').addClass('active');Для того чтобы скрыть все, следующий код:
$('#accordion > h3, #accordion > div').removeClass('active');Спасибо)
Всегда рад помочь :)
а про сторонный скриптик-то промолчали)) хотя в исходнике он есть. http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js — этот. А как раз таки без него ничего и не работает!!!
Это сам jQuery вообще-то!
как так?
в исходнике у вас есть accordeon.js а в index.html прописан ещё и jquery.min.js
так вот если последний отключить (jquery.min.js ) то работать скрипт не будет)))
Правильно. Потому что jquery.min.js это и есть сам jQuery. Вы вообще понимаете, что такое jQuery, или хотя бы заголовок статьи читали? :)
да, я понимаю что такое jQuery. но тогда встаёт вопрос — зачем в index.html подключать два ОДИНАКОВЫХ скрипта, один из которых в вашем исходнике — accordion.js, а другой jquery.min.js. Вы говорите что это и есть сам скрипт. зачем они тогда там вдвоём? понимаете о чём я? (извините если нафлудил в вашей теме)))
С чего вы взяли, что они одинаковые? Файл accordion.js отвечает за работу аккордеона, а файл jquery.min.js сама jQuery библиотека!
теперь понятно))) sorry если что) учусь)
Скажите пожалуйста, как сделать чтобы когда щелкаешь на открытую секцию, то она закрывалась?
После строк:
// Делаем активной на которую кликнули $(this).addClass('active');впиши следующее:
if ($(this).next().hasClass('active')) { $(this).next().removeClass('active').animate({ height: 0, 'padding-top': 0, 'padding-bottom': 0 }, 500, function() { $(this).hide() }); return; }Работоспособность не проверял, так что если будут ошибки пишите, тогда уже проверю :)
Спасибо!
Вроде работает, только блоки теперь резко прыгают при закрывании и открывании(это не суть важно). Иногда происходит косяк при открывании другой секции, текущая закрывается, а новая не открывается. Но вот только не всегда.
Убрал анимацию и все клева заработало! Спасибо!
.animate({
height: 0,
‘padding-top’: 0,
‘padding-bottom’: 0
}, 500, function() {
$(this).hide()
});
заменил на .show();
Ну вот и славненько :)
Всеравно через раз работает
Конкретней?
Ситуация такая: у меня две секции. Открываю первую секцию все нормально -> вторую — нормально все -> опять первую ( контент дива block остаеться, а сам див как будто сварачивается и вторая секция под контентом) -> нажимаю среди текста на вторую секцию(такая же фигня, но так как секций больше нет, под текстом прозрачно). Уф вроде объяснил… :))
Есть ссылка на пример?
неа, на локалке делаю, код могу кинуть
Кинь код на мыло, оно есть на странице «Обо мне».
Выслал нужный вам код на ваше мыло!
подскажите пожалуйста код, все вкладки при открытии свернуты и закрыть кликом открытую, и чтобы не соскакивал кверху.
у меня такая же примерно ситуация, как здесь >>>>>
Ситуация такая: у меня две секции. Открываю первую секцию все нормально -> вторую – нормально все -> опять первую ( контент дива block остаеться, а сам див как будто сварачивается и вторая секция под контентом) -> нажимаю среди текста на вторую секцию(такая же фигня, но так как секций больше нет, под текстом прозрачно). Уф вроде объяснил… :))
заранее спасибо
Простите, но я ничего не понял. Видео в студию :)
Привет ребят! У меня возникла подробность в заголовках Секция #1 добавить стили при помощи div’ов например, мне нужно чтобы было к примеру:
Секция #1 — т.е вместо h3, div’ка. Я делаю:
#accordion #is.head { margin: 1px 0; padding: 5px 10px; font-size: 17px; font-family: Tahoma; font-weight: normal; color: #fff; background: #333; cursor: pointer; border-radius: 3px; -o-border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; text-shadow: 1px 1px 0px #000; -o-text-shadow: 1px 1px 0px #000; -moz-text-shadow: 1px 1px 0px #000; -webkit-text-shadow: 1px 1px 0px #000; } #accordion #is.active { background: #369; margin: 1px 0; padding: 5px 10px; font-size: 17px; font-family: Tahoma; font-weight: normal; color: #fff; cursor: pointer; border-radius: 3px; -o-border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; text-shadow: 1px 1px 0px #000; -o-text-shadow: 1px 1px 0px #000; -moz-text-shadow: 1px 1px 0px #000; -webkit-text-shadow: 1px 1px 0px #000; } #accordion div.block { padding: 10px; margin: 0; font-size: 13px; font-family: Tahoma; font-weight: normal; color: #888; border: 1px solid #ccc; border-radius: 3px; -o-border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; }$(window).ready(function() { // запоминаем высоту и отступы каждого блока $('#accordion > div').each(function() { $(this).data('height', $(this).height()); $(this).data('padding-top', $(this).css('padding-top')); $(this).data('padding-bottom', $(this).css('padding-bottom')); }); // Скрываем все секции кроме первой $('#accordion > div:not(:first)').hide(); // Делаем первую секцию активной $('#accordion #is:first, #accordion div:first').addClass('active'); // Если пользователь кликнул на секцию $('#accordion > #is').click(function() { // Сбрасываем все секции $('#accordion > #is').removeClass('active'); $('#accordion > div:visible').animate({height: 0, 'padding-top': 0, 'padding-bottom': 0}, 500, function() { $(this).hide() }); // Делаем активной на которую кликнули $(this).addClass('active'); box = $(this).next().addClass('active'); $(box).animate( { height: $(box).data('height'), 'padding-top': $(box).data('padding-top'), 'padding-bottom': $(box).data('padding-bottom') }, 500); }); });Но при нажатии на первый заголовок, div — он исчезает, но конент появляется. Что я делаю не правильно?
Ссылку на пример, а то в данный момент нет возможности воспроизвести!
А у всех в IE9 коряво работает? На опере гуд все
Коряво это как именно, в данный момент нету возможности проверить.
А как учесть в этом параметре:
height: $(box).data(‘height’)
высоту всех изображений, которые находятся в этом блоке?
Проблема в том, что высота считается по тексту без учета изображений и после раскрытия блок получается меньшей высоты, чем должен быть.
Анимацию убрал, все само собой исправилось.