Гибкий аккордеон
Создадим простой быстрореагирующий аккордеон, который при раскрытии будет перемещаться к верхней области просмотра. Также будет добавлено несколько переходов CSS3 для стрелки. Гибкость заключается в том, что ширина аккордеона будет подстраиваться под размеры экрана.
HTML
Cтруктура html будет состоять из контейнера с ID и class "st-accordion" и неупорядоченного списка. У элементов списка будет ссылка, служащая заголовком пункта аккордеона и блок с контентом, который изначально скрыт. Блок SPAN с классом "st-arrow" будет стрелкой в правой части, которая появляется при наведении на название пункта:
<div id="st-accordion" class="st-accordion">
<ul>
<li>
<a href="#">Название пункта<span class="st-arrow">Открыть или Закрыть</span></a>
<div class="st-content">
<p>Контент</p>
</div>
</li>
<li>
...
</li>
</ul>
</div>
CSS
В начале стилизуем основной контейнер, дав ему ширину в 100%, так как хотим, чтобы он подстраивался под ширинув внешнего контейнера. Если внешнего контейнера у вас нет, то используйте значение в процентах, которое вам больше подходит. В нашем примере у внешнего контейнера максимальная ширина 800px, а ширина 90%. У "st-accordion" будет минимальная ширина 270px:
.st-accordion{
width:100%;
min-width:270px;
margin: 0 auto;
}
Предположим, хотя в примере он и используется, у нас есть некоторый стиль reset.css, который сбрасывает значения padding и margin из списков UL и т. д., тогда мы определяем стиль для каждого элемента списка. Установим начальную высоту 100px, в основном она будет высотой элемента ссылки, а переполнение - overflow - будет скрыто, т.е. контент мы не увидим. При открытии элемента, мы анимируем его высоту, чтобы показать контент. Границы border позволяет нам создать разделение между пунктами аккордеона:
.st-accordion ul li{
height: 100px;
border-bottom: 1px solid #c7deef;
border-top:1px solid #fff;
overflow: hidden;
}
У первого пункта не будет верхней границы:.st-accordion ul li:first-child{
border-top:none;
}
Для ссылок добавим цветной переход при наведении мышки. Высота строки - line-height - должна быть такой же, как и начальная высота элемента списка:.st-accordion ul li > a{
font-family: Verdana,Georgia, serif;
text-shadow: 1px 1px 1px #fff;
font-size: 46px;
display: block;
position: relative;
line-height: 100px;
outline:none;
-webkit-transition: color 0.2s ease-in-out;
-moz-transition: color 0.2s ease-in-out;
-o-transition: color 0.2s ease-in-out;
-ms-transition: color 0.2s ease-in-out;
transition: color 0.2s ease-in-out;
}
.st-accordion ul li > a:hover{
color: #1693eb;
}
SPAN для стрелки будет расположен абсолютно, мы также скроем его, поместив за пределами элемента ссылки с прозрачностью 0. С помощью переходов стрелка будет появляться с правой стороны:.st-accordion ul li > a span{
background: transparent url(../images/down.png) no-repeat center center;
text-indent:-9000px;
width: 26px;
height: 14px;
position: absolute;
top: 50%;
right: -26px;
margin-top: -7px;
opacity:0;
-webkit-transition: all 0.2s ease-in-out;
-moz-transition: all 0.2s ease-in-out;
-o-transition: all 0.2s ease-in-out;
-ms-transition: all 0.2s ease-in-out;
transition: all 0.2s ease-in-out;
}
.st-accordion ul li > a:hover span{
opacity:1;
right: 10px;
}
Когда мы раскроем пункт аккордеона, то назначим для него класс st-open и ссылка останется с цветом, какой был при наведении. SPAN будет повернут на 180 градусов:.st-accordion ul li.st-open > a{
color: #1693eb;
}
.st-accordion ul li.st-open > a span{
-webkit-transform:rotate(180deg);
-moz-transform:rotate(180deg);
transform:rotate(180deg);
right:10px;
opacity:1;
}
Это стиль контента и его элементов:.st-content{
padding: 5px 0px 30px 0px;
}
.st-content p{
font-size: 16px;
font-family: Georgia, serif;
font-style: italic;
line-height: 28px;
padding: 0px 4px 15px 4px;
}
.st-content img{
border-right:1px solid #fff;
border-bottom:1px solid #fff;
}
С помощью media запроса, удостоверимся, что размер шрифта заголовка будет меньше:@media screen and (max-width: 320px){
.st-accordion ul li > a{
font-size:36px;
}
}
JS
Подключаем jQuery библиотеку и плагин easing и плагин accordion, о котором ниже чуть подробнее.
Самые важные части плагина accordion.
Начнем с настроек по умолчанию:
$.Accordion.defaults = {
// Открыт или Закрыт пункт. -1 означает, что все пункты свернуты по умолчанию.
open: -1,
// если установлено true, то только один элемент может быть раскрыт, другой, если был открыт, свернется.
oneOpenedItem: false,
// сокрость анимации открытия / закрытия
speed: 600,
// название используемой анимации открытия / закрытия
easing: 'easeInOutExpo',
// сокрость анимации прокрутки
scrollSpeed: 900,
// анимация при прокрутке
scrollEasing: 'easeInOutExpo'
};
Инициализируем плагин вызывая функцию _init:_init: function(options) {
this.options = $.extend(true, {}, $.Accordion.defaults, options);
// проверка опций
this._validate();
// current is the index of the opened item
this.current = this.options.open;
// скрыть содержимое
this.$items.find('div.st-content').hide();
// сохранить оригинальную высоту и значение top каждого пункта
this._saveDimValues();
// если мы хотим, пункт открыт по умолчанию...
if (this.current != -1)
this._toggleItem(this.$items.eq(this.current));
// инициализируем события
this._initEvents();
},
Функция _saveDimValues сохраняет исходную высоту и значение top элемента так, чтобы мы знали до куда должны прокрутить при открытии элмента.
Если мы установили по умолчанию элемент открытым, то вызывается функция _toggleItem. Затем инициализируем событие.
Функция _toggleItem заботится о двух случаях, когда мы кликаем по пунктам, то есть при открытии и закрытии элементов. И затем прокручиваем окно до положения при котором элемент по которому кликаем, останется вверху за счет функции _scroll:
_toggleItem: function($item) {
var $content = $item.find('div.st-content');
($item.hasClass('st-open'))
?
(this.current = -1, $content.stop(true, true).fadeOut(this.options.speed), $item.removeClass('st-open').stop().animate({
height: $item.data('originalHeight')
}, this.options.speed, this.options.easing))
:
(this.current = $item.index(), $content.stop(true, true).fadeIn(this.options.speed), $item.addClass('st-open').stop().animate({
height: $item.data('originalHeight') + $content.outerHeight(true)
}, this.options.speed, this.options.easing), this._scroll(this))
},
В функции _initevents мы инициализируем два события, нажатие на пункт и изменение размеров окна. Когда мы кликаем по элементу мы или открываем или закрываем его, вызывая функцию _toggleItem и если мы установили опцию oneOpenedItem в значение true, то мы закрываем сначала любой открытый элемент прежде, чем открыть текущий.Когда окно изменено, мы должны сбросить исходные значения элемента и высоту контента. И затем элемент прокручивается к верху:
_initEvents: function() {
var instance = this;
// открыть / закрыть пункт
this.$items.find('a:first').bind('click.accordion', function(event) {
var $item = $(this).parent();
// закрыть открытый пункт, если oneOpenedItem - true
if (instance.options.oneOpenedItem && instance._isOpened() && instance.current !== $item.index()) {
instance._toggleItem(instance.$items.eq(instance.current));
}
// открыть / закрыть пункт
instance._toggleItem($item);
return false;
});
$(window).bind('smartresize.accordion', function(event) {
// сбросить исходные значения
instance._saveDimValues();
// сбросить высоту контента любого элемента, который в настоящий момент открыт
instance.$el.find('li.st-open').each(function() {
var $this = $(this);
$this.css('height', $this.data('originalHeight') + $this.find('div.st-content').outerHeight(true));
});
// прокуртка до текушего
if (instance._isOpened())
instance._scroll();
});
},
Это наиболее важные функции для данного аккордеона.