--> Reactでスマホのみハンバーガーメニューにする -Sass編 | BORDERLESSS
scroll

Reactでスマホのみハンバーガーメニューにする -Sass編

最初はreact-burger-menuを使って実装していたものの、
PCとスマホでメニューの表示方法を切り替えたいと思い、調べてみました。

そこで行き着いた方法が、三項演算子でのクラスの切り替えです。

でもclassNameでScssを使ってる場合が探せなかったので、メモしておきます。
本当はマルチクラスで表現したかったのですが、うまくいかなかったので、今回はシングルクラスでの表現にしました。

この記事はScssやCSSについてはすでに知識がある人向けに書いています。

完成コード

import Link from "next/link";
import styles from '../styles/Home.module.scss';
import React, { useState } from "react";

export const HeaderNav = () => {
	
	const [openMenu, setOpenMenu] = useState(false);
	const handleMenuOpen = () => {
	setOpenMenu(!openMenu);
	};

	return (
		<>
		<button onClick={handleMenuOpen} type="button" className={styles['p-header-nav__trigger']}
		>
			<span></span>
			<span></span>
			<span></span>
		</button>
		<ul
			className={`${styles['l-header-nav__contents']} 
			${openMenu ? styles['open'] : styles['clouse']}`
		}>
			<li>
                           //省略
			</li>
		</ul>
	</>
	);
}
.l-header-nav__contents {
	display: flex;
	align-items: center;
	align-content: center;
	justify-content: space-between;
	width: 100%;
	list-style: none;
	font-size: 14px;
	@include breakPoint(sp) {
		overflow: hidden;
		position: fixed;
		// right: -201px;
		transition: .2s;
		top: 100px;
		display: flex;
		align-items: center;
		align-content: center;
		flex-direction: column;
		justify-content: space-around;
		z-index: 10;
		height: calc(100vh - 100px);
		max-width: 12em;
		width: 80%;
		background-color: #fff;
		border: 1px solid $COLOR_BULE_2;
		border-radius: 24px 0 0 24px;
		box-shadow: 0 4px 12px rgba($COLOR_BLACK, .3);
		transition: .2s;
		&.open {
			transition: .2s;
			right: 0;
		}
		&.clouse {
			transition: .2s;
			right: -100%;
		}	}
	}

ポイント解説

ポイントは下記です

  • Scssでも三項演算子でマルチクラス付与できた
  • 基礎のクラス内でfalseを定義して、Open付与時に上書きもできる
  • マルチクラスのおかげで、Scssの書き方がスッキリ

三項演算子とは

(任意の条件) ? (tureの時の処理) : (falseの時の処理)

条件ごとに処理を変えることができる式のこと。
詳しくはこちら。

Scssでも三項演算子でマルチクラス付与できた

最初調べながら書いている際、Scssでマルチクラスを書いているとエラーが出ていました。

//NGの書き方
<ul
className={openMenu ? ${styles['l-header-nav__contents']${styles['open'] : undefined}}}>
//OKの書き方1
<ul
className={`${styles['l-header-nav__contents']} 
${openMenu ? styles['open'] : styles['close']}`
}>

//OKの書き方2
<ul
className={`${styles['l-header-nav__contents']} 
${openMenu ? styles['open'] : undefined}`
}>

先にベースのスタイルを当ててから、三項演算子を書くとうまく行きました。

ベースになるclass内でright: -100%を定義して、Open付与時に上書きもできる

前述のOKパターンの違いは、false時にcloseクラスを付与するか、特に何も付与しないか、の違いです。
CSSでハンバーガーメニューを作る場合、デフォルトで隠れた状態のスタイルを作り、openクラスが追加された時だけコンテンツの位置が変わる書き方が多いのではないでしょうか。

そういった慣習を表現できるのがundefinedを使った書き方だと思います。

undefinedを使う場合、right: -100%;は.l-header-nav__contents(sp)の中に書きます。

マルチクラスのおかげで、書き方がスッキリ

マルチクラスができないと思っていた間は、open時もclose時もdispay; flexなど細かく書いていたので、コード量が増えていました。

マルチクラスにすると、上書きしたい箇所だけ追加すればいいので、読みやすいです。

修正時も、あちこち修正するよりずっとメンテナンスしやすいですね。

これでよりコーダーらしい使い方ができそうだなと一人にやりとしています。