ハンバーガーメニューを作成する時に現行サイトの修正だとサイトによって記述を変えることがあるので、汎用的なハンバーガーモーダルメニューを作成してみました。
1つのメニュー領域だけでなく複数のメニュー領域やサイドバーをモーダル内にタグ付けするだけで入れられるようにしています。
また、ページ内アンカーリンクに対しても対応してみました。
それぞれのソースは長いのですが重要なポイントを解説していきます。
jsは
〇モーダルの表示領域を作成して、そこにメニューを複製します。
〇ハンバーガーボタンに特定のクラスを付与して押下毎にクラスを付け替えます。
〇モーダルメニュー以外を押下した場合はメニューを閉じるようにする。
〇アンカーリンクの場合はモーダルを閉じてスクロールするようにする。
が主な処理となります。
他のハンバーガーメニューと違うのはモーダルの領域に既存のエリアを複製するという点です。
これによって既存のメニューを簡単にモーダル化することが可能になります。
また、デモではヘッダーメニューとサイドバーをモーダルメニューに入れる設定になっています。複数の領域をモーダルメニューに出来るということです。
$(function(){
//クリック判定フラグを0に設定
let go_click_flg = "0";//モーダルの状態を表すフラグ0=非表示、1=表示
let modalOverlay = '#go_modal_overlay';//body最後に入れる背景レイヤIDー
let modalOverlayName = 'go_modal_overlay';
let modalInner = '#go_modal_inner';//モーダルの大枠ID
let modalInnerName = 'go_modal_inner';
let modalA = ".go_modal_a";//クリック時に処理するclass
let modalAName = "go_modal_a";
let modalContent = '.go_menu_content'//モーダル内に持ってくるエリアに付けるclass
let modalOpenName = 'go_modal_open';
let modalCloseName = 'go_modal_close';
let modalFixedName = 'go_modal_fixed';
let modalNoscrollName = 'go_nonscrollbar';
//オーバーレイ用の要素を追加
$('body').append('<div id="' + modalOverlayName + '" class="' + modalAName + ' ' + modalCloseName + '"><div id="' + modalInnerName + '"></div></div>');
//対象のクラスをオーバーレイ内にクローン
$(modalContent).clone().appendTo(modalInner);
//モーダル内のリンクがアンカーリンクだったらクラスを付与
$(modalOverlay + ' a[href^="#"]').addClass(modalAName);
$(modalOverlay + ' a[href^="#"]').addClass(modalCloseName);
//「.go_modal_a」をクリックしたときの処理
$(document).on("click",modalA,function(e){
//ページ内アンカーリンク対応
var href = $(this).attr("href");
var $target = $((href == "#" || href == "" ) ? 'html' : href);
var position;
if ($target.length) {
position = $target.offset().top;
}else{
position = 0;
}
if(go_click_flg == "0"){//モーダルが開いていない時
scrollpos = $(window).scrollTop() + position;//現在表示位置
$('body').addClass(modalFixedName).css({'top': -scrollpos});
mopen();
}else if(go_click_flg == "1"){//モーダルが開いている時
mclose();
//表示位置調整
scrollpos = scrollpos + position;//現在表示位置
e.stopPropagation();//モーダルをと実時に処理が複数起動しないように伝搬を止める
}
});
function mopen(){
//オーバーレイをフェードイン
$(modalOverlay).fadeIn('slow');
//モーダルコンテンツフェードイン
$(modalInner).fadeIn('slow');
//スクロールをさせないようにする
$('body').addClass(modalNoscrollName);
//openとcloseを入れ替える
$(modalA).removeClass(modalOpenName);
$(modalA).addClass(modalCloseName);
//クリック判定フラグを1に設定
go_click_flg = "1";
}
function mclose(){
// モーダルコンテンツとオーバーレイをフェードアウト
$(modalInner).fadeOut('slow');
$(modalOverlay).fadeOut('slow',function(){
// html、bodyの固定解除
$('body').removeClass(modalFixedName).css({'top': 0});
//スクロール
$("html,body").animate({scrollTop:scrollpos},0);
});
//openとcloseを入れ替える
$(modalA).removeClass(modalCloseName);
$(modalA).addClass(modalOpenName);
//スクロール出来るように
$('body').removeClass(modalNoscrollName);
//クリック判定フラグを初期化
go_click_flg = "0";
}
//スムーズスクロール
$('a[href^="#"]'+'a:not(.no-scroll-target)').click(function(e) {
e.preventDefault();
var headerHeight = $('.go_menu_button').outerHeight();//header高さ取得 【ヘッダー追従用】
var speed = 600; // ミリ秒
var href = $(this).attr("href");
var $target = $((href == "#" || href == "" ) ? 'html' : href);
if ($target.length) {
var position = $target.offset().top-headerHeight;
$('body,html').animate({scrollTop:position}, speed, 'swing');
}
});
});
CSSは後半がメニューに関連する部分ですが、モーダルメニューで問題になるスクロールバーの設定が冒頭に入っています。
これはモーダル内で画面高さを超える状態になるとスクロールバーが出たり、通常状態でスクロールバーがあると表示がずれるのを防ぐために、スマホ表示時は常に表示しないようにしています。
@charset "UTF-8";
* {
font-size: 14px;
-webkit-text-size-adjust: 100%;
line-height: 1.6;
margin: 0px;
padding: 0px;
box-sizing: border-box;
word-break: break-all;
min-height: 0;
min-width: 0;
}
body {
width: 100%;
text-align: center;
overflow-y: scroll;
-ms-overflow-style: none;/* IE, Edge 対応 */
scrollbar-width: none;/* Firefox 対応 */
color: #333;
/*font-family:"HG丸ゴシックM-PRO","MS Pゴシック","メイリオ","Meiryo","ヒラギノ角ゴ Pro W3","Hiragino Kaku Gothic Pro","MS P Gothic","Osaka,Verdana,Arial","Helvetica",sans-serif;*/
font-family: "游明朝", YuMincho, "Hiragino Mincho ProN W3", "ヒラギノ明朝 ProN W3", "Hiragino Mincho ProN", "HG明朝E", "MS P明朝", "MS 明朝", serif;
/*font-family: "M PLUS 1p",-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";*/
/*font-family: 'ヒラギノ角ゴ ProN', 'Hiragino Kaku Gothic ProN', 'メイリオ', Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif;*/
/*font-family: "游ゴシック体", YuGothic, "游ゴシック", "Yu Gothic", sans-serif; */
}
body::-webkit-scrollbar {
display: none;
}
@media screen and (min-width: 768px) {
body {
font-size: 1rem;
overflow-y: auto;
-ms-overflow-style: auto;/* IE, Edge 対応 */
scrollbar-width: auto;/* Firefox 対応 */
}
body::-webkit-scrollbar {
display: block;
width: 15px;
}
body::-webkit-scrollbar-thumb {
background: #c1c1c1;
}
body::-webkit-scrollbar-track-piece:start,
body::-webkit-scrollbar-track-piece:end {
background: #f1f1f1;
}
}
a {
outline: none;
opacity: 1;
-webkit-transition: opacity 0.2s ease-in-out;
transition: opacity 0.2s ease-in-out;
text-decoration: none;
color: #6A6868; }
a:hover {
opacity: 0.5;
}
/*コンテンツ▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼*/
header {
margin: 0 auto;
padding: 0;
width:100%;
}
nav ul li{
display: block;
}
@media screen and (min-width: 768px) {
nav ul li{
display: inline-block;
}
}
#main {
margin: 0 auto;
padding: 0;
width:100%;
max-width: 100%;
}
#main p{
padding:30px;/*テスト用*/
}
#main p:nth-child(even){
background-color: #aaa;
}
#main:after {
content: "";
clear: both;
display: block;
}
.content{
margin: 0 auto;
padding: 0;
width:100%;
float:left;
background: #999;
}
.sidebar {
margin: 0 auto;
padding: 0;
background: #099;
display: right;
}
@media screen and (min-width: 768px) {
.content{
width:75%;
float:left;
}
.sidebar {
display: block;
width:25%;
float:right;
}
}
footer {
margin: 0 auto;
padding: 0;
width:100%;
}
/*コンテンツ▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲*/
/*モーダルメニュー▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼*/
/*スクロールバー関連*/
.go_scrollbar_y_on {
overflow-y: scroll;
}
.go_nonscrollbar {
-ms-overflow-style: none;
scrollbar-width: none;
}
.go_nonscrollbar::-webkit-scrollbar {
display: none;
}
/*ボタン*/
.go_menu_button {
z-index: 10020;
width: auto;
height: auto;
margin: 0;
position: fixed;
top: 8px;
right: 8px;
padding: 1%;
background-color:transparent;
}
@media screen and (min-width: 768px) {
.go_menu_button {
display: none;
}
}
.go_menu_button a {
z-index: 10030;
cursor: pointer;
width: 40px;
height: 40px;
position: relative;
display: block;
}
.go_menu_line1,
.go_menu_line2,
.go_menu_line3 {
left: 0;
width: 100%;
height: 10%;
background-color: #000;
transition-duration: 1s;
border-radius: 8px;
position: absolute;
}
.go_menu_line1 {
top: 10%;
}
.go_menu_line2 {
top: 45%;
}
.go_menu_line3 {
bottom: 10%;
}
a.go_modal_close > .go_menu_line1 {
-webkit-transform: rotate(-45deg);
transform: rotate(-45deg);
top: 45%;
}
a.go_modal_close > .go_menu_line2 {
opacity: 0;
}
a.go_modal_close > .go_menu_line3 {
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
bottom: 45%;
}
.go_menu_content{
display: none;
}
@media screen and (min-width: 768px) {
.go_menu_content {
display: block;
}
}
.go_modal_fixed {
position: fixed;
width: 100%;
height: 100%;
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
}
#go_modal_overlay {
z-index: 9999;
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 120%;
background-color: rgba(200,200,200,0.5);
-ms-overflow-style: none;
scrollbar-width: none;
overflow-y: scroll;
}
#go_modal_overlay::-webkit-scrollbar {
display: none;
}
#go_modal_inner{
z-index: 10000;
height: auto;
margin-left:10%;
width: 90%;
padding-bottom: 30%;
}
#go_modal_inner .go_menu_content{
display: block;
background-color: #E0F8E6;
}
.go_menu_content li{
padding: 60px 0;/*テスト用*/
}
/*モーダルメニュー▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲*/
HTMLは全幅ヘッダー内にメニューと2カラム構成でサイドバーがある状態にしています。
オレンジ色の部分がハンバーガーでbodyの子要素になるように記述します。
青色の部分がモーダル内に入れたい部分で、class="go_menu_content"
でくくります。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"/>
<meta name="referrer" content="no-referrer-when-downgrade"/>
<title>汎用モーダルメニュー</title>
<link rel="shortcut icon" href="favicon.ico" type="image/vnd.microsoft.icon">
<link rel="icon" href="favicon.ico" type="image/vnd.microsoft.icon">
<link href="style.css" rel="stylesheet">
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<script src="ovarley_menu.js"></script>
</head>
<body class="go_scrollbar_y_on" itemscope itemtype="https://schema.org/WebPage" data-barba="wrapper">
<div class="go_menu_button">
<a data-target="go_menu_content" class="go_modal_a go_modal_open">
<span class="go_menu_line1"></span>
<span class="go_menu_line2"></span>
<span class="go_menu_line3"></span>
</a>
</div><!-- go_menu_button end -->
<header>
<div class="header_nav">
<div class="go_menu_content"><!--モーダルに入れたいセクションを括る-->
<nav>
<ul>
<li><a href="#sc" title="メニュー1">メニュー1</a></li>
<li><a href="" title="メニュー1">メニュー1</a></li>
<li><a href="" title="メニュー1">メニュー1</a></li>
<li><a href="" title="メニュー1">メニュー1</a></li>
<li><a href="" title="メニュー1">メニュー1</a></li>
</ul>
</nav>
</div>
</div><!-- header_nav end -->
<!--<h1></h1>-->
</header>
<article id="main">
<div class="content">
<p>1</p>
<p>1</p>
<p>1</p>
<p>1</p>
<p>1</p>
<p>1</p>
<p>1</p>
<p>1</p>
<p>1</p>
<p>1</p>
<p>1</p>
<p>1</p>
<p>1</p>
<p>1</p>
<p>1</p>
<p>1</p>
<p>1</p>
<p id="sc">1000</p>
<p>1</p>
<p>1</p>
<p>1</p>
<p>1</p>
<p>1</p>
<p>1</p>
</div>
<div class="sidebar">
<div class="go_menu_content"><!--モーダルに入れたいセクションを括る-->
<p>side</p>
<p>side</p>
<p>side</p>
<p>side</p>
<p>side</p>
</div>
</div><!--sidebar end-->
</article><!-- main end-->
<footer>
<div class="footer_inner">
<p>©. All Rights Reserved.</p>
</div>
</footer>
</body>
</html>
コメント