検索

Accordion

このページは現在調整中です
Lism UI (@lism-css/ui) はまだ準備中です。

アコーディオン要素を作成できるUIコンポーネントです。

<details> / <summary> ではなく、<div> / <button> ベースで構成されており、JavaScriptで開閉アニメーションを制御します。 パネルには hidden="until-found" を活用しているため、アコーディオンが閉じた状態でもブラウザのページ内検索でコンテンツを検出でき、ヒット時に自動的にパネルが展開されます。

Preview
<Accordion.Root>
<Accordion.Item>
<Accordion.Heading>
<Accordion.Button p='20'>Accordion Example</Accordion.Button>
</Accordion.Heading>
<Accordion.Panel p='20' pt='5'>
<Dummy length='l' />
</Accordion.Panel>
</Accordion.Item>
<Accordion.Item bd-t>
<Accordion.Heading>
<Accordion.Button p='20'>Accordion Example 2</Accordion.Button>
</Accordion.Heading>
<Accordion.Panel p='20' pt='5'>
<Dummy length='l' />
</Accordion.Panel>
</Accordion.Item>
</Accordion.Root>

基本構造

div.l--stack.c--accordion
div.c--accordion_item
div.c--accordion_heading[role="heading"]
button.c--accordion_button[aria-controls="{id}"][aria-expanded="false"]
Accordion Label
span.c--accordion_icon.a--icon[aria-hidden="true"]
div.c--accordion_panel#id[hidden="until-found"]
div.c--accordion_content(.l--flow) ...Contents...

<Accordion.Button> には、末尾に <Accordion.Icon> が自動的に配置されます。 アイコンはCSSの疑似要素(::before / ::after)で描画されるため、SVGの指定は不要です。

ソースコード

_style.css
@layer lism.modules {
	.c--accordion {
		--duration: var(--acc-duration, 0.25s);
	}
	.c--accordion_item {
		--_panel-h: 0px;
		--_icon-transform: rotate(0deg);
	}

	/* 開いている時 */
	.c--accordion_item[data-opened] {
		--_icon-transform: rotate(90deg);
		--_panel-h: auto; /* Note: アニメーション時、jsでセットされる */
	}

	/* .c--accordion_button {} */
	.c--accordion_panel {
		height: var(--_panel-h);
		transition: height var(--duration);
	}

	/* コンテンツの paddingは __panel ではなくこっちにつける */
	/* .c--accordion_content {} */

	/* パネルが完全に閉じている時にabsoluteで飛ばしておくと、Chromeでも検索時に正常にハイライトされるようになる(なぜかは不明) */
	[hidden] > .c--accordion_content {
		position: absolute;
	}

	/* アイコンの描画 */
	.c--accordion_icon {
		display: grid;
		width: 1em;
		height: 1em;

		&::before,
		&::after {
			content: '';
			display: block;
			grid-area: 1 / 1;
			background-color: currentColor;
		}
		&::before {
			width: 0.1em;
			height: 100%;
			transition: transform var(--duration);
			transform: var(--_icon-transform);
		}
		&::after {
			height: 0.1em;
			width: 100%;
		}
	}

	/* フォーカス時のアウトラインを少し内側に寄せる( overflow:hidden によって途切れてしまうので)  */
	.c--accordion_button:focus-visible {
		outline: solid 2px currentColor;
		outline-color: revert;
		outline-offset: -3px; /* offset 調整だけだとブラウザ間の差が大きい */
	}

	/* --- 「視差効果を減らす」設定を考慮 --- */
	@media (prefers-reduced-motion: reduce) {
		.c--accordion_item {
			--duration: 0s;
		}
	}

	/* --- JSオフ環境の考慮 --- */
	@media (scripting: none) {
		.c--accordion_panel {
			height: auto !important;
			content-visibility: visible !important;
		}
		.c--accordion_content {
			position: static !important;
		}
	}
}

Import

@lism-css/ui パッケージで提供しています。

import { Accordion } from '@lism-css/ui/react';

以下のコンポーネントが利用できます。

  • <Accordion.Root>: 複数のアコーディオンアイテムをラップするルート要素(Stack ベース)
  • <Accordion.Item>: 個別のアコーディオン要素
  • <Accordion.Heading>: 見出しエリアのラッパー(デフォルトは <div role="heading">
  • <Accordion.Button>: 開閉トリガーのボタン(末尾に <Accordion.Icon> を自動で含みます)
  • <Accordion.Icon>: 開閉状態を示すアイコン(CSS疑似要素で描画)
  • <Accordion.Panel>: 開閉されるコンテンツパネル(hidden="until-found" を使用)

Props

プロパティ説明
<Accordion.Root>
allowMultiple
複数のアコーディオンを同時に展開できるようにします。デフォルトでは一つしか展開できません。
<Accordion.Heading>
as
見出しのHTMLタグを指定します。デフォルトは divrole="heading" が自動付与されます)。h2h6 を指定すると role は付与されません。
<Accordion.Panel>
flow
パネル内のコンテンツ領域(__content)に渡すフローレイアウトの設定。

Examples

見出しタグを変更する

<Accordion.Heading> はデフォルトでは <div role="heading"> として出力されますが、ash3 などの見出しタグを指定することで、実際の見出し要素として出力できます。

<Accordion.Root bd>
<Accordion.Item>
<Accordion.Heading as='h3'>
<Accordion.Button p='20'>Accordion Label</Accordion.Button>
</Accordion.Heading>
<Accordion.Panel p='20' pt='5'>
<Dummy length='l' />
</Accordion.Panel>
</Accordion.Item>
<Accordion.Item bd-t>
<Accordion.Heading as='h3'>
<Accordion.Button p='20'>Accordion Label</Accordion.Button>
</Accordion.Heading>
<Accordion.Panel p='20' pt='5'>
<Dummy length='l' />
</Accordion.Panel>
</Accordion.Item>
</Accordion.Root>

アニメーション時間を変更し、複数同時展開を許可する

アコーディオンの開閉アニメーションの速度は --duration 変数で管理されており、デフォルトは 0.25s です。

デフォルトでは、同じ <Accordion.Root> 内で一つのアコーディオンしか同時に展開できません。 allowMultiple を指定することで、複数を同時に展開できるようになります。

Preview
<Accordion.Root g='1px' allowMultiple>
<Accordion.Item style={{'--duration': '.15s'}}>
<Accordion.Heading>
<Accordion.Button p='20'>Accordion Label 1</Accordion.Button>
</Accordion.Heading>
<Accordion.Panel p='20' pt='5'>
...
</Accordion.Panel>
</Accordion.Item>
<Accordion.Item style={{'--duration': '.15s'}}>
<Accordion.Heading>
<Accordion.Button p='20'>Accordion Label 2</Accordion.Button>
</Accordion.Heading>
<Accordion.Panel p='20' pt='5'>
...
</Accordion.Panel>
</Accordion.Item>
...
</Accordion.Root>

© Lism CSS. All rights reserved.