Адаптивный вертикальный аккордеон
В данном уроке мы создадим простой адаптивный аккордеон, который будет открывать разделы вниз во вертикали с плавным появлением содержания в них. Идея заключается в том, чтобы скомпоновать содержание с минимальной необходимостью для вертикальной прокрутки. Также мы будем использовать трансформации CSS3 для формирования стрелки рядом с разделом, которая будет появляться при наведении курсора мыши на название раздела и переворачиваться при открытии/закрытии. Аккордеон будет изменять размер вместе с окном браузера.
Разметка HTML
Структура HTML состоит из контейнера с идентификатором и классом st-accordion, в котором располагается неупорядоченный список. Пункты списка имеют ссылки, работающие как название пункта, и область содержания, которая изначально скрыта. Элемент span с классом st-arrow будет работать как индикатор с правой стороны от названия раздела. Он будет появляться при наведении курсора мыши на родительский элемент, то есть на ссылку.
Code
<div id="st-accordion" class="st-accordion">
<ul>
<li>
<a href="#">
Item Title
<span class="st-arrow">Open or Close</span>
</a>
<div class="st-content">
<p>Some content</p>
</div>
</li>
<li> ... </li>
</ul>
</div>
<ul>
<li>
<a href="#">
Item Title
<span class="st-arrow">Open or Close</span>
</a>
<div class="st-content">
<p>Some content</p>
</div>
</li>
<li> ... </li>
</ul>
</div>
CSS
Зададим стили для контейнера. Установим для него ширину 100%, чтобы она изменялась при изменении внешнего элемента. Вы можете использовать здесь то значение, которое нужно. Внешний элемент в демонстрации имеет ширину 90% при ограниченном максимуме 800 px. Элемент st-accordion будет иметь минимальную ширину 270 px:
Code
.st-accordion{
width:100%;
min-width:270px;
margin: 0 auto;
}
width:100%;
min-width:270px;
margin: 0 auto;
}
Предположим, что мы используем сброс CSS, который удаляет отступы и поля у неупорядоченного списка. И в таких условиях определим стили для каждого элемента списка. Установим начальную высоту равную 100 px и скроем все что выходит за границу элемента. Таким образом мы не будем видеть содержание пункта. Когда пункт открывается, изменение высоты будет анимироваться для вывода содержания. Для разделения пунктов используется верхняя и нижняя части рамки.
Code
.st-accordion ul li{
height: 100px;
border-bottom: 1px solid #c7deef;
border-top:1px solid #fff;
overflow: hidden;
}
height: 100px;
border-bottom: 1px solid #c7deef;
border-top:1px solid #fff;
overflow: hidden;
}
У первого пункта не должно быть верхней разделительной линии.
Code
.st-accordion ul li:first-child{
border-top:none;
}
border-top:none;
}
Для элемента ссылки добавляем трансформацию цвета, которая будет формировать визуальный эффект при наведении курсора мыши:
Code
.st-accordion ul li > a{
font-family: 'Josefin Slab',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;
}
font-family: 'Josefin Slab',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 для стрелки позиционируется абсолютно и скрывается за счет
установки вне элемента ссылки и полной прозрачности. Трансформация
передвинет стрелку в область видимости и плавно проявит её:
Code
.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;
}
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 будет повернут, чтобы стрелка указывала вверх:
Code
.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;
}
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;
}
Стили для элементов содержания:
Code
.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{
width:125px;
border-right:1px solid #fff;
border-bottom:1px solid #fff;
}
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{
width:125px;
border-right:1px solid #fff;
border-bottom:1px solid #fff;
}
С помощью медиа запроса мы изменяем размер шрифта на более мелкий при уменьшении ширины экрана:
Code
@media screen and (max-width: 320px){
.st-accordion ul li > a{
font-size:36px;
}
}
.st-accordion ul li > a{
font-size:36px;
}
}
JavaScript
Рассмотрим важные части плагина. Начнем с определения опций и их значений по умолчанию:
Code
$.Accordion.defaults = {
// Индекс открытого пункта. -1 означает, что все пункты закрыты по умолчанию.
open : -1,
// Если данная опция имеет значение true, то только один пункт может быть открыт. При открытии пункта другой открытый пункт закрывается.
oneOpenedItem : false,
// Скорость анимации открытия/закрытия
speed : 600,
// Эффект анимации открытия/закрытия
easing : 'easeInOutExpo',
// Скорость прокрутки анимации действия
scrollSpeed : 900,
// Эффект прокрутки анимации действия
scrollEasing : 'easeInOutExpo'
};
// Индекс открытого пункта. -1 означает, что все пункты закрыты по умолчанию.
open : -1,
// Если данная опция имеет значение true, то только один пункт может быть открыт. При открытии пункта другой открытый пункт закрывается.
oneOpenedItem : false,
// Скорость анимации открытия/закрытия
speed : 600,
// Эффект анимации открытия/закрытия
easing : 'easeInOutExpo',
// Скорость прокрутки анимации действия
scrollSpeed : 900,
// Эффект прокрутки анимации действия
scrollEasing : 'easeInOutExpo'
};
Плагин инициализируется вызовом функции _init:
Code
_init : function( options ) {
this.options = $.extend( true, {}, $.Accordion.defaults, options );
// Проверка опций
this._validate();
// current - индекс открытого пункта
this.current = this.options.open;
// Скрываем содержание, чтобы вывести его потом
this.$items.find('div.st-content').hide();
// Сохраняем оригинальную высоту и координату по вертикали для каждого пункта
this._saveDimValues();
// Если нужно по умолчанию открыть пункт
if( this.current != -1 )
this._toggleItem( this.$items.eq( this.current ) );
// Инициализируем события
this._initEvents();
},
this.options = $.extend( true, {}, $.Accordion.defaults, options );
// Проверка опций
this._validate();
// current - индекс открытого пункта
this.current = this.options.open;
// Скрываем содержание, чтобы вывести его потом
this.$items.find('div.st-content').hide();
// Сохраняем оригинальную высоту и координату по вертикали для каждого пункта
this._saveDimValues();
// Если нужно по умолчанию открыть пункт
if( this.current != -1 )
this._toggleItem( this.$items.eq( this.current ) );
// Инициализируем события
this._initEvents();
},
Функция _saveDimValues сохраняет оригинальные значения высоты и координаты пункта, так что мы знаем куда нужно прокручивать содержание, когда пункт открывается.
Если есть пункт, который должен быть открыт по умолчанию, то вызываем функцию _toggleItem. А затем инициализируем события.
Функция _toggleItem обрабатывает два варианта при нажатии кнопки мыши на пункте. Либо пункт уже открыт, то есть имеет класс st-open, либо он закрыт. Если он открыт, присваиваем переменной current значение -1 и скрываем содержание, изменяя высоту пункта до оригинального значения. Если пункт закрыт, то мы присваиваем переменной currrent индекс пункта, анимируем изменение высоты и прозрачности содержания для вывода на экран. Затем мы прокручиваем окно вниз с помощью функции _scroll, чтобы открытый пункт оказался вверху:
Code
// Открыть / закрыть пункт
_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 ) )
},
_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, то сначала закрывается другой открытый пункт.
Когда окно изменяет размеры, нужно сбросить оригинальные значения положения пункта и высоты его содержания. Также нужно прокрутить окно, чтобы пункт находился вверху.
Code
_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();
});
},
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();
});
},
Выше описаны самые важные функции кода. Полностью текст JavaScript плагина вы можете посмотреть в исходниках.
-
FalleN -
4232 -
1 -
270
Но только нужно ставить наверное на те модули которые обновляться должны не раньше через пару тройку минут
С Уважением, Андрей...