メニューサンプル-DEMO
See the Pen Menu-1 by YugetaKoji (@geta1972) on CodePen.
機能説明
ホームページの上部に固定するタイプのヘッダメニューで、URLでリンクのものと、プルダウンメニューの混在するものです。 機能が階層化されているようなWEBシステムなどのヘッダで利用すると便利に使えますね。 プルダウンするメニューには、▼マークをつけて階層が有ることを表し、改装メニューの表示。非表示は、若干のcssアニメーションをつけて存在感を表しています。 クリック判定でdata-view属性を切り替えることで設置されているcssでの表示処理やアニメーション処理を行っています。 また、サブメニューを表示している状態で、画面のそれ以外の場所をクリックした場合に、サブメニューを閉じるという処理を追加しています。ソースコード
<html lang="en">
<head>
<meta charset="utf-8">
<title>HTML-parts Header</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="menu.css">
<script src="menu.js"></script>
</head>
<body>
<div class="menu-bar">
<ul>
<li>
<a href="javascript:void(0)">Menu-1</a>
<ul>
<li><a href="#menu-1-1">Menu-1-1</a></li>
<li><a href="#menu-1-2">Menu-1-2</a></li>
</ul>
</li>
<li>
<a href="#menu-2">Menu-2</a>
</li>
</ul>
<ul>
<li>
<a href="javascript:void(0)">Menu-3</a>
<ul>
<li><a href="#menu-3-1">Menu-3-1</a></li>
<li><a href="javascript:void(0)">Menu-3-2</a></li>
</ul>
</li>
</ul>
</div>
</body>
</html>
html,body{
margin : 0;
padding : 0;
border : 0;
width : 100%;
height : 100%;
}
*, *:before, *:after {
-webkit-box-sizing : border-box;
-moz-box-sizing : border-box;
-o-box-sizing : border-box;
-ms-box-sizing : border-box;
box-sizing : border-box;
}
.menu-bar{
height : 60px;
border-bottom : 1px solid #AAA;
line-height : 60px;
display : -webkit-flex;
display : flex;
-webkit-justify-content : center;
justify-content : center;
-webkit-align-items : center;
align-items : center;
}
/* basic */
.menu-bar ul{
margin : 0;
padding : 0;
border : 0;
}
.menu-bar ul li{
margin : 0;
padding : 0;
border : 0;
list-style : none;
}
.menu-bar ul li a{
display : inline-block;
height : 100%;
padding : 0 8px;
cursor : pointer;
text-decoration : none;
}
/* .menu-bar ul li a:hover{
opacity : 0.5;
} */
/* top-menu */
.menu-bar > ul{
display : flex;
height : 100%;
min-width : 100px;
}
.menu-bar > ul > li{
position : relative;
}
.menu-bar > ul > li > a{
min-width : 100px;
text-align:center;
}
.menu-bar > ul > li > a:hover{
background-color:#eee;
}
.menu-bar > ul > li > a[data-active="1"]{
background-color:#ccc;
}
.menu-bar > ul > li > a[data-active="0"]{
animation: menu-noactive 0.3s linear forwards;
}
.menu-bar > ul > li.dropdown > a:after,
.menu-bar > ul > li[data-dropdown="1"] > a:after{
content: "";
display: inline-block;
width: 0;
height: 0;
vertical-align: middle;
border-top: 6px dashed;
border-right: 4px solid transparent;
border-left: 4px solid transparent;
box-sizing: border-box;
margin-left:4px;
}
/* second-menu */
.menu-bar > ul > li > ul{
position : absolute;
left : 0;
line-height : 30px;
border:1px solid #aaa;
border-width:1px 1px 0;
box-shadow : 2px 2px 8px rgba(0,0,0,0.4);
opacity : 0.0;
visibility : hidden;
}
.menu-bar > ul > li > ul[data-view="1"]{
visibility : visible;
opacity : 1.0;
}
.menu-bar > ul > li > ul[data-view="0"]{
animation: menu-close 0.3s linear forwards;
}
.menu-bar > ul > li > ul[data-view="0"] > li{
animation: menu-list-close 0.1s linear forwards;
}
.menu-bar > ul > li > ul[data-view="1"] > li{
animation: menu-list-open 0.1s linear forwards;
}
.menu-bar > ul > li > ul > li{
border-bottom : 1px solid #aaa;
overflow:hidden;
}
.menu-bar > ul > li > ul > li > a{
min-width : 120px;
text-align:center;
}
.menu-bar > ul > li > ul > li > a:hover{
background-color : #eee;
}
@keyframes menu-noactive{
0%{
background-color:#ccc;
}
100%{
background-color:rgba(255,255,255,0.0);
}
}
@keyframes menu-close{
0%{
opacity:1.0;
visibility:visible;
}
100%{
opacity:0.0;
visibility:hidden;
}
}
@keyframes menu-list-open{
0%{
height:0px;
}
100%{
height:30px;
}
}
@keyframes menu-list-close{
0%{
height:30px;
}
100%{
height:0px;
}
}
;(function(){
// ページ内にjsライブラリの読み込み
var $$addScript = function(file){
var s = document.createElement("script");
s.src = file;
document.body.appendChild(s);
}
// イベントライブラリ
var $$event = function(target, mode, func){
//other Browser
if (typeof target.addEventListener !== "undefined"){
target.addEventListener(mode, func, false);
}
else if(typeof target.attachEvent !== "undefined"){
target.attachEvent('on' + mode, function(){func.call(target , window.event)});
}
};
var $$ = function(){
var state = document.readyState;
if(state === "complete"){
this.start();
}
else if(state === "interactive"){
$$event(window , "DOMContentLoaded" , (function(e){this.start(e)}).bind(this));
}
else{
$$event(window , "load" , (function(e){this.start(e)}).bind(this));
}
};
$$.prototype.start = function(){
// top-menu
var top_menus = document.querySelectorAll(".menu-bar > ul > li > a");
for(var i=0; i<top_menus.length; i++){
$$event(top_menus[i] , "click" , (function(e){this.set_top_menu_toggle(e)}).bind(this));
}
// dropdown-set
this.set_dropdown();
// other-click
$$event(window , "click" , (function(e){this.checkClick(e)}).bind(this));
};
$$.prototype.set_top_menu_toggle = function(e){
var target = e.currentTarget;
var top_menus = document.querySelectorAll(".menu-bar > ul > li > a");
for(var i=0; i<top_menus.length; i++){
var dropdown = top_menus[i].parentNode.querySelector(":scope > ul");
// data-view
if(dropdown && top_menus[i] === target && dropdown.getAttribute("data-view") !== "1"){
dropdown.setAttribute("data-view" , "1");
top_menus[i].setAttribute("data-active" , "1");
}
else{
if(dropdown && dropdown.getAttribute("data-view") === "1"){
dropdown.setAttribute("data-view" , "0");
}
if(top_menus[i].getAttribute("data-active") === "1"){
top_menus[i].setAttribute("data-active" , "0");
}
}
}
};
$$.prototype.checkClick = function(e){
var target = e.target;
// console.log(target);
if(!target || !target.matches(".menu-bar > ul > li > a")){
this.set_top_menu_toggle({currentTarget:null});
}
};
$$.prototype.set_dropdown = function(){
var top_menus = document.querySelectorAll(".menu-bar > ul > li > ul");
for(var i=0; i<top_menus.length; i++){
top_menus[i].parentNode.setAttribute("data-dropdown" , "1");
}
};
new $$;
})();
解説
HTMLはclass="menu-bar"というヘッダの親要素に対して、それ以下のタグはシンプルな状態で設置できるようにしています。
見てもらうとわかりますが、LIの中にULが存在していると階層ありという処理をして、JSがページ読み込み時に属性フラグを設置してます。
CSSでの注意点は、コピペで利用する時に、ソース上部にある2つの基本コードは省いたほうがコンフリクトしなくなります。
※今回はデモ用でつけているだけです。
改良ポイント
このツールのデメリットはJS処理をしているのですが、CSSのみでこうした処理ができる仕組みであれば、サイトのスペック向上をすることが可能になります。
CSSだけ版というものを次回以降にサンプルで紹介したいと思います。
0 件のコメント:
コメントを投稿