Привет! Сегодня я покажу вам как использовать плагин BookBlock в полноэкранном режиме, к примеру реализуем удобный просмотр новостей. Я решил создать полноэкранный макет, применить к нему BookBlock и добавить меню в боковую панель. Также я покажу вам, как настроить BookBlock и использовать его опции для навигации по содержимому страницы.
Идея заключается в том, чтобы перемещаться, к примеру, по новостям с помощью стрелок или проводя пальцем по странице (если вы просматриваете новости с смартфона/планшета), также открывать/скрывать меню при нажатии на кнопку меню. Боковое меню будет содержать ссылки на разные страницы/новости. Мы будем также использовать плагин JScrollPane, чтобы добавить прокрутку для содержания в случае необходимости.
Будут использоваться следующие библиотеки и плагины JQuery:
1. BookBlock
2. JQuery
3. JScrollPane
4. jQuery Mouse Wheel
5. Modernizr
И так, давайте начнем!
Создаем общий контейнер для всех наших элементов. Внутри мы добавим блок для бокового меню, которому дадим класс "menu-panel", и блок-оболочку для BookBlock с классом «bb-custom-wrapper". В последнем блоке у нас будет структура, которую требует сам плагин BookBlock. Внутри каждого элемента, мы добавим блок-обертку, чтобы реализовать функционал прокрутки:
HTML
<div id="container" class="container"> <div class="menu-panel"> <h3>Меню</h3> <ul id="menu-toc" class="menu-toc"> <li class="menu-toc-current"><a href="#item1">Новость 1</a></li> <li><a href="#item2">Новость 2</a></li> <li><a href="#item3">Новость 3</a></li> <li><a href="#item4">Новость 4</a></li> <li><a href="#item5">Новость 5</a></li> </ul> </div> <div class="bb-custom-wrapper"> <div id="bb-bookblock" class="bb-bookblock"> <div class="bb-item" id="item1"> <div class="content"> <div class="scroller"> <h2>Новость 1</h2> <p>...</p> </div> </div><!-- /content --> </div><!-- /bb-item --> <div class="bb-item" id="item2"><!-- ... --></div> <div class="bb-item" id="item3"><!-- ... --></div> <div class="bb-item" id="item4"><!-- ... --></div> <div class="bb-item" id="item5"><!-- ... --></div> </div><!-- /bb-bookblock --> <nav> <a id="bb-nav-prev" href="#">←</a> <a id="bb-nav-next" href="#">→</a> </nav> <span id="tblcontents" class="menu-button">Меню</span> </div><!-- /bb-custom-wrapper --> </div><!-- /container -->
Пункты меню будут указаны на соответствующих страницах BookBlock (bb-item). Также добавим навигационные стрелки и кнопку для переключения открытия и закрытия меню.
Давайте перейдем к стилям.
CSS
Не будем обсуждать стили плагина BookBlock (вы можете их найти в bookblock.css), вместо этого, мы сосредоточимся на всех других стилях, которые важны для макета и настройки некоторых вещей.
Давайте начнем с импорта шрифта Lato, одного с веб-шрифтов Google:
@import url(http://fonts.googleapis.com/css?family=Lato:300,400,700);
HTML блок должен иметь высоту 100%, так как нам нужно будет установить абсолютную высоту внутренних элементов и расширить их к высоте окна:
html { height: 100%; }
Применим свойство box-sizing для изменения алгоритма расчета ширины и высоты элемента.
Согласно спецификации CSS ширина блока складывается из ширины контента (width), значений отступов (margin), полей (padding) и границ (border). Аналогично обстоит и с высотой блока. Свойство box-sizing позволяет изменить этот алгоритм, чтобы свойства width и height задавали размеры не контента, а размеры блока. Значение border-box означает, что width и height включают в себя значения полей и границ, но не отступов (margin).
*, *:after, *:before { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; padding: 0; margin: 0; }
Давайте определим шрифт для body и установим высоту 100%. Помните, нам нужно это сделать из-за дочерних элементов:
body { font-family: 'Lato', Calibri, Arial, sans-serif; font-weight: 400; font-size: 100%; color: #333; height: 100%; }
Мы используем Modernizr и добавим класс "no-js" к HTML элементам. Когда JavaScript включен в браузере, Modernizr заменит этот класс с "JS". Это позволит нам задать определенные свойства CSS к элементам, которые нам не нужны, если JavaScript отключен. 100% ширина и высота макета имеют смысл только если JS включен. В этом случае нам понадобится свойство overflow:
.js body { overflow: hidden; }
Стили для ссылок:
a { color: #555; text-decoration: none; } a:hover { color: #000; }
Мы хотим, чтобы главный контейнер, занял всю ширину и высоту окна. Боковое меню позиционируем вне этого блока, установив отрицательное значение left. Идея заключается в том, что мы оживим весь контейнер при нажатии на кнопку открытия меню. Главный блок будет скользить вправо раскрывая боковое меню.
Устанавливаем ширину и высоту главного блока 100% и добавляем свойство transition к контейнеру для красоты:
.container, .bb-custom-wrapper, .bb-bookblock { width: 100%; height: 100%; } .container { position: relative; left: 0px; transition: left 0.3s ease-in-out; }
При нажатии на кнопку меню, добавим еще один класс к контейнеру, который будет устанавливать значение left в 240 пикселей (это ширина бокового меню):
.slideRight { left: 240px; }
При выключенном JS мы не сможем добавить класс slideRight, поэтому в этом случае сделаем это вручную:
.no-js .container { padding-left: 240px; }
По дефолту, закрепим боковое меню слева:
.menu-panel { background: #f1103a; width: 240px; height: 100%; position: fixed; z-index: 1000; top: 0; left: 0; text-shadow: 0 1px 1px rgba(0,0,0,0.1); }
Если JS включен, выставляем значения свойств position и left:
.js .menu-panel { position: absolute; left: -240px; }
Стили элементов меню:
.menu-panel h3 { font-size: 1.8em; padding: 20px; font-weight: 300; color: #fff; box-shadow: inset 0 -1px 0 rgba(0,0,0,0.05); } .menu-toc { list-style: none; } .menu-toc li a { display: block; color: #fff; font-size: 1.1em; line-height: 3.5; padding: 0 20px; cursor: pointer; background: #f1103a; border-bottom: 1px solid #dd1338; } .menu-toc li a:hover, .menu-toc li.menu-toc-current a{ background: #dd1338; }
Блок навигации должен абсолютно позиционироваться сверху:
.bb-custom-wrapper nav { top: 20px; left: 60px; position: absolute; z-index: 1000; }
Стрелки навигации и кнопка меню, должны также быть с абсолютным позиционированием, плюс сделаем их круглыми при помощи border-radius:
.bb-custom-wrapper nav span, .menu-button { position: absolute; width: 32px; height: 32px; top: 0; left: 0; background: #f1103a; border-radius: 50%; color: #fff; line-height: 30px; text-align: center; speak: none; font-weight: bold; cursor: pointer; } .bb-custom-wrapper nav span:last-child { left: 40px; } .bb-custom-wrapper nav span:hover, .menu-button:hover { background: #000; }
Кнопка меню будет позиционироваться в верхнем левом углу, и мы заодно спрячем его текст:
.menu-button { z-index: 1000; left: 20px; top: 20px; text-indent: -9000px; }
В случае если JS не включен нам не нужны эти элементы, так что просто скрываем их:
.no-js .bb-custom-wrapper nav span, .no-js .menu-button { display: none; }
Давайте перейдем к внутренностям элементов BookBlock. У них позиционирование должно быть абсолютным и мы установим также свойство overflow в hidden. Это важно, поскольку мы хотим применить здесь наш кастомный скролл, делать это мы будем только когда была применена прокрутка на странице. Если мы не будем устанавливать overflow в hidden, то будет видно все содержание, которое переполнит блок. Опять же ж, это имеет смысл только когда включен JS:
.js .content { position: absolute; top: 60px; left: 0; bottom: 50px; width: 100%; overflow: hidden; }
Отступы для блока самого скрола:
.scroller { padding: 10px 5% 10px 5%; }
Сделаем градиент для текста сверху и снизу дабы скрыть острые края букв:
.js .content:before, .js .content:after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 20px; z-index: 100; pointer-events: none; background: linear-gradient( to bottom, rgba(255,255,255,1) 0%, rgba(255,255,255,0) 100% ); } .js .content:after { top: auto; bottom: 0; background: linear-gradient( to top, rgba(255,255,255,1) 0%, rgba(255,255,255,0) 100% ); }
Стили для текстовых элементов:
.content h2 { font-weight: 300; font-size: 4em; padding: 0 0 10px; color: #333; margin: 0 1% 40px; text-align: left; box-shadow: 0 10px 0 rgba(0,0,0,0.02); text-shadow: 0 0 2px #fff; } .no-js .content h2 { padding: 40px 1% 20px; } .content p { font-size: 1.2em; line-height: 1.6; font-weight: 300; padding: 5px 8%; text-align: justify; }
Наконец, давайте добавим некоторые media запросы. Когда JavaScript выключен, нам не нужно к примеру чтобы меню было больше 800 пикселей. Это один пример того, как мы можем контролировать эти элементы при определенных условиях.
@media screen and (max-width: 800px){ .no-js .menu-panel { display: none; } .no-js .container { padding: 0; } } @media screen and (max-width: 400px){ .menu-panel, .content { font-size: 75%; } }
JQuery
Инициализируем скрипты и задаем некоторые настройки:
var $container = $( '#container' ), // элемент, к которому применяем плагин BookBlock $bookBlock = $( '#bb-bookblock' ), // элементы BookBlock (bb-item) $items = $bookBlock.children(), // номер текущего элемента current = 0, // инициализация плагина BookBlock bb = $( '#bb-bookblock' ).bookblock( { speed : 800, perspective : 2000, shadowSides : 0.8, shadowFlip : 0.4, // после каждого перелистывания страниц onEndFlip : function(old, page, isLimit) { // обновление текущего значения current = page; // обновление выбранного элемента в боковом меню updateTOC(); // показать и/или скрыть стрелки навигации updateNavigation( isLimit ); // инициализация плагина jScrollPane для блока контента нового элемента setJSP( 'init' ); // удалям jScrollPane для блока контента старого элемента setJSP( 'destroy', old ); } } ), // стрелки навигации $navNext = $( '#bb-nav-next' ), $navPrev = $( '#bb-nav-prev' ).hide(), //элементы меню $menuItems = $container.find( 'ul.menu-toc > li' ), $tblcontents = $( '#tblcontents' ), transEndEventNames = { 'WebkitTransition': 'webkitTransitionEnd', 'MozTransition': 'transitionend', 'OTransition': 'oTransitionEnd', 'msTransition': 'MSTransitionEnd', 'transition': 'transitionend' }, transEndEventName = transEndEventNames[Modernizr.prefixed('transition')], supportTransitions = Modernizr.csstransitions;
Во-первых, давайте связывать события некоторых из элементов, инициализированных ранее. Кроме того, мы должны инициализировать JScrollPane для первого (текущего) пункта.
function init() { setJSP( 'init' ); initEvents(); }
В конечном итоге необходимо инициализировать, пере инициализировать и уничтожить JScrollPane, давайте определим функцию для этого:
function setJSP( action, idx ) { var idx = idx === undefined ? current : idx, $content = $items.eq( idx ).children( 'div.content' ), apiJSP = $content.data( 'jsp' ); if( action === 'init' && apiJSP === undefined ) { $content.jScrollPane({verticalGutter : 0, hideFocus : true }); } else if( action === 'reinit' && apiJSP !== undefined ) { apiJSP.reinitialise(); } else if( action === 'destroy' && apiJSP !== undefined ) { apiJSP.destroy(); } }
Нам нужно будет привязать несколько событий:
1. Мы будем вызывать методы next() и prev плагина BookBlock при нажатии стрелки навигации или при проведении мышкой (или пальцем) по странице.
2. Меню должно скрываться/показываться при клике по кнопке меню ($tblcontents).
3. Мы будем вызывать метод jump() плагина BookBlock при нажатии на пункт меню.
4. JScrollPane будет инициализирован при изменении размеров окна.
Приступим:
function initEvents() { $navNext.on( 'click', function() { bb.next(); return false; } ); $navPrev.on( 'click', function() { bb.prev(); return false; } ); $items.on( { 'swipeleft' : function( event ) { if( $container.data( 'opened' ) ) { return false; } bb.next(); return false; }, 'swiperight' : function( event ) { if( $container.data( 'opened' ) ) { return false; } bb.prev(); return false; } } ); $tblcontents.on( 'click', toggleTOC ); $menuItems.on( 'click', function() { var $el = $( this ), idx = $el.index(), jump = function() { bb.jump( idx + 1 ); }; current !== idx ? closeTOC( jump ) : closeTOC(); return false; } ); $( window ).on( 'debouncedresize', function() { setJSP( 'reinit' ); } ); }
Видимость стрелок навигации будет зависеть от текущей страницы, то есть если мы находимся на первой странице, то видим только одну стрелку "вправо", если на последней странице, то "влево" и в случае если это промежуточная страница, то видим обе стрелки.
function updateNavigation( isLastPage ) { if( current === 0 ) { $navNext.show(); $navPrev.hide(); } else if( isLastPage ) { $navNext.hide(); $navPrev.show(); } else { $navNext.show(); $navPrev.show(); } }
При открытом меню сделаем возможность скрыть кнопки навигации и покажем их только при скрытом меню. Анимировать все будем при помощи CSS, но в случае если некоторые свойства не поддерживаются, будем использовать обычные методы show и hide:
function toggleTOC() { var opened = $container.data( 'opened' ); opened ? closeTOC() : openTOC(); } function openTOC() { $navNext.hide(); $navPrev.hide(); $container.addClass( 'slideRight' ).data( 'opened', true ); } function closeTOC( callback ) { $navNext.show(); $navPrev.show(); $container.removeClass( 'slideRight' ).data( 'opened', false ); if( callback ) { if( supportTransitions ) { $container.on( transEndEventName, function() { $( this ).off( transEndEventName ); callback.call(); } ); } else { callback.call(); } } }
Ну вот, вроде и все) Надеюсь урок был вам полезен. Добавляйтесь к нам в соц. сети дабы быть в курсе новых событий. Скоро увидимся!