Анимированное меню на границах страницы
Недавно мы натолкнулись на интересное меню на сайте UI8. Поэтому сегодня рассмотрим как можно реализовать подобные примеры для своих сайтов.
HTML
Навигация будет состоять из ненумерованного списка, помещённого в элемент nav. Через атрибут класс передаём какая иконка должна быть прикреплена к элементу:
Теперь давайте оформим всё это дело.
CSS
Обратите внимание, что код с браузерными префиксами, можете найти в исходниках. Воспользуемся свойством box-sizing:
Зададим общие стили для body и основного контейнера:
Внутренние отступы можем использовать для расширения нужного нам пространства.
Основной элемент навигации будет располагаться фиксировано в зависимости от того, какой пример мы запустим. При раскрытии меню, меняем ширину рамки. Сначала высота рамки будет равна 0. Далее мы её расширим с задержкой в 0.3 сек:
При раскрытии меню меняем высоту и ставим значение 100%, а рамку смещаем на 90px влево и на 30px со всех других сторон. Цвет фона выставим в формате RGBA:
Далее применим один финт. Через JavaScript добавим невидимый элемент при клике на который, поставленная нами рамка будет исчезать. Он будет расширен на всю страниц
При открытии меню, расширяем данный элемент:
При отображении меню, будем затемнять основную область. Остальные две области будут созданы псевдо-элементами. При открытом меню, средняя линия исчезнет:
Псевдо-элементы расположим абсолютно и их высота будет такой же как у родительского элемента - 100%:
Для того позиционирования, воспользуемся свойством translateY:
Ненумерованные списки с иконками расположим фиксированно и поместим в левую часть экрана:
Давайте зададим элементам меню блочный вид расположения display: block, а так же ширину:
Каждый элемент списка изначально будет скрыт. Анимацию появления реализуем позже:
Теперь давайте расположим все элементы меню по центру слева , до тех пор пока они не отображаемые (-100% на оси Y):
При открытии меню, элементы списка станут видимыми, а затем применяем эффект плавного появления. Так же изменим значение transform до 0, для достижения 3d эффекта:
Теперь займёмся ссылками. В качестве шрифтов будем использовать иконки. Задаём размер шрифта, равный 0, и делаем его невидимым:
Сбросим размер текста псевдо-элементов, которые содержат иконки. Значения em тут работать не будут, поэтому задаём размеры в пикселях:
При наведении мыши сделаем их цвет белым:
Сделаем иконки чуть меньше, если пользователь просматривает сайт через мобильное устройство:
о стилями всё. Приступаем к JavaScript.
JAVASCRIPT
Наш скрипт очень простой; при клике по ссылке, мы прикрепляем или открепляем классы bt-menu-open и bt-menu-close.
При клике на свободную область, меню будет закрыто. Так же нам нужно обеспечить поддержку событий прикосновений:
Вот и всё! Я надеюсь, данный урок будет вам полезен!
HTML
Навигация будет состоять из ненумерованного списка, помещённого в элемент nav. Через атрибут класс передаём какая иконка должна быть прикреплена к элементу:
Код
<nav id="bt-menu" class="bt-menu">
<a href="#" class="bt-menu-trigger"><span>Menu</span></a>
<ul>
<li><a href="#" class="bt-icon icon-zoom">Zoom</a></li>
<li><a href="#" class="bt-icon icon-refresh">Refresh</a></li>
<li><a href="#" class="bt-icon icon-lock">Lock</a></li>
<li><a href="#" class="bt-icon icon-speaker">Sound</a></li>
<li><a href="#" class="bt-icon icon-star">Favorite</a></li>
</ul>
</nav>
<a href="#" class="bt-menu-trigger"><span>Menu</span></a>
<ul>
<li><a href="#" class="bt-icon icon-zoom">Zoom</a></li>
<li><a href="#" class="bt-icon icon-refresh">Refresh</a></li>
<li><a href="#" class="bt-icon icon-lock">Lock</a></li>
<li><a href="#" class="bt-icon icon-speaker">Sound</a></li>
<li><a href="#" class="bt-icon icon-star">Favorite</a></li>
</ul>
</nav>
Теперь давайте оформим всё это дело.
CSS
Обратите внимание, что код с браузерными префиксами, можете найти в исходниках. Воспользуемся свойством box-sizing:
Код
*,
*:after,
*::before {
box-sizing: border-box;
}
*:after,
*::before {
box-sizing: border-box;
}
Зададим общие стили для body и основного контейнера:
Код
body {
background: #04a466;
}
.container {
padding: 80px;
}
background: #04a466;
}
.container {
padding: 80px;
}
Внутренние отступы можем использовать для расширения нужного нам пространства.
Основной элемент навигации будет располагаться фиксировано в зависимости от того, какой пример мы запустим. При раскрытии меню, меняем ширину рамки. Сначала высота рамки будет равна 0. Далее мы её расширим с задержкой в 0.3 сек:
Код
.bt-menu {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 0;
border-width: 0px;
border-style: solid;
border-color: #333;
background-color: rgba(0,0,0,0);
transition: border-width 0.3s, background-color 0.3s, height 0s 0.3s;
}
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 0;
border-width: 0px;
border-style: solid;
border-color: #333;
background-color: rgba(0,0,0,0);
transition: border-width 0.3s, background-color 0.3s, height 0s 0.3s;
}
При раскрытии меню меняем высоту и ставим значение 100%, а рамку смещаем на 90px влево и на 30px со всех других сторон. Цвет фона выставим в формате RGBA:
Код
.bt-menu.bt-menu-open {
height: 100%;
border-width: 30px 30px 30px 90px;
background-color: rgba(0,0,0,0.3);
transition: border-width 0.3s, background-color 0.3s;
}
height: 100%;
border-width: 30px 30px 30px 90px;
background-color: rgba(0,0,0,0.3);
transition: border-width 0.3s, background-color 0.3s;
}
Далее применим один финт. Через JavaScript добавим невидимый элемент при клике на который, поставленная нами рамка будет исчезать. Он будет расширен на всю страниц
Код
.bt-overlay {
position: absolute;
width: 100%;
}
position: absolute;
width: 100%;
}
При открытии меню, расширяем данный элемент:
Код
.bt-menu-open .bt-overlay {
height: 100%;
}
.bt-menu-trigger {
position: fixed;
top: 15px;
left: 20px;
display: block;
width: 50px;
height: 50px;
cursor: pointer;
}
.bt-menu-trigger span {
position: absolute;
top: 50%;
left: 0;
display: block;
width: 100%;
height: 4px;
margin-top: -2px;
background-color: #fff;
font-size: 0px;
user-select: none;
transition: background-color 0.3s;
}
height: 100%;
}
.bt-menu-trigger {
position: fixed;
top: 15px;
left: 20px;
display: block;
width: 50px;
height: 50px;
cursor: pointer;
}
.bt-menu-trigger span {
position: absolute;
top: 50%;
left: 0;
display: block;
width: 100%;
height: 4px;
margin-top: -2px;
background-color: #fff;
font-size: 0px;
user-select: none;
transition: background-color 0.3s;
}
При отображении меню, будем затемнять основную область. Остальные две области будут созданы псевдо-элементами. При открытом меню, средняя линия исчезнет:
Код
.bt-menu-open .bt-menu-trigger span {
background-color: transparent;
}
background-color: transparent;
}
Псевдо-элементы расположим абсолютно и их высота будет такой же как у родительского элемента - 100%:
Код
.bt-menu-trigger span:before,
.bt-menu-trigger span:after {
position: absolute;
left: 0;
width: 100%;
height: 100%;
background: #fff;
content: '';
transition: transform 0.3s;
}
.bt-menu-trigger span:after {
position: absolute;
left: 0;
width: 100%;
height: 100%;
background: #fff;
content: '';
transition: transform 0.3s;
}
Для того позиционирования, воспользуемся свойством translateY:
Код
.bt-menu-trigger span:before {
transform: translateY(-250%);
}
.bt-menu-trigger span:after {
transform: translateY(250%);
}
.bt-menu-open .bt-menu-trigger span:before {
transform: translateY(0) rotate(45deg);
}
.bt-menu-open .bt-menu-trigger span:after {
transform: translateY(0) rotate(-45deg);
}
transform: translateY(-250%);
}
.bt-menu-trigger span:after {
transform: translateY(250%);
}
.bt-menu-open .bt-menu-trigger span:before {
transform: translateY(0) rotate(45deg);
}
.bt-menu-open .bt-menu-trigger span:after {
transform: translateY(0) rotate(-45deg);
}
Ненумерованные списки с иконками расположим фиксированно и поместим в левую часть экрана:
Код
.bt-menu ul {
position: fixed;
top: 75px;
left: 0;
margin: 0;
padding: 0;
width: 90px;
list-style: none;
backface-visibility: hidden;
}
position: fixed;
top: 75px;
left: 0;
margin: 0;
padding: 0;
width: 90px;
list-style: none;
backface-visibility: hidden;
}
Давайте зададим элементам меню блочный вид расположения display: block, а так же ширину:
Код
.bt-menu ul li,
.bt-menu ul li a {
display: block;
width: 100%;
text-align: center;
}
.bt-menu ul li a {
display: block;
width: 100%;
text-align: center;
}
Каждый элемент списка изначально будет скрыт. Анимацию появления реализуем позже:
Код
.bt-menu ul li {
padding: 16px 0;
opacity: 0;
visibility: hidden;
transition: transform 0.3s, opacity 0.2s, visibility 0s 0.3s;
}
padding: 16px 0;
opacity: 0;
visibility: hidden;
transition: transform 0.3s, opacity 0.2s, visibility 0s 0.3s;
}
Теперь давайте расположим все элементы меню по центру слева , до тех пор пока они не отображаемые (-100% на оси Y):
Код
.bt-menu ul li:first-child {
transform: translate3d(-100%,200%,0);
}
.bt-menu ul li:nth-child(2) {
transform: translate3d(-100%,100%,0);
}
.bt-menu ul li:nth-child(3) {
transform: translate3d(-100%,0,0);
}
.bt-menu ul li:nth-child(4) {
transform: translate3d(-100%,-100%,0);
}
.bt-menu ul li:nth-child(5) {
transform: translate3d(-100%,-200%,0);
}
transform: translate3d(-100%,200%,0);
}
.bt-menu ul li:nth-child(2) {
transform: translate3d(-100%,100%,0);
}
.bt-menu ul li:nth-child(3) {
transform: translate3d(-100%,0,0);
}
.bt-menu ul li:nth-child(4) {
transform: translate3d(-100%,-100%,0);
}
.bt-menu ul li:nth-child(5) {
transform: translate3d(-100%,-200%,0);
}
При открытии меню, элементы списка станут видимыми, а затем применяем эффект плавного появления. Так же изменим значение transform до 0, для достижения 3d эффекта:
Код
.bt-menu.bt-menu-open ul li {
visibility: visible;
opacity: 1;
transition: transform 0.3s, opacity 0.3s;
transform: translate3d(0,0,0);
}
visibility: visible;
opacity: 1;
transition: transform 0.3s, opacity 0.3s;
transform: translate3d(0,0,0);
}
Теперь займёмся ссылками. В качестве шрифтов будем использовать иконки. Задаём размер шрифта, равный 0, и делаем его невидимым:
Код
.bt-menu ul li a {
display: block;
outline: none;
color: transparent;
text-decoration: none;
font-size: 0px;
}
display: block;
outline: none;
color: transparent;
text-decoration: none;
font-size: 0px;
}
Сбросим размер текста псевдо-элементов, которые содержат иконки. Значения em тут работать не будут, поэтому задаём размеры в пикселях:
Код
.bt-menu ul li a:before {
color: #04a466;
font-size: 48px;
transition: color 0.2s;
}
color: #04a466;
font-size: 48px;
transition: color 0.2s;
}
При наведении мыши сделаем их цвет белым:
Код
.bt-menu ul li a:hover:before,
.bt-menu ul li a:focus:before {
color: #fff;
}
.bt-menu ul li a:focus:before {
color: #fff;
}
Сделаем иконки чуть меньше, если пользователь просматривает сайт через мобильное устройство:
Код
@media screen and (max-height: 31.125em) {
.bt-menu ul li a:before {
font-size: 32px;
}
}
.bt-menu ul li a:before {
font-size: 32px;
}
}
о стилями всё. Приступаем к JavaScript.
JAVASCRIPT
Наш скрипт очень простой; при клике по ссылке, мы прикрепляем или открепляем классы bt-menu-open и bt-menu-close.
При клике на свободную область, меню будет закрыто. Так же нам нужно обеспечить поддержку событий прикосновений:
Код
(function() {
function mobilecheck() {
var check = false;
(function(a){if(/(android|ipad|playbook|silk|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4)))check = true})(navigator.userAgent||navigator.vendor||window.opera);
return check;
}
function init() {
var menu = document.getElementById( 'bt-menu' ),
trigger = menu.querySelector( 'a.bt-menu-trigger' ),
// тип события (если мобильное устройство, то используются события нажатий)
eventtype = mobilecheck() ? 'touchstart' : 'click',
resetMenu = function() {
classie.remove( menu, 'bt-menu-open' );
classie.add( menu, 'bt-menu-close' );
},
closeClickFn = function( ev ) {
resetMenu();
overlay.removeEventListener( eventtype, closeClickFn );
};
var overlay = document.createElement('div');
overlay.className = 'bt-overlay';
menu.appendChild( wrapper );
trigger.addEventListener( eventtype, function( ev ) {
ev.stopPropagation();
ev.preventDefault();
if( classie.has( menu, 'bt-menu-open' ) ) {
resetMenu();
}
else {
classie.remove( menu, 'bt-menu-close' );
classie.add( menu, 'bt-menu-open' );
overlay.addEventListener( eventtype, closeClickFn );
}
});
}
init();
})();
function mobilecheck() {
var check = false;
(function(a){if(/(android|ipad|playbook|silk|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4)))check = true})(navigator.userAgent||navigator.vendor||window.opera);
return check;
}
function init() {
var menu = document.getElementById( 'bt-menu' ),
trigger = menu.querySelector( 'a.bt-menu-trigger' ),
// тип события (если мобильное устройство, то используются события нажатий)
eventtype = mobilecheck() ? 'touchstart' : 'click',
resetMenu = function() {
classie.remove( menu, 'bt-menu-open' );
classie.add( menu, 'bt-menu-close' );
},
closeClickFn = function( ev ) {
resetMenu();
overlay.removeEventListener( eventtype, closeClickFn );
};
var overlay = document.createElement('div');
overlay.className = 'bt-overlay';
menu.appendChild( wrapper );
trigger.addEventListener( eventtype, function( ev ) {
ev.stopPropagation();
ev.preventDefault();
if( classie.has( menu, 'bt-menu-open' ) ) {
resetMenu();
}
else {
classie.remove( menu, 'bt-menu-close' );
classie.add( menu, 'bt-menu-open' );
overlay.addEventListener( eventtype, closeClickFn );
}
});
}
init();
})();
Вот и всё! Я надеюсь, данный урок будет вам полезен!
-
FalleN -
3512 -
1 -
213
Но только нужно ставить наверное на те модули которые обновляться должны не раньше через пару тройку минут
С Уважением, Андрей...