<div id="drawer">
<div class="button">
<div class="line"></div>
<div class="line"></div>
<div class="line"></div>
</div>
<div class="close-area"></div>
</div>
<div id="drawer-menu">
メニュー
</div>
#drawer .button {
padding: 7px;
position: fixed;
display: box;
display: flexbox;
display: flex;
box-shadow: 2px 2px 4px #444;
box-shadow: 2px 2px 4px #444;
width: 32px;
height: 32px;
box-pack: justify;
flex-pack: justify;
justify-content: space-between;
box-orient: vertical;
box-direction: normal;
flex-direction: column;
flex-direction: column;
top: 10px;
left: 23px;
z-index: 1;
color: #fff;
background-color: #999;
cursor: pointer;
}
#drawer .button:hover {
background-color: #ddd;
}
#drawer .button .line {
height: 4px;
background-color: #fff;
}
#drawer .button:hover .line {
background-color: #666;
}
#drawer .close-area {
position: fixed;
width: 100vw;
height: 100vh;
top: 0;
left: 0;
opacity: 0;
visibility: hidden;
transition: opacity .2s,visibility .2s;
transition: opacity .2s,visibility .2s;
z-index: 2;
}
#drawer .close-area.active {
visibility: visible;
opacity: .5;
background-color: #363b3f;
}
#drawer-menu {
position: fixed;
left: -100%;
min-width: 280px;
height: 100vh;
background-color: #fefefe;
transition: left .3s ease-in;
z-index: 3;
}
#drawer-menu.active {
left: 0;
transition: right .5s cubic-bezier(0,.8,.6,1);
transition: left .5s cubic-bezier(0,.8,.6,1);
}
function DrawerEventRegisterer() {
let _isOpening = false;
function _register() {
const BUTTON = document.querySelector( '#drawer .button' );
if ( BUTTON === null ) return;
const CLOSE_AREA = document.querySelector( '#drawer .close-area' );
if ( CLOSE_AREA === null ) return;
const MENU = document.getElementById( 'drawer-menu' );
if ( MENU === null ) return;
const ACTIVE_CLASS_NAME = 'active';
const onOpen = function() {
_isOpening = true;
BUTTON .addClass( ACTIVE_CLASS_NAME );
CLOSE_AREA .addClass( ACTIVE_CLASS_NAME );
MENU .addClass( ACTIVE_CLASS_NAME );
};
const onClose = function() {
_isOpening = false;
BUTTON .removeClass( ACTIVE_CLASS_NAME );
CLOSE_AREA .removeClass( ACTIVE_CLASS_NAME );
MENU .removeClass( ACTIVE_CLASS_NAME );
};
_registerPushedEvents( BUTTON, CLOSE_AREA, onOpen, onClose );
_registerResizedEvent( BUTTON, onClose );
}
function _registerPushedEvents( button, closeArea, onOpen, onClose ) {
const onPushedButton = function() { if ( !_isOpening ) onOpen(); };
const onPushedCloseArea = function() { if ( _isOpening ) onClose(); };
button .registerOnPushed( onPushedButton );
closeArea .registerOnPushed( onPushedCloseArea );
}
function _registerResizedEvent( button, onCompleted ) {
const onResized = function() {
if ( !_isOpening ) return;
const DISPLAY = button.getStylesheetValue( 'display' );
if ( DISPLAY !== 'none' ) return;
onCompleted();
};
window.registerOnResized( onResized );
}
return {
register: _register,
};
};
Element.prototype.addClass = function( name ) {
this.classList.add( name );
};
Element.prototype.removeClass = function( name ) {
this.classList.remove( name );
};
Element.prototype.getStylesheetValue = function( propertyName ) {
const STYLE = window.getComputedStyle( this );
const VALUE = STYLE .getPropertyValue( propertyName );
return VALUE;
};
Element.prototype.registerOnPushed = function( onPushed ) {
if ( isSmartPhoneOrTablet() ) {
let isTouching = false;
const OPTION = canUsePassive() ? { passive: true } : false;
const onTouched = function() {
if ( !isTouching ) return;
onPushed();
isTouching = false;
};
this.addEventListener( 'touchstart' , function() { isTouching = true; }, OPTION );
this.addEventListener( 'touchmove' , function() { isTouching = false; }, OPTION );
this.addEventListener( 'touchend' , onTouched , OPTION );
}
else {
this.addEventListener( 'click', onPushed );
}
};
function isSmartPhoneOrTablet() {
const isContaining = function( search ) {
return navigator.userAgent.indexOf( search ) !== -1;
};
const IS_SMART_PHONE_OR_TABLET =
isContaining( 'iPhone' ) ||
isContaining( 'iPod' ) ||
isContaining( 'Android' ) ||
isContaining( 'iPad' )
;
return IS_SMART_PHONE_OR_TABLET;
}
function canUsePassive() {
let canUsePassive = false;
const PROPERTY = { get: function() { canUsePassive = true; } };
const OPTIONS = Object.defineProperty( {}, 'passive', PROPERTY );
window.addEventListener( 'dummy', null, OPTIONS );
return canUsePassive;
}
Window.prototype.registerOnResized = function( onResized ) {
const INTERVAL = 300;
const observingEvent = createObservingEvent( INTERVAL, null, null, onResized );
window.addEventListener( 'resize', observingEvent );
};
function createObservingEvent( interval, onStarted, onExecuting, onEnded ) {
let intervalID = null;
let isExecuting = false;
const onElapsed = function() {
if ( !isExecuting ) {
clearInterval( intervalID );
intervalID = null;
if ( onEnded !== null ) onEnded();
return;
}
if ( onExecuting !== null ) onExecuting();
isExecuting = false;
};
const onExecute = function() {
isExecuting = true;
if ( intervalID !== null ) return;
if ( onStarted !== null ) onStarted();
intervalID = setInterval( onElapsed, interval );
};
return onExecute;
};
const DRAWER_EVENT_REGISTERER = new DrawerEventRegisterer;
DRAWER_EVENT_REGISTERER.register();
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.