🖌️

【脱JavaScript】HTMLとCSSでできるJavaScriptっぽい機能

2021/07/23に公開

脱jQueryが叫ばれる昨今、HTMLやCSSが進化したことでjQueryはおろかJavaScriptが無くてもWEBサイトの簡単な機能が実装できるようになってきました。

ただ、そのたびに「アコーディオンメニュー CSSだけ」とかで検索するのはとても面倒なので、今回よく使う機能とそのコピペ用のコードをまとめました。

今回紹介するHTMLとCSSでできるJavaScriptっぽい機能は以下の6つ。

  • スムーズスクロール
  • アコーディオンメニュー
  • タブメニュー
  • ハンバーガーメニュー
  • モーダルウィンドウ

順番にデモサイトやコードを紹介していきます。

スムーズスクロール

<a href="#about">のようにaタグでページ内のスクロールをスムーズにする機能はCSSに一行足すだけで実装できます。

html {
  scroll-behavior: smooth;
}

htmlに直接scroll-behavior:smooth;を実装すると、ページ全体のaタグが全てスムーズスクロールするようになるのでおすすめ。

アコーディオンメニュー

よくある質問とかで頻出のアコーディオンメニュー。

一時期、inputの機能でCSSだけでつくるアコーディオンメニューが流行りましたが、HTMLのdetailsタグとsummaryタグを使うとより一層簡単にアコーディオンメニューがつくれるようになります。

正直、detailsタグとsummaryタグがあればHTMLだけでシンプルなアコーディオンはつくれます。

<details>
	<summary>アコーディオンタイトル</summary>
	<div>アコーディオンのコンテンツ</div>
</details>

ただ、これだけだと味気ないので、私はよくCSSでアニメーションをつけたり、アイコンをつけたりしています。

デモサイトはこちら

実装したコードは以下の通りです。

アコーディオンメニューのHTMLファイル
<details class="c-faq">
	<summary>アコーディオンタイトル</summary>
	<div class="c-faq__content">アコーディオンのコンテンツ</div>
</details>
アコーディオンメニューのCSSファイル
.c-faq summary {
	position: relative;
	display: block;
	width: 80%;
	padding: 10px 20px;
	font-weight: bold;
	background-color: #a0daa8;
	cursor: pointer;
	transition: 0.2s;
}
.c-faq summary:hover {
	background-color: #6ebe79;
}
/* デフォルトの矢印を消す */
.c-faq summary::-webkit-details-marker {
	display: none;
}
/* アコーディオンの+アイコン */
.c-faq summary:after {
	position: absolute;
	font-family: "Font Awesome 5 Free";
	content: "\f067";
	font-weight: bold;
	font-size: 20px;
	color: #1b7c26;
	margin: auto;
	top: 28%;
	right: 3%;
	transition: 0.4s;
}

/* アコーディオンオープン時のスタイル */
.c-faq[open] summary {
	background-color: #6ebe79;
}
.c-faq[open] summary:after {
	transform: rotate(45deg); /* アイコンを回転 */
}

/* アニメーション */
.c-faq[open] .c-faq__content {
	animation: fadeIn 0.5s ease;
}
@keyframes fadeIn {
	0% {
		opacity: 0;
		transform: translateY(-10px);
	}
	100% {
		opacity: 1;
		transform: none;
	}
}

.c-faq__content {
	padding: 10px 20px;
}

今回はアコーディオンメニューのアイコンにfontawesomeを用いているので、コピペする際はfontawesomeのコードをhead内に入れるのを忘れないように。

<!-- fontawesome -->
<link
	href="https://use.fontawesome.com/releases/v5.6.1/css/all.css"
	rel="stylesheet"
/>

detailsタグは意外と知られていないですが、かなり使いやすいのでとてもおすすめです。

タブメニュー

JavaScriptの入門書でよくありがちなタブメニューもinputタグを活用することでHTMLとCSSだけで実装することができます。

デモサイトはこちら

実装したコードは以下の通りです。

タブメニューのHTMLファイル
<section class="c-tabs">
	<!--menu1-->
	<input id="tab1" type="radio" name="c-tabs__item" checked />
	<label class="c-tabs__item" for="tab1">メニュー1</label>

	<!--menu2-->
	<input id="tab2" type="radio" name="c-tabs__item" />
	<label class="c-tabs__item" for="tab2">メニュー2</label>

	<!--menu3-->
	<input id="tab3" type="radio" name="c-tabs__item" />
	<label class="c-tabs__item" for="tab3">メニュー3</label>

	<!--content1-->
	<div class="c-tabs__content" id="tab1_content">
		<p>メニュー1の内容がここに入ります</p>
	</div>

	<!--content2-->
	<div class="c-tabs__content" id="tab2_content">
		<p>メニュー2の内容がここに入ります</p>
	</div>

	<!--content3-->
	<div class="c-tabs__content" id="tab3_content">
		<p>メニュー3の内容がここに入ります</p>
	</div>
</section>
タブメニューのCSSファイル
/* タブ切り替え全体のスタイル*/
.c-tabs {
	background-color: #fff;
	/* タブに影をつける */
	box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
	/* タブ全体の横幅設定 */
	width: min(700px, 90%);
	/* タブの位置調整(autoで中央寄せ) */
	margin-top: 50px;
	margin: 0 auto;
	/* タブ内の余白設定 */
	padding-bottom: 40px;
}

/* ラジオボタンを全て消す */
input[name="c-tabs__item"] {
	display: none;
}

/* タブのスタイル */
.c-tabs__item {
	/*タブタイトルの幅を三分割に(ここで数の調整が可能)*/
	width: calc(100% / 3);
	/*タブタイトルの高さ*/
	height: 50px;
	line-height: 50px;
	/*タブタイトルのフォント設定*/
	font-size: 16px;
	text-align: center;
	color: #565656;
	font-weight: bold;
	/*タブタイトル下の線を設定(不要なら削除)*/
	border-bottom: 3px solid #1b7c26;
	/*タブタイトルの背景色*/
	background-color: #d9d9d9;
	display: block;
	float: left;
	transition: all 0.2s ease;
}
/* タブアイテムにカーソルを当てたとき */
.c-tabs__item:hover {
	opacity: 0.75;
	cursor: pointer;
}

/* タブ切り替えの中身のスタイル */
.c-tabs__content {
	display: none;
	padding: 40px 40px 0;
	clear: both;
	overflow: hidden;
}

/* 選択されているタブのコンテンツのみを表示 */
#tab1:checked ~ #tab1_content,
#tab2:checked ~ #tab2_content,
#tab3:checked ~ #tab3_content {
	display: block;
}

/* 選択されているタブのスタイルを変える */
.c-tabs input:checked + .c-tabs__item {
	background-color: #1b7c26;
	color: #fff;
}

仕組みは、inputタグでチェックが入っているコンテンツだけを表示させるという感じです。

タブの数だけ、checkedでcontentを表示させるコード(以下のコード参照)が必要なので、多少面倒ですが、ササッとつくれるので便利です。

#tab1:checked ~ #tab1_content,
#tab2:checked ~ #tab2_content,
#tab3:checked ~ #tab3_content {
  display: block;
}

ハンバーガーメニュー

簡易なハンバーガーメニューも、inputタグを活用してCSSだけで実装することができます。(inputタグ便利過ぎ)

メニュー部分を☓印に変えるなど細かい機能になってくると、JavaScriptのほうが実装するのが簡単なまでありますが、簡単なハンバーガーメニューならHTMLとCSSだけで実装ができて便利です。

初期表示の状態

3本線のアコーディオンメニューをクリックするとこんな感じ。

メニュー選択時の状態

デモサイトはこちら

実装したコードは以下の通りです。

ハンバーガーメニューのHTMLファイル
<header>
	<nav class="c-gnavi">
		<input
			class="c-gnavi__button--none"
			id="gnavi__checkbox"
			type="checkbox"
		/>
		<label class="c-gnavi__button" for="gnavi__checkbox"
			><span></span
		></label>
		<label
			class="c-gnavi__button--none c-gnavi__close"
			id=""
			for="gnavi__checkbox"
		></label>
		<!--ハンバーガーメニュー内のコンテンツ-->
		<div class="c-gnavi__content">
			<ul>
				<li><a href="">メニューのリスト1</a></li>
				<li><a href="">メニューのリスト2</a></li>
				<li><a href="">メニューのリスト3</a></li>
				<li><a href="">メニューのリスト4</a></li>
				<li><a href="">メニューのリスト5</a></li>
			</ul>
		</div>
	</nav>
</header>
ハンバーガーメニューのCSSファイル
ul {
	list-style: none;
}

.c-gnavi {
	position: relative;
}

/* チェックボックスを非表示 */
.c-gnavi__button--none {
	display: none;
}

/* ハンバーガーメニューの3本線アイコン */
.c-gnavi__button {
	display: inline-block;
	width: 30px;
	height: 22px;
	vertical-align: middle;
}

/* 線アイコン1本ずつ */
.c-gnavi__button span,
.c-gnavi__button span:before,
.c-gnavi__button span:after {
	position: absolute;
	/* 線の太さ */
	height: 3px;
	/* 線の長さ */
	width: 25px;
	/* 線の輪郭 */
	border-radius: 3px;
	/* 線の色 */
	background: #333;
	display: block;
	content: "";
	cursor: pointer;
}
.c-gnavi__button span:before {
	bottom: -8px;
}
.c-gnavi__button span:after {
	bottom: -16px;
}

/* メニュー以外を暗く調整 */
.c-gnavi__close {
	display: none;
	position: fixed;
	z-index: 99;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	background: black;
	opacity: 0;
	transition: 0.3s ease-in-out;
}

/* ハンバーガーメニュー内コンテンツ */
.c-gnavi__content {
	overflow: auto;
	position: fixed;
	top: 0;
	left: 0;
	/* 最前面に */
	z-index: 9999;
	/* ハンバーガーメニュー内の幅 */
	width: 90%;
	max-width: 330px;
	height: 100%;
	background: #fff;
	/* 滑らかに表示 */
	transition: 0.3s ease-in-out;
	-webkit-transform: translateX(-105%);
	/* 初期設定では隠れるように設定 */
	transform: translateX(-105%);
}

/* チェック入力後の動き */
#gnavi__checkbox:checked ~ .c-gnavi__close {
	display: block;
	opacity: 0.5;
}
#gnavi__checkbox:checked ~ .c-gnavi__content {
	-webkit-transform: translateX(0%);
	transform: translateX(0%);
	box-shadow: 6px 0 25px rgba(0, 0, 0, 0.15);
}

モーダルウィンドウ

モーダルウィンドウも、aタグとtargetを使ってHTMLとCSSだけで実装できます。

aタグのアンカーを変えれば、複数のモーダルウィンドウも実装できるので何やかんやよく使います。

このリンクをクリックすると、以下のように表示されます。

モーダルを開いた状態

デモサイトはこちら

実装したコードは以下の通りです。

モーダルウィンドウのHTMLファイル
<a href="#demo">モーダルウィンドウを開く</a>
<section id="demo" class="c-modal">
	<a href="#close" class="c-modal__cancel"></a>
	<div class="c-modal__content">
		<p>モーダルウィンドウの内容がここに表示されます。</p>
		<a href="#close" class="c-modal__close">&times;</a>
	</div>
</section>
モーダルウィンドウのCSSファイル
/* モーダルの初期状態 */
.c-modal {
	visibility: hidden;
	opacity: 0;
	position: absolute;
}
/* モーダルが選択された状態 */
.c-modal:target {
	visibility: visible;
	opacity: 1;
	position: fixed;

	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	transition: all 0.4s;
}
/* モーダルコンテンツ内 */
.c-modal__content {
	border-radius: 4px;
	position: relative;
	width: 500px;
	max-width: 90%;
	background: #fff;
	padding: 1em 2em;
}
/* モーダルコンテンツ内の☓ */
.c-modal__close {
	position: absolute;
	top: 10px;
	right: 10px;
	color: #585858;
	text-decoration: none;
}
/* モーダルコンテンツ外の背景 */
.c-modal__cancel {
	position: absolute;
	width: 100%;
	height: 100%;
	cursor: default;
	background: rgba(77, 77, 77, 0.7);
}

複数のモーダルウィンドウを実装したい際は、id名、アンカーのdemoの部分を変えてコピペすれば簡単に実装できます。

#でモーダルの表示非表示を切り替えているので、UI的に若干微妙かも。
もっといい方法あればまた更新します。

最後に:用途に合わせてCSSとJavaScriptを使おう

ということで、CSSで実装できるJavaScriptっぽい機能一覧でした。

他にもスライドバナーとかも一応CSSでそれっぽくつくれそうでしたが、JavaScriptのほうが管理のしやすさ、拡張のしやすさがともに勝っていたので紹介は避けました。

JavaScriptを使わずCSSだけでなるべく実装するのはあくまで、簡単に実装できてかつ管理しやすいから。
CSSで実装することにこだわるあまり、本来の目的である簡単に実装する目的とはずれないような機能を今回紹介しました。

皆さんのコーディングでの参考になれば幸いです。

それでは。👋

Discussion