Sử dụng CSS3 và Javasript tạo Menu cho Mobile
Việc làm cho menu trở nên linh động và gọn gàng hơn khi hiển thị trên các thiết bị mobile là một trong những điều mà chúng ta cần phải làm để tạo giao diện web thân thiện với người dùng. Hôm nay iZdesigner sẽ giới thiệu cho các bạn một mẫu menu đa cấp rất thích hợp tích hợp cho các giao diện mobile. Menu này không những nhỏ gọn mà còn có những hiệu ứng đẹp mắt.
HTML
Đầu tiên, các bạn tạo menu theo khung chuẩn html như sau :
<div class="container">
<div class="mp-pusher" id="mp-pusher">
<!-- mp-menu -->
<nav id="mp-menu" class="mp-menu">
<div class="mp-level">
<h2 class="icon icon-world">All Categories <a href="#" class="close">×</a></h2>
<ul>
<li class="icon icon-arrow-left">
<a class="icon icon-display" href="#">Devices</a>
<div class="mp-level">
<h2 class="icon icon-display">Devices</h2>
<a class="mp-back" href="#">back</a>
<ul>
<li class="icon icon-arrow-left">
<a class="icon icon-phone" href="#">Mobile Phones</a>
<div class="mp-level">
<h2>Mobile Phones</h2>
<a class="mp-back" href="#">back</a>
<ul>
<li><a href="#">Super Smart Phone</a></li>
<li><a href="#">Thin Magic Mobile</a></li>
<li><a href="#">Performance Crusher</a></li>
<li><a href="#">Futuristic Experience</a></li>
</ul>
</div>
</li>
<li class="icon icon-arrow-left">
<a class="icon icon-tv" href="#">Televisions</a>
<div class="mp-level">
<h2>Televisions</h2>
<a class="mp-back" href="#">back</a>
<ul>
<li><a href="#">Flat Superscreen</a></li>
<li><a href="#">Gigantic LED</a></li>
<li><a href="#">Power Eater</a></li>
<li><a href="#">3D Experience</a></li>
<li><a href="#">Classic Comfort</a></li>
</ul>
</div>
</li>
<li class="icon icon-arrow-left">
<a class="icon icon-camera" href="#">Cameras</a>
<div class="mp-level">
<h2>Cameras</h2>
<a class="mp-back" href="#">back</a>
<ul>
<li><a href="#">Smart Shot</a></li>
<li><a href="#">Power Shooter</a></li>
<li><a href="#">Easy Photo Maker</a></li>
<li><a href="#">Super Pixel</a></li>
</ul>
</div>
</li>
</ul>
</div>
</li>
<li class="icon icon-arrow-left">
<a class="icon icon-news" href="#">Magazines</a>
<div class="mp-level">
<h2 class="icon icon-news">Magazines</h2>
<a class="mp-back" href="#">back</a>
<ul>
<li><a href="#">National Geographic</a></li>
<li><a href="#">Scientific American</a></li>
<li><a href="#">The Spectator</a></li>
<li><a href="#">The Rambler</a></li>
<li><a href="#">Physics World</a></li>
<li><a href="#">The New Scientist</a></li>
</ul>
</div>
</li>
<li class="icon icon-arrow-left">
<a class="icon icon-shop" href="#">Store</a>
<div class="mp-level">
<h2 class="icon icon-shop">Store</h2>
<a class="mp-back" href="#">back</a>
<ul>
<li class="icon icon-arrow-left">
<a class="icon icon-t-shirt" href="#">Clothes</a>
<div class="mp-level">
<h2 class="icon icon-t-shirt">Clothes</h2>
<a class="mp-back" href="#">back</a>
<ul>
<li class="icon icon-arrow-left">
<a class="icon icon-female" href="#">Women's Clothing</a>
<div class="mp-level">
<h2 class="icon icon-female">Women's Clothing</h2>
<a class="mp-back" href="#">back</a>
<ul>
<li><a href="#">Tops</a></li>
<li><a href="#">Dresses</a></li>
<li><a href="#">Trousers</a></li>
<li><a href="#">Shoes</a></li>
<li><a href="#">Sale</a></li>
</ul>
</div>
</li>
<li class="icon icon-arrow-left">
<a class="icon icon-male" href="#">Men's Clothing</a>
<div class="mp-level">
<h2 class="icon icon-male">Men's Clothing</h2>
<a class="mp-back" href="#">back</a>
<ul>
<li><a href="#">Shirts</a></li>
<li><a href="#">Trousers</a></li>
<li><a href="#">Shoes</a></li>
<li><a href="#">Sale</a></li>
</ul>
</div>
</li>
</ul>
</div>
</li>
<li>
<a class="icon icon-diamond" href="#">Jewelry</a>
</li>
<li>
<a class="icon icon-music" href="#">Music</a>
</li>
<li>
<a class="icon icon-food" href="#">Grocery</a>
</li>
</ul>
</div>
</li>
<li><a class="icon icon-photo" href="#">Collections</a></li>
<li><a class="icon icon-wallet" href="#">Credits</a></li>
</ul>
</div>
</nav>
<!-- /mp-menu -->
<div class="scroller"><!-- this is for emulating position fixed of the nav -->
<div class="scroller-inner">
<h1><a href="#" id="trigger" class="menu-trigger">Open/Close Menu</a></h1>
</div>
</div>
</div>
</div>
CSS
Sau đó các bạn định dạng menu với đoạn css sau :
.clearfix:before,
.clearfix:after {
display: table;
content: " ";
}
.clearfix:after {
clear: both;
}
.codrops-header,
.codrops-top {
font-family: 'Lato', Arial, sans-serif;
}
.codrops-header {
margin: 0 auto;
padding: 2em;
background: rgba(0, 0, 0, 0.01);
text-align: center;
}
.codrops-header h1 {
margin: 0;
font-weight: 300;
font-size: 2.625em;
line-height: 1.3;
}
.codrops-header span {
display: block;
padding: 0 0 0.6em 0.1em;
font-size: 60%;
opacity: 0.7;
}
/* To Navigation Style */
.codrops-top {
width: 100%;
background: #91cfa1;
background: rgba(255, 255, 255, 0.1);
text-transform: uppercase;
font-size: 0.69em;
line-height: 2.2;
}
.codrops-top a {
display: inline-block;
padding: 0 1em;
color: #fff;
text-decoration: none;
letter-spacing: 0.1em;
}
.codrops-top a:hover {
background: rgba(255, 255, 255, 0.95);
color: #333;
}
.codrops-top span.right {
float: right;
}
.codrops-top span.right a {
display: block;
float: left;
}
.codrops-icon:before {
margin: 0 4px;
text-transform: none;
font-weight: normal;
font-style: normal;
font-variant: normal;
line-height: 1;
speak: none;
-webkit-font-smoothing: antialiased;
}
.codrops-icon-drop:before {
content: "\2039";
}
.codrops-icon-prev:before {
content: "\2039";
}
/* Demo Buttons Style */
.codrops-demos {
padding-top: 1em;
font-size: 1.1em;
}
.codrops-demos a {
display: block;
float: left;
clear: both;
margin: 0.5em 0.5em 0.5em 1.9em;
padding: 1em 1.1em;
width: 280px;
outline: none;
color: #fff;
background: #336ca6;
text-align: center;
text-decoration: none;
font-weight: 700;
}
.codrops-demos a:hover,
.codrops-demos a.current-demo,
.codrops-demos a.current-demo:hover {
opacity: 0.6;
}
.content {
padding: 4em 2em;
max-width: 1200px;
margin: 0 auto;
}
.block {
float: left;
padding: 1em 3em;
}
.block-40 {
width: 40%;
}
.block-60 {
width: 60%;
}
.block p {
margin: 0;
padding: 0 1em 0.6em;
font-size: 1.8em;
line-height: 1.5;
}
.info {
text-align: center;
font-size: 1.5em;
margin-top: 3em;
clear: both;
padding-top: 3em;
color: rgba(255, 255, 255, 0.5);
}
.info a {
font-weight: 700;
font-size: 0.9em;
}
.info a:hover {
color: #336ca6;
}
@media screen and (max-width: 69em) {
.block {
float: none;
width: 100% !important;
padding: 1em;
}
}
@media screen and (max-width: 25em) {
body {
font-size: 80%;
}
.codrops-icon span {
display: none;
}
}
*,
*:after,
*::before {
box-sizing: border-box;
}
html, body, .container, .scroller {
height: 100%;
}
.scroller {
overflow-y: scroll;
}
.scroller,
.scroller-inner {
position: relative;
text-align: center;
}
.container {
position: relative;
overflow: hidden;
background: #34495e;
}
.menu-trigger {
position: relative;
padding-left: 60px;
font-size: 0.9em;
}
.menu-trigger:before {
position: absolute;
top: 2px;
left: 0;
width: 40px;
height: 6px;
background: #fff;
box-shadow: 0 6px #34495e, 0 12px #fff, 0 18px #34495e, 0 24px #fff;
content: '';
}
.mp-pusher {
position: relative;
left: 0;
height: 100%;
}
.mp-menu {
position: absolute;
/* we can't use fixed here <img src="http://www.thuthuatweb.net/wp-includes/images/smilies/icon_sad.gif" alt=":(" class="wp-smiley"> */
top: 0;
left: 0;
z-index: 1;
width: 100vw;
height: 100%;
-webkit-transform: translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0);
}
.mp-level {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #336ca6;
-webkit-transform: translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0);
}
/* overlays for pusher and for level that gets covered */
.mp-pusher::after,
.mp-level::after,
.mp-level::before {
position: absolute;
top: 0;
right: 0;
width: 0;
height: 0;
content: '';
opacity: 0;
}
.mp-pusher::after,
.mp-level::after {
background: rgba(0, 0, 0, 0.3);
-webkit-transition: opacity 0.3s, width 0.1s 0.3s, height 0.1s 0.3s;
transition: opacity 0.3s, width 0.1s 0.3s, height 0.1s 0.3s;
}
.mp-level::after {
z-index: -1;
}
.mp-pusher.mp-pushed::after,
.mp-level.mp-level-overlay::after {
width: 100%;
height: 100%;
opacity: 1;
-webkit-transition: opacity 0.3s;
transition: opacity 0.3s;
}
.mp-level.mp-level-overlay {
cursor: pointer;
}
.mp-level.mp-level-overlay.mp-level::before {
width: 100%;
height: 100%;
background: transparent;
opacity: 1;
}
.mp-pusher,
.mp-level {
-webkit-transition: all 0.5s;
transition: all 0.5s;
}
/* overlap */
.mp-overlap .mp-level.mp-level-open {
box-shadow: 1px 0 2px rgba(0, 0, 0, 0.2);
-webkit-transform: translate3d(-40px, 0, 0);
transform: translate3d(-40px, 0, 0);
}
/* First level */
.mp-menu > .mp-level,
.mp-menu > .mp-level.mp-level-open,
.mp-menu.mp-overlap > .mp-level,
.mp-menu.mp-overlap > .mp-level.mp-level-open {
box-shadow: none;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
/* cover */
.mp-cover .mp-level.mp-level-open {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
.mp-cover .mp-level.mp-level-open > ul > li > .mp-level:not(.mp-level-open) {
-webkit-transform: translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0);
}
/* content style */
.mp-menu ul {
margin: 0;
padding: 0;
list-style: none;
}
.mp-menu h2 {
margin: 0;
padding: 1em;
color: rgba(0, 0, 0, 0.4);
text-shadow: 0 0 1px rgba(0, 0, 0, 0.1);
font-weight: 300;
font-size: 2em;
}
.mp-menu.mp-overlap h2::before {
position: absolute;
top: 0;
right: 0;
margin-right: 8px;
font-size: 75%;
line-height: 1.8;
opacity: 0;
-webkit-transition: opacity 0.3s, -webkit-transform 0.1s 0.3s;
transition: opacity 0.3s, transform 0.1s 0.3s;
-webkit-transform: translateX(-100%);
-ms-transform: translateX(-100%);
transform: translateX(-100%);
}
.mp-menu.mp-cover h2 {
text-transform: uppercase;
font-weight: 700;
letter-spacing: 1px;
font-size: 1em;
}
.mp-overlap .mp-level.mp-level-overlay > h2::before {
opacity: 1;
-webkit-transition: -webkit-transform 0.3s, opacity 0.3s;
transition: transform 0.3s, opacity 0.3s;
-webkit-transform: translateX(0);
-ms-transform: translateX(0);
transform: translateX(0);
}
.mp-menu ul li > a {
display: block;
padding: 0.7em 1em 0.7em 1.8em;
outline: none;
box-shadow: inset 0 -1px rgba(0, 0, 0, 0.2);
text-shadow: 0 0 1px rgba(255, 255, 255, 0.1);
font-size: 1.4em;
-webkit-transition: background 0.3s, box-shadow 0.3s;
transition: background 0.3s, box-shadow 0.3s;
}
.mp-menu ul li::before {
position: absolute;
left: 10px;
z-index: -1;
color: rgba(255, 255, 255, 0.5);
line-height: 3.5;
}
.mp-level > ul > li:first-child > a {
box-shadow: inset 0 -1px rgba(0, 0, 0, 0.2), inset 0 1px rgba(0, 0, 0, 0.2);
}
.mp-menu ul li a:hover,
.mp-level > ul > li:first-child > a:hover {
background: rgba(0, 0, 0, 0.2);
box-shadow: inset 0 -1px transparent;
}
.mp-menu .mp-level.mp-level-overlay > ul > li > a,
.mp-level.mp-level-overlay > ul > li:first-child > a {
box-shadow: inset 0 -1px transparent;
}
.mp-level > ul > li:first-child > a:hover,
.mp-level.mp-level-overlay > ul > li:first-child > a {
box-shadow: inset 0 -1px transparent, inset 0 1px transparent;
}
/* seems like Chrome 34.0.1847.131 needs the second shadow otherwise the transition breaks */
.mp-back {
background: rgba(0, 0, 0, 0.1);
outline: none;
color: #fff;
text-transform: uppercase;
letter-spacing: 1px;
font-weight: 700;
display: block;
font-size: 0.8em;
padding: 1em;
position: relative;
box-shadow: inset 0 1px rgba(0, 0, 0, 0.1);
-webkit-transition: background 0.3s;
transition: background 0.3s;
}
.mp-back::after {
font-family: 'linecons';
position: absolute;
content: "\203A";
right: 10px;
font-size: 1.3em;
color: rgba(0, 0, 0, 0.3);
}
.mp-menu .mp-level.mp-level-overlay > .mp-back,
.mp-menu .mp-level.mp-level-overlay > .mp-back::after {
background: transparent;
box-shadow: none;
color: transparent;
}
/* Fallback example for browsers that don't support 3D transforms (and no JS fallback) */
/* We'll show the first level only */
.no-csstransforms3d .mp-pusher,
.no-js .mp-pusher {
padding-left: 100vw;
}
.no-csstransforms3d .mp-menu .mp-level,
.no-js .mp-menu .mp-level {
display: none;
}
.no-csstransforms3d .mp-menu > .mp-level,
.no-js .mp-menu > .mp-level {
display: block;
}
.icon:before {
speak: none;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
display: inline-block;
margin-right: 0.6em;
-webkit-font-smoothing: antialiased;
}
.icon-arrow-left:before {
content: "\2039";f
}
.close {
float: right;
font-size: 32px;
line-height: 18px;
}
Javascript
Cuối cùng là copy đoạn code sau để xử lý các sự kiện.
(function (window) {
'use strict';
function classReg(className) {
return new RegExp('(^|\\s+)' + className + '(\\s+|$)');
}
var hasClass, addClass, removeClass;
if ('classList' in document.documentElement) {
hasClass = function (elem, c) {
return elem.classList.contains(c);
};
addClass = function (elem, c) {
elem.classList.add(c);
};
removeClass = function (elem, c) {
elem.classList.remove(c);
};
} else {
hasClass = function (elem, c) {
return classReg(c).test(elem.className);
};
addClass = function (elem, c) {
if (!hasClass(elem, c)) {
elem.className = elem.className + ' ' + c;
}
};
removeClass = function (elem, c) {
elem.className = elem.className.replace(classReg(c), ' ');
};
}
function toggleClass(elem, c) {
var fn = hasClass(elem, c) ? removeClass : addClass;
fn(elem, c);
}
var classie = {
hasClass: hasClass,
addClass: addClass,
removeClass: removeClass,
toggleClass: toggleClass,
has: hasClass,
add: addClass,
remove: removeClass,
toggle: toggleClass
};
if (typeof define === 'function' && define.amd) {
define(classie);
} else {
window.classie = classie;
}
}(window));
;
(function (window) {
'use strict';
function extend(a, b) {
for (var key in b) {
if (b.hasOwnProperty(key)) {
a[key] = b[key];
}
}
return a;
}
function hasParent(e, id) {
if (!e)
return false;
var el = e.target || e.srcElement || e || false;
while (el && el.id != id) {
el = el.parentNode || false;
}
return el !== false;
}
function getLevelDepth(e, id, waypoint, cnt) {
cnt = cnt || 0;
if (e.id.indexOf(id) >= 0)
return cnt;
if (classie.has(e, waypoint)) {
++cnt;
}
return e.parentNode && getLevelDepth(e.parentNode, id, waypoint, cnt);
}
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 closest(e, classname) {
if (classie.has(e, classname)) {
return e;
}
return e.parentNode && closest(e.parentNode, classname);
}
function mlPushMenu(el, trigger, options) {
this.el = el;
this.trigger = trigger;
this.options = extend(this.defaults, options);
this.support = Modernizr.csstransforms3d;
if (this.support) {
this._init();
}
}
mlPushMenu.prototype = {
defaults: {
type: 'overlap',
levelSpacing: 40,
backClass: 'mp-back'
},
_init: function () {
this.open = false;
this.level = 0;
this.wrapper = document.getElementById('mp-pusher');
this.levels = Array.prototype.slice.call(this.el.querySelectorAll('div.mp-level'));
var self = this;
this.levels.forEach(function (el, i) {
el.setAttribute('data-level', getLevelDepth(el, self.el.id, 'mp-level'));
});
this.menuItems = Array.prototype.slice.call(this.el.querySelectorAll('li'));
this.levelBack = Array.prototype.slice.call(this.el.querySelectorAll('.' + this.options.backClass));
this.eventtype = mobilecheck() ? 'touchstart' : 'click';
classie.add(this.el, 'mp-' + this.options.type);
this._initEvents();
},
_initEvents: function () {
var self = this;
var bodyClickFn = function (el) {
self._resetMenu();
el.removeEventListener(self.eventtype, bodyClickFn);
};
this.trigger.addEventListener(this.eventtype, function (ev) {
ev.stopPropagation();
ev.preventDefault();
if (self.open) {
self._resetMenu();
} else {
self._openMenu();
document.addEventListener(self.eventtype, function (ev) {
if (self.open && !hasParent(ev.target, self.el.id)) {
bodyClickFn(this);
}
});
}
});
document.querySelector('.close').addEventListener('click', function (ev) {
ev.preventDefault();
bodyClickFn(this);
});
this.menuItems.forEach(function (el, i) {
var subLevel = el.querySelector('div.mp-level');
if (subLevel) {
el.querySelector('a').addEventListener(self.eventtype, function (ev) {
ev.preventDefault();
var level = closest(el, 'mp-level').getAttribute('data-level');
if (self.level <= level) {
ev.stopPropagation();
classie.add(closest(el, 'mp-level'), 'mp-level-overlay');
self._openMenu(subLevel);
}
});
}
});
this.levels.forEach(function (el, i) {
el.addEventListener(self.eventtype, function (ev) {
ev.stopPropagation();
var level = el.getAttribute('data-level');
if (self.level > level) {
self.level = level;
self._closeMenu();
}
});
});
this.levelBack.forEach(function (el, i) {
el.addEventListener(self.eventtype, function (ev) {
ev.preventDefault();
var level = closest(el, 'mp-level').getAttribute('data-level');
if (self.level <= level) {
ev.stopPropagation();
self.level = closest(el, 'mp-level').getAttribute('data-level') - 1;
self.level === 0 ? self._resetMenu() : self._closeMenu();
}
});
});
},
_openMenu: function (subLevel) {
++this.level;
var levelFactor = (this.level - 1) * this.options.levelSpacing, translateVal = this.options.type === 'overlap' ? this.el.offsetWidth + levelFactor : this.el.offsetWidth;
this._setTransform('translate3d(' + translateVal + 'px,0,0)');
if (subLevel) {
this._setTransform('', subLevel);
for (var i = 0, len = this.levels.length; i < len; ++i) {
var levelEl = this.levels[i];
if (levelEl != subLevel && !classie.has(levelEl, 'mp-level-open')) {
this._setTransform('translate3d(-100%,0,0) translate3d(' + -1 * levelFactor + 'px,0,0)', levelEl);
}
}
}
if (this.level === 1) {
classie.add(this.wrapper, 'mp-pushed');
this.open = true;
}
classie.add(subLevel || this.levels[0], 'mp-level-open');
},
_resetMenu: function () {
this._setTransform('translate3d(0,0,0)');
this.level = 0;
classie.remove(this.wrapper, 'mp-pushed');
this._toggleLevels();
this.open = false;
},
_closeMenu: function () {
var translateVal = this.options.type === 'overlap' ? this.el.offsetWidth + (this.level - 1) * this.options.levelSpacing : this.el.offsetWidth;
this._setTransform('translate3d(' + translateVal + 'px,0,0)');
this._toggleLevels();
},
_setTransform: function (val, el) {
el = el || this.wrapper;
el.style.WebkitTransform = val;
el.style.MozTransform = val;
el.style.transform = val;
},
_toggleLevels: function () {
for (var i = 0, len = this.levels.length; i < len; ++i) {
var levelEl = this.levels[i];
if (levelEl.getAttribute('data-level') >= this.level + 1) {
classie.remove(levelEl, 'mp-level-open');
classie.remove(levelEl, 'mp-level-overlay');
} else if (Number(levelEl.getAttribute('data-level')) == this.level) {
classie.remove(levelEl, 'mp-level-overlay');
}
}
}
};
window.mlPushMenu = mlPushMenu;
}(window));
new mlPushMenu(document.getElementById('mp-menu'), document.getElementById('trigger'), { type: 'cover' });
//@ sourceURL=pen.js
Các bạn nhớ chèn thêm thư viện Modernizr vào trước đoạn script.
<script src="https://5b21f984adb49aaa6e26cc5af1b28eda3f4cf198.googledrive.com/host/0B2l0BaezKpPXdUFRdV9mLXU5djg"></script>
HTML
Đầu tiên, các bạn tạo menu theo khung chuẩn html như sau :
<div class="container">
<div class="mp-pusher" id="mp-pusher">
<!-- mp-menu -->
<nav id="mp-menu" class="mp-menu">
<div class="mp-level">
<h2 class="icon icon-world">All Categories <a href="#" class="close">×</a></h2>
<ul>
<li class="icon icon-arrow-left">
<a class="icon icon-display" href="#">Devices</a>
<div class="mp-level">
<h2 class="icon icon-display">Devices</h2>
<a class="mp-back" href="#">back</a>
<ul>
<li class="icon icon-arrow-left">
<a class="icon icon-phone" href="#">Mobile Phones</a>
<div class="mp-level">
<h2>Mobile Phones</h2>
<a class="mp-back" href="#">back</a>
<ul>
<li><a href="#">Super Smart Phone</a></li>
<li><a href="#">Thin Magic Mobile</a></li>
<li><a href="#">Performance Crusher</a></li>
<li><a href="#">Futuristic Experience</a></li>
</ul>
</div>
</li>
<li class="icon icon-arrow-left">
<a class="icon icon-tv" href="#">Televisions</a>
<div class="mp-level">
<h2>Televisions</h2>
<a class="mp-back" href="#">back</a>
<ul>
<li><a href="#">Flat Superscreen</a></li>
<li><a href="#">Gigantic LED</a></li>
<li><a href="#">Power Eater</a></li>
<li><a href="#">3D Experience</a></li>
<li><a href="#">Classic Comfort</a></li>
</ul>
</div>
</li>
<li class="icon icon-arrow-left">
<a class="icon icon-camera" href="#">Cameras</a>
<div class="mp-level">
<h2>Cameras</h2>
<a class="mp-back" href="#">back</a>
<ul>
<li><a href="#">Smart Shot</a></li>
<li><a href="#">Power Shooter</a></li>
<li><a href="#">Easy Photo Maker</a></li>
<li><a href="#">Super Pixel</a></li>
</ul>
</div>
</li>
</ul>
</div>
</li>
<li class="icon icon-arrow-left">
<a class="icon icon-news" href="#">Magazines</a>
<div class="mp-level">
<h2 class="icon icon-news">Magazines</h2>
<a class="mp-back" href="#">back</a>
<ul>
<li><a href="#">National Geographic</a></li>
<li><a href="#">Scientific American</a></li>
<li><a href="#">The Spectator</a></li>
<li><a href="#">The Rambler</a></li>
<li><a href="#">Physics World</a></li>
<li><a href="#">The New Scientist</a></li>
</ul>
</div>
</li>
<li class="icon icon-arrow-left">
<a class="icon icon-shop" href="#">Store</a>
<div class="mp-level">
<h2 class="icon icon-shop">Store</h2>
<a class="mp-back" href="#">back</a>
<ul>
<li class="icon icon-arrow-left">
<a class="icon icon-t-shirt" href="#">Clothes</a>
<div class="mp-level">
<h2 class="icon icon-t-shirt">Clothes</h2>
<a class="mp-back" href="#">back</a>
<ul>
<li class="icon icon-arrow-left">
<a class="icon icon-female" href="#">Women's Clothing</a>
<div class="mp-level">
<h2 class="icon icon-female">Women's Clothing</h2>
<a class="mp-back" href="#">back</a>
<ul>
<li><a href="#">Tops</a></li>
<li><a href="#">Dresses</a></li>
<li><a href="#">Trousers</a></li>
<li><a href="#">Shoes</a></li>
<li><a href="#">Sale</a></li>
</ul>
</div>
</li>
<li class="icon icon-arrow-left">
<a class="icon icon-male" href="#">Men's Clothing</a>
<div class="mp-level">
<h2 class="icon icon-male">Men's Clothing</h2>
<a class="mp-back" href="#">back</a>
<ul>
<li><a href="#">Shirts</a></li>
<li><a href="#">Trousers</a></li>
<li><a href="#">Shoes</a></li>
<li><a href="#">Sale</a></li>
</ul>
</div>
</li>
</ul>
</div>
</li>
<li>
<a class="icon icon-diamond" href="#">Jewelry</a>
</li>
<li>
<a class="icon icon-music" href="#">Music</a>
</li>
<li>
<a class="icon icon-food" href="#">Grocery</a>
</li>
</ul>
</div>
</li>
<li><a class="icon icon-photo" href="#">Collections</a></li>
<li><a class="icon icon-wallet" href="#">Credits</a></li>
</ul>
</div>
</nav>
<!-- /mp-menu -->
<div class="scroller"><!-- this is for emulating position fixed of the nav -->
<div class="scroller-inner">
<h1><a href="#" id="trigger" class="menu-trigger">Open/Close Menu</a></h1>
</div>
</div>
</div>
</div>
CSS
Sau đó các bạn định dạng menu với đoạn css sau :
.clearfix:before,
.clearfix:after {
display: table;
content: " ";
}
.clearfix:after {
clear: both;
}
.codrops-header,
.codrops-top {
font-family: 'Lato', Arial, sans-serif;
}
.codrops-header {
margin: 0 auto;
padding: 2em;
background: rgba(0, 0, 0, 0.01);
text-align: center;
}
.codrops-header h1 {
margin: 0;
font-weight: 300;
font-size: 2.625em;
line-height: 1.3;
}
.codrops-header span {
display: block;
padding: 0 0 0.6em 0.1em;
font-size: 60%;
opacity: 0.7;
}
/* To Navigation Style */
.codrops-top {
width: 100%;
background: #91cfa1;
background: rgba(255, 255, 255, 0.1);
text-transform: uppercase;
font-size: 0.69em;
line-height: 2.2;
}
.codrops-top a {
display: inline-block;
padding: 0 1em;
color: #fff;
text-decoration: none;
letter-spacing: 0.1em;
}
.codrops-top a:hover {
background: rgba(255, 255, 255, 0.95);
color: #333;
}
.codrops-top span.right {
float: right;
}
.codrops-top span.right a {
display: block;
float: left;
}
.codrops-icon:before {
margin: 0 4px;
text-transform: none;
font-weight: normal;
font-style: normal;
font-variant: normal;
line-height: 1;
speak: none;
-webkit-font-smoothing: antialiased;
}
.codrops-icon-drop:before {
content: "\2039";
}
.codrops-icon-prev:before {
content: "\2039";
}
/* Demo Buttons Style */
.codrops-demos {
padding-top: 1em;
font-size: 1.1em;
}
.codrops-demos a {
display: block;
float: left;
clear: both;
margin: 0.5em 0.5em 0.5em 1.9em;
padding: 1em 1.1em;
width: 280px;
outline: none;
color: #fff;
background: #336ca6;
text-align: center;
text-decoration: none;
font-weight: 700;
}
.codrops-demos a:hover,
.codrops-demos a.current-demo,
.codrops-demos a.current-demo:hover {
opacity: 0.6;
}
.content {
padding: 4em 2em;
max-width: 1200px;
margin: 0 auto;
}
.block {
float: left;
padding: 1em 3em;
}
.block-40 {
width: 40%;
}
.block-60 {
width: 60%;
}
.block p {
margin: 0;
padding: 0 1em 0.6em;
font-size: 1.8em;
line-height: 1.5;
}
.info {
text-align: center;
font-size: 1.5em;
margin-top: 3em;
clear: both;
padding-top: 3em;
color: rgba(255, 255, 255, 0.5);
}
.info a {
font-weight: 700;
font-size: 0.9em;
}
.info a:hover {
color: #336ca6;
}
@media screen and (max-width: 69em) {
.block {
float: none;
width: 100% !important;
padding: 1em;
}
}
@media screen and (max-width: 25em) {
body {
font-size: 80%;
}
.codrops-icon span {
display: none;
}
}
*,
*:after,
*::before {
box-sizing: border-box;
}
html, body, .container, .scroller {
height: 100%;
}
.scroller {
overflow-y: scroll;
}
.scroller,
.scroller-inner {
position: relative;
text-align: center;
}
.container {
position: relative;
overflow: hidden;
background: #34495e;
}
.menu-trigger {
position: relative;
padding-left: 60px;
font-size: 0.9em;
}
.menu-trigger:before {
position: absolute;
top: 2px;
left: 0;
width: 40px;
height: 6px;
background: #fff;
box-shadow: 0 6px #34495e, 0 12px #fff, 0 18px #34495e, 0 24px #fff;
content: '';
}
.mp-pusher {
position: relative;
left: 0;
height: 100%;
}
.mp-menu {
position: absolute;
/* we can't use fixed here <img src="http://www.thuthuatweb.net/wp-includes/images/smilies/icon_sad.gif" alt=":(" class="wp-smiley"> */
top: 0;
left: 0;
z-index: 1;
width: 100vw;
height: 100%;
-webkit-transform: translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0);
}
.mp-level {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #336ca6;
-webkit-transform: translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0);
}
/* overlays for pusher and for level that gets covered */
.mp-pusher::after,
.mp-level::after,
.mp-level::before {
position: absolute;
top: 0;
right: 0;
width: 0;
height: 0;
content: '';
opacity: 0;
}
.mp-pusher::after,
.mp-level::after {
background: rgba(0, 0, 0, 0.3);
-webkit-transition: opacity 0.3s, width 0.1s 0.3s, height 0.1s 0.3s;
transition: opacity 0.3s, width 0.1s 0.3s, height 0.1s 0.3s;
}
.mp-level::after {
z-index: -1;
}
.mp-pusher.mp-pushed::after,
.mp-level.mp-level-overlay::after {
width: 100%;
height: 100%;
opacity: 1;
-webkit-transition: opacity 0.3s;
transition: opacity 0.3s;
}
.mp-level.mp-level-overlay {
cursor: pointer;
}
.mp-level.mp-level-overlay.mp-level::before {
width: 100%;
height: 100%;
background: transparent;
opacity: 1;
}
.mp-pusher,
.mp-level {
-webkit-transition: all 0.5s;
transition: all 0.5s;
}
/* overlap */
.mp-overlap .mp-level.mp-level-open {
box-shadow: 1px 0 2px rgba(0, 0, 0, 0.2);
-webkit-transform: translate3d(-40px, 0, 0);
transform: translate3d(-40px, 0, 0);
}
/* First level */
.mp-menu > .mp-level,
.mp-menu > .mp-level.mp-level-open,
.mp-menu.mp-overlap > .mp-level,
.mp-menu.mp-overlap > .mp-level.mp-level-open {
box-shadow: none;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
/* cover */
.mp-cover .mp-level.mp-level-open {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
.mp-cover .mp-level.mp-level-open > ul > li > .mp-level:not(.mp-level-open) {
-webkit-transform: translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0);
}
/* content style */
.mp-menu ul {
margin: 0;
padding: 0;
list-style: none;
}
.mp-menu h2 {
margin: 0;
padding: 1em;
color: rgba(0, 0, 0, 0.4);
text-shadow: 0 0 1px rgba(0, 0, 0, 0.1);
font-weight: 300;
font-size: 2em;
}
.mp-menu.mp-overlap h2::before {
position: absolute;
top: 0;
right: 0;
margin-right: 8px;
font-size: 75%;
line-height: 1.8;
opacity: 0;
-webkit-transition: opacity 0.3s, -webkit-transform 0.1s 0.3s;
transition: opacity 0.3s, transform 0.1s 0.3s;
-webkit-transform: translateX(-100%);
-ms-transform: translateX(-100%);
transform: translateX(-100%);
}
.mp-menu.mp-cover h2 {
text-transform: uppercase;
font-weight: 700;
letter-spacing: 1px;
font-size: 1em;
}
.mp-overlap .mp-level.mp-level-overlay > h2::before {
opacity: 1;
-webkit-transition: -webkit-transform 0.3s, opacity 0.3s;
transition: transform 0.3s, opacity 0.3s;
-webkit-transform: translateX(0);
-ms-transform: translateX(0);
transform: translateX(0);
}
.mp-menu ul li > a {
display: block;
padding: 0.7em 1em 0.7em 1.8em;
outline: none;
box-shadow: inset 0 -1px rgba(0, 0, 0, 0.2);
text-shadow: 0 0 1px rgba(255, 255, 255, 0.1);
font-size: 1.4em;
-webkit-transition: background 0.3s, box-shadow 0.3s;
transition: background 0.3s, box-shadow 0.3s;
}
.mp-menu ul li::before {
position: absolute;
left: 10px;
z-index: -1;
color: rgba(255, 255, 255, 0.5);
line-height: 3.5;
}
.mp-level > ul > li:first-child > a {
box-shadow: inset 0 -1px rgba(0, 0, 0, 0.2), inset 0 1px rgba(0, 0, 0, 0.2);
}
.mp-menu ul li a:hover,
.mp-level > ul > li:first-child > a:hover {
background: rgba(0, 0, 0, 0.2);
box-shadow: inset 0 -1px transparent;
}
.mp-menu .mp-level.mp-level-overlay > ul > li > a,
.mp-level.mp-level-overlay > ul > li:first-child > a {
box-shadow: inset 0 -1px transparent;
}
.mp-level > ul > li:first-child > a:hover,
.mp-level.mp-level-overlay > ul > li:first-child > a {
box-shadow: inset 0 -1px transparent, inset 0 1px transparent;
}
/* seems like Chrome 34.0.1847.131 needs the second shadow otherwise the transition breaks */
.mp-back {
background: rgba(0, 0, 0, 0.1);
outline: none;
color: #fff;
text-transform: uppercase;
letter-spacing: 1px;
font-weight: 700;
display: block;
font-size: 0.8em;
padding: 1em;
position: relative;
box-shadow: inset 0 1px rgba(0, 0, 0, 0.1);
-webkit-transition: background 0.3s;
transition: background 0.3s;
}
.mp-back::after {
font-family: 'linecons';
position: absolute;
content: "\203A";
right: 10px;
font-size: 1.3em;
color: rgba(0, 0, 0, 0.3);
}
.mp-menu .mp-level.mp-level-overlay > .mp-back,
.mp-menu .mp-level.mp-level-overlay > .mp-back::after {
background: transparent;
box-shadow: none;
color: transparent;
}
/* Fallback example for browsers that don't support 3D transforms (and no JS fallback) */
/* We'll show the first level only */
.no-csstransforms3d .mp-pusher,
.no-js .mp-pusher {
padding-left: 100vw;
}
.no-csstransforms3d .mp-menu .mp-level,
.no-js .mp-menu .mp-level {
display: none;
}
.no-csstransforms3d .mp-menu > .mp-level,
.no-js .mp-menu > .mp-level {
display: block;
}
.icon:before {
speak: none;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
display: inline-block;
margin-right: 0.6em;
-webkit-font-smoothing: antialiased;
}
.icon-arrow-left:before {
content: "\2039";f
}
.close {
float: right;
font-size: 32px;
line-height: 18px;
}
Javascript
Cuối cùng là copy đoạn code sau để xử lý các sự kiện.
(function (window) {
'use strict';
function classReg(className) {
return new RegExp('(^|\\s+)' + className + '(\\s+|$)');
}
var hasClass, addClass, removeClass;
if ('classList' in document.documentElement) {
hasClass = function (elem, c) {
return elem.classList.contains(c);
};
addClass = function (elem, c) {
elem.classList.add(c);
};
removeClass = function (elem, c) {
elem.classList.remove(c);
};
} else {
hasClass = function (elem, c) {
return classReg(c).test(elem.className);
};
addClass = function (elem, c) {
if (!hasClass(elem, c)) {
elem.className = elem.className + ' ' + c;
}
};
removeClass = function (elem, c) {
elem.className = elem.className.replace(classReg(c), ' ');
};
}
function toggleClass(elem, c) {
var fn = hasClass(elem, c) ? removeClass : addClass;
fn(elem, c);
}
var classie = {
hasClass: hasClass,
addClass: addClass,
removeClass: removeClass,
toggleClass: toggleClass,
has: hasClass,
add: addClass,
remove: removeClass,
toggle: toggleClass
};
if (typeof define === 'function' && define.amd) {
define(classie);
} else {
window.classie = classie;
}
}(window));
;
(function (window) {
'use strict';
function extend(a, b) {
for (var key in b) {
if (b.hasOwnProperty(key)) {
a[key] = b[key];
}
}
return a;
}
function hasParent(e, id) {
if (!e)
return false;
var el = e.target || e.srcElement || e || false;
while (el && el.id != id) {
el = el.parentNode || false;
}
return el !== false;
}
function getLevelDepth(e, id, waypoint, cnt) {
cnt = cnt || 0;
if (e.id.indexOf(id) >= 0)
return cnt;
if (classie.has(e, waypoint)) {
++cnt;
}
return e.parentNode && getLevelDepth(e.parentNode, id, waypoint, cnt);
}
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 closest(e, classname) {
if (classie.has(e, classname)) {
return e;
}
return e.parentNode && closest(e.parentNode, classname);
}
function mlPushMenu(el, trigger, options) {
this.el = el;
this.trigger = trigger;
this.options = extend(this.defaults, options);
this.support = Modernizr.csstransforms3d;
if (this.support) {
this._init();
}
}
mlPushMenu.prototype = {
defaults: {
type: 'overlap',
levelSpacing: 40,
backClass: 'mp-back'
},
_init: function () {
this.open = false;
this.level = 0;
this.wrapper = document.getElementById('mp-pusher');
this.levels = Array.prototype.slice.call(this.el.querySelectorAll('div.mp-level'));
var self = this;
this.levels.forEach(function (el, i) {
el.setAttribute('data-level', getLevelDepth(el, self.el.id, 'mp-level'));
});
this.menuItems = Array.prototype.slice.call(this.el.querySelectorAll('li'));
this.levelBack = Array.prototype.slice.call(this.el.querySelectorAll('.' + this.options.backClass));
this.eventtype = mobilecheck() ? 'touchstart' : 'click';
classie.add(this.el, 'mp-' + this.options.type);
this._initEvents();
},
_initEvents: function () {
var self = this;
var bodyClickFn = function (el) {
self._resetMenu();
el.removeEventListener(self.eventtype, bodyClickFn);
};
this.trigger.addEventListener(this.eventtype, function (ev) {
ev.stopPropagation();
ev.preventDefault();
if (self.open) {
self._resetMenu();
} else {
self._openMenu();
document.addEventListener(self.eventtype, function (ev) {
if (self.open && !hasParent(ev.target, self.el.id)) {
bodyClickFn(this);
}
});
}
});
document.querySelector('.close').addEventListener('click', function (ev) {
ev.preventDefault();
bodyClickFn(this);
});
this.menuItems.forEach(function (el, i) {
var subLevel = el.querySelector('div.mp-level');
if (subLevel) {
el.querySelector('a').addEventListener(self.eventtype, function (ev) {
ev.preventDefault();
var level = closest(el, 'mp-level').getAttribute('data-level');
if (self.level <= level) {
ev.stopPropagation();
classie.add(closest(el, 'mp-level'), 'mp-level-overlay');
self._openMenu(subLevel);
}
});
}
});
this.levels.forEach(function (el, i) {
el.addEventListener(self.eventtype, function (ev) {
ev.stopPropagation();
var level = el.getAttribute('data-level');
if (self.level > level) {
self.level = level;
self._closeMenu();
}
});
});
this.levelBack.forEach(function (el, i) {
el.addEventListener(self.eventtype, function (ev) {
ev.preventDefault();
var level = closest(el, 'mp-level').getAttribute('data-level');
if (self.level <= level) {
ev.stopPropagation();
self.level = closest(el, 'mp-level').getAttribute('data-level') - 1;
self.level === 0 ? self._resetMenu() : self._closeMenu();
}
});
});
},
_openMenu: function (subLevel) {
++this.level;
var levelFactor = (this.level - 1) * this.options.levelSpacing, translateVal = this.options.type === 'overlap' ? this.el.offsetWidth + levelFactor : this.el.offsetWidth;
this._setTransform('translate3d(' + translateVal + 'px,0,0)');
if (subLevel) {
this._setTransform('', subLevel);
for (var i = 0, len = this.levels.length; i < len; ++i) {
var levelEl = this.levels[i];
if (levelEl != subLevel && !classie.has(levelEl, 'mp-level-open')) {
this._setTransform('translate3d(-100%,0,0) translate3d(' + -1 * levelFactor + 'px,0,0)', levelEl);
}
}
}
if (this.level === 1) {
classie.add(this.wrapper, 'mp-pushed');
this.open = true;
}
classie.add(subLevel || this.levels[0], 'mp-level-open');
},
_resetMenu: function () {
this._setTransform('translate3d(0,0,0)');
this.level = 0;
classie.remove(this.wrapper, 'mp-pushed');
this._toggleLevels();
this.open = false;
},
_closeMenu: function () {
var translateVal = this.options.type === 'overlap' ? this.el.offsetWidth + (this.level - 1) * this.options.levelSpacing : this.el.offsetWidth;
this._setTransform('translate3d(' + translateVal + 'px,0,0)');
this._toggleLevels();
},
_setTransform: function (val, el) {
el = el || this.wrapper;
el.style.WebkitTransform = val;
el.style.MozTransform = val;
el.style.transform = val;
},
_toggleLevels: function () {
for (var i = 0, len = this.levels.length; i < len; ++i) {
var levelEl = this.levels[i];
if (levelEl.getAttribute('data-level') >= this.level + 1) {
classie.remove(levelEl, 'mp-level-open');
classie.remove(levelEl, 'mp-level-overlay');
} else if (Number(levelEl.getAttribute('data-level')) == this.level) {
classie.remove(levelEl, 'mp-level-overlay');
}
}
}
};
window.mlPushMenu = mlPushMenu;
}(window));
new mlPushMenu(document.getElementById('mp-menu'), document.getElementById('trigger'), { type: 'cover' });
//@ sourceURL=pen.js
Các bạn nhớ chèn thêm thư viện Modernizr vào trước đoạn script.
<script src="https://5b21f984adb49aaa6e26cc5af1b28eda3f4cf198.googledrive.com/host/0B2l0BaezKpPXdUFRdV9mLXU5djg"></script>
Sử dụng CSS3 và Javasript tạo Menu cho Mobile
Reviewed by Unknown
on
05:30
Rating:
Không có nhận xét nào: