Created
January 14, 2021 23:41
-
-
Save tak-dcxi/58987e71b8b332bb704288e9780ed00d to your computer and use it in GitHub Desktop.
Drawer Menu Pattern 2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div class="wrapper" data-inert-target> | |
<header class="global-header"> | |
<div class="global-header__container"> | |
<div class="global-header__title"> | |
<p class="logo">My Drawer Menu</p> | |
</div> | |
<div class="global-header__burger-button"> | |
<button class="menu-button js-menu-open-trigger" type="button" aria-label="メニューを開く"> | |
<span class="menu-button__icon -open"></span> | |
</button> | |
</div> | |
</div> | |
</header> | |
<main class="main-content"> | |
<article class="article"> | |
<h1 class="article__title">このドロワーメニューについて</h1> | |
<div class="article__sentence"> | |
<p>ユーザビリティおよびにアクセシビリティを意識した自作ドロワーメニューです。</p> | |
</div> | |
<section class="article__section"> | |
<h2 class="article__subtitle">自己チェック</h2> | |
<ul class="article__list"> | |
<li class="article__list-item -checked">メニューが開いている時に背景のスクロールを無効にする</li> | |
<li class="article__list-item -checked">メニュー内のリンクをクリック時にメニューを閉じることができる(非同期遷移のサイトやページ内リンクをメニューに含む場合は必須)</li> | |
<li class="article__list-item -checked">支援技術向けのラベルをボタンとメニュー本体に付与する</li> | |
<li class="article__list-item -checked">裏側のコンテンツの読み上げを制御する</li> | |
<li class="article__list-item -checked">裏側のコンテンツを操作対象外にする(inert属性を利用)</li> | |
<li class="article__list-item -checked">メニュー本体をEsc操作で閉じられる</li> | |
<li class="article__list-item -checked">メニューを閉じた時にフォーカスをボタンに当てる</li> | |
<li class="article__list-item -checked">背景固定時のスクロールバー消失によるガタツキを防止する</li> | |
<li class="article__list-item -checked">durationの設定を反映したCSSカスタムプロパティを生成することで、JSのオプションで一括でアニメーションのdurationを変えられるようにする</li> | |
</ul> | |
</section> | |
<section class="article__section"> | |
<h2 class="article__subtitle">課題点</h2> | |
<ul class="article__list"> | |
<li class="article__list-item -not-checked">裏側のコンテンツの読み上げ制御はDOM依存のため要検討</li> | |
<li class="article__list-item -not-checked">自作するよりMicromodal.js使ったほうが良さそう</li> | |
</ul> | |
</section> | |
<section class="article__section"> | |
<h2 class="article__subtitle">参考サイト</h2> | |
<ul class="article__list"> | |
<li class="article__list-item -link"><a class="article__link" href="https://magazine.techcareer.jp/instacart-blog/technology-instacart-blog/6418/" target="_blank" rel="noopener noreferrer">アクセシブルなWebモーダルを作る | techcareer magazine</a></li> | |
<li class="article__list-item -link"><a class="article__link" href="https://www.w3.org/TR/wai-aria-practices-1.1/examples/dialog-modal/dialog.html" target="_blank" rel="noopener noreferrer">Modal Dialog Example | WAI-ARIA Authoring Practices 1.1</a></li> | |
<li class="article__list-item -link"><a class="article__link" href="https://bootstrap-guide.com/components/modal" target="_blank" rel="noopener noreferrer">モーダル~Bootstrap5設置ガイド</a></li> | |
<li class="article__list-item -link"><a class="article__link" href="https://standard.shiftbrain.com/blog/unavailable-inert-regions-and-inert-attribute" target="_blank" rel="noopener noreferrer">UIにおける見えるけど利用できない非活性な領域の実装とinert属性について - シフトブレイン/スタンダードデザインユニット</a></li> | |
</ul> | |
</section> | |
</article> | |
</main> | |
</div> | |
<nav id="js-menu-content" class="drawer-menu" style="display: none;"> | |
<div class="drawer-menu__container"> | |
<h2 id="js-menu-label" class="drawer-menu__headline">メニュー</h2> | |
<ul class="drawer-menu__list"> | |
<li class="drawer-menu__item"> | |
<a class="drawer-menu__link" href="#"> | |
<span class="drawer-menu__en-label">Drawer Menu</span> | |
<span class="drawer-menu__jp-label">ドロワーメニュー</span> | |
</a> | |
</li> | |
<li class="drawer-menu__item"> | |
<a class="drawer-menu__link" href="https://codepen.io/tak-dcxi/pen/VwZbwyg" target="_blank" rel="noreferrer noopener"> | |
<span class="drawer-menu__en-label">Hero Header</span> | |
<span class="drawer-menu__jp-label">ヒーローヘッダー</span> | |
</a> | |
</li> | |
<li class="drawer-menu__item"> | |
<a class="drawer-menu__link" href="https://codepen.io/tak-dcxi/pen/jOEVKEX" target="_blank" rel="noreferrer noopener"> | |
<span class="drawer-menu__en-label">Observe Animation</span> | |
<span class="drawer-menu__jp-label">スクロール連動アニメーション</span> | |
</a> | |
</li> | |
<li class="drawer-menu__item"> | |
<a class="drawer-menu__link" href="https://codepen.io/tak-dcxi/pen/yLaaJYj" target="_blank" rel="noreferrer noopener"> | |
<span class="drawer-menu__en-label">Accordion</span> | |
<span class="drawer-menu__jp-label">アコーディオン</span> | |
</a> | |
</li> | |
<li class="drawer-menu__item"> | |
<a class="drawer-menu__link" href="https://codepen.io/tak-dcxi/pen/vYEyrGJ" target="_blank" rel="noreferrer noopener"> | |
<span class="drawer-menu__en-label">Tab</span> | |
<span class="drawer-menu__jp-label">タブコンポーネント</span> | |
</a> | |
</li> | |
<li class="drawer-menu__item"> | |
<a class="drawer-menu__link" href="https://codepen.io/tak-dcxi/pen/vYXWPvZ" target="_blank" rel="noreferrer noopener"> | |
<span class="drawer-menu__en-label">Form Template</span> | |
<span class="drawer-menu__jp-label">フォームテンプレート</span> | |
</a> | |
</li> | |
</ul> | |
<div class="drawer-menu__close-button"> | |
<button class="menu-button js-menu-close-trigger" type="button" aria-label="メニューを閉じる"> | |
<span class="menu-button__icon -close"></span> | |
</button> | |
</div> | |
</div> | |
<div class="drawer-menu__overlay js-menu-close-trigger"></div> | |
</nav> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
window.addEventListener("DOMContentLoaded", () => { | |
const drawer = document.getElementById("js-menu-content"); | |
new DrawerMenu(drawer); | |
new PrepareCurrent(drawer); | |
}); | |
class DrawerMenu { | |
constructor(root, options) { | |
this.root = root; | |
if (!this.root) return; | |
const defaultOptions = { | |
openTriggerSelector: ".js-menu-open-trigger", // メニューを開く際のターゲットとなるセレクタ | |
closeTriggerSelector: ".js-menu-close-trigger", // メニューを閉じる際のターゲットとなるセレクタ | |
inertTargetSelector: "[data-inert-target]", // 開いている時はこのセレクタを読み上げ対象外にする。 | |
labelSelector: "#js-menu-label", // 支援技術向けのメニュー本体のラベルとなるidセレクタ | |
hideLabelSelector: true, //ニューのラベルとなる要素を視覚的に非表示にするか | |
clickLinkToClose: true, // メニュー内のリンクをクリック時にメニューを閉じるか | |
toggleDuration: 500 // メニューの遷移時間 | |
}; | |
const mergedOptions = Object.assign(defaultOptions, options); | |
this.options = mergedOptions; | |
/** | |
* メニューを開くトリガーとなるセレクタの設定 | |
*/ | |
this.openTrigger = document.querySelectorAll( | |
this.options.openTriggerSelector | |
); | |
if (!this.openTrigger.length) | |
throw TypeError("メニューを開く要素が見つかりません"); | |
/** | |
* メニューを閉じるトリガーとなるセレクタの設定 | |
*/ | |
this.closeTrigger = this.options.clickLinkToClose | |
? document.querySelectorAll( | |
`${this.options.closeTriggerSelector}, #${this.root.getAttribute( | |
"id" | |
)} a` | |
) | |
: document.querySelectorAll(this.options.closeTriggerSelector); | |
if (!this.closeTrigger.length) | |
throw TypeError("メニューを閉じる要素が見つかりません"); | |
/** | |
* メニューのラベルとなるセレクタの設定 | |
*/ | |
this.label = document.querySelector(this.options.labelSelector); | |
if (!this.label) throw TypeError("ラベルとなる見出し要素の指定は必須です"); | |
/** | |
* メニューが開かれている際に読み上げ対象外とするセレクタの指定 | |
*/ | |
this.inertTarget = document.querySelectorAll( | |
this.options.inertTargetSelector | |
); | |
if (!this.inertTarget.length) | |
throw TypeError("inert対象のセレクタの指定は必須です"); | |
/** | |
* 状態を格納する変数 | |
*/ | |
this.isExpanded = false; // メニューの開閉状態を格納する | |
this.openButton; // どのトリガーでメニューが開かれたかを格納する | |
this.scrollAmount; // メニューが開かれた際のスクロール量を格納する | |
/** | |
* 初期化時に属性を付与 | |
*/ | |
this.prepareAttributes(); | |
/** | |
* イベントハンドラの設定 | |
*/ | |
this.openTrigger.forEach((trigger) => { | |
attachEvent(trigger, "click", this.handleOpenTriggerClick.bind(this)); | |
}); | |
this.closeTrigger.forEach((trigger) => { | |
attachEvent(trigger, "click", this.handleCloseTriggerClick.bind(this)); | |
}); | |
attachEvent(document, "keyup", this.handleKeyup.bind(this)); | |
} | |
prepareAttributes() { | |
this.root.setAttribute("inert", ""); | |
this.root.style.display = "none"; | |
this.openTrigger.forEach((trigger) => { | |
trigger.setAttribute("aria-haspopup", true); | |
}); | |
this.label.setAttribute("tabindex", "-1"); | |
document.documentElement.style.setProperty( | |
"--menu-toggle-duration", | |
`${this.options.toggleDuration}ms` | |
); | |
/** | |
* ラベル対象にidが含まれていない場合はid属性を付与 | |
*/ | |
if (!this.label.hasAttribute("id")) { | |
const randomId = "aria-label-" + Math.random().toString(32).substring(2); | |
this.label.setAttribute("id", randomId); | |
} | |
const labelId = this.label.getAttribute("id"); | |
/** | |
* ラベル対象を非表示にする設定をしている場合の処理 | |
*/ | |
if (this.options.hideLabelSelector) { | |
const styles = { | |
border: "0", | |
clip: "rect(0 0 0 0)", | |
clipPath: "inset(50%)", | |
height: "1px", | |
margin: "-1px", | |
overflow: "hidden", | |
padding: "0", | |
position: "absolute", | |
whiteSpace: "nowrap", | |
width: "1px" | |
}; | |
Object.keys(styles).forEach((key) => { | |
document.querySelector(this.options.labelSelector).style[key] = | |
styles[key]; | |
}); | |
} | |
this.root.setAttribute("aria-labelledby", labelId); | |
} | |
handleOpenTriggerClick(event) { | |
event.preventDefault; | |
this.open(); | |
} | |
handleCloseTriggerClick(event) { | |
event.preventDefault; | |
this.close(); | |
} | |
handleKeyup(event) { | |
const pressEsc = event.keyCode === 27; | |
if (this.isExpanded && pressEsc) { | |
event.preventDefault; | |
this.close(); | |
} | |
} | |
open() { | |
this.root.removeAttribute("inert"); | |
this.root.style.display = ""; | |
this.backfaceFixed(true); | |
this.inertTarget.forEach((target) => { | |
target.setAttribute("inert", ""); | |
}); | |
this.openButton = document.activeElement; | |
setTimeout(() => { | |
this.label.focus(); | |
}, 100); | |
this.isExpanded = true; | |
} | |
close() { | |
this.root.setAttribute("inert", ""); | |
this.backfaceFixed(); | |
this.openTrigger.forEach((trigger) => { | |
trigger.setAttribute("inert", ""); | |
}); | |
this.inertTarget.forEach((target) => { | |
target.removeAttribute("inert"); | |
}); | |
new Promise((resolve) => { | |
setTimeout(() => { | |
this.root.style.display = "none"; | |
this.openTrigger.forEach((trigger) => { | |
trigger.removeAttribute("inert"); | |
}); | |
resolve(); | |
}, this.options.toggleDuration); | |
}).then(() => { | |
this.openButton.focus(); | |
}); | |
this.isExpanded = false; | |
} | |
backfaceFixed(fixed) { | |
/** | |
* 表示されているスクロールバーとの差分を計測し、背面固定時はその差分body要素にボーダーを生成する | |
*/ | |
const scrollbarWidth = window.innerWidth - document.body.clientWidth; | |
document.body.style.borderRight = fixed | |
? `${scrollbarWidth}px solid transparent` | |
: ""; | |
/** | |
* 背面固定する対象を決定する | |
*/ | |
const scrollingElement = () => { | |
const browser = window.navigator.userAgent.toLowerCase(); | |
// document.scrollingElementが有効なブラウザの場合 | |
if ("scrollingElement" in document) return document.scrollingElement; | |
// document.scrollingElementが無効なiOSの場合はbody要素を | |
if (browser.indexOf("webkit") > 0) return document.body; | |
// その他(IEとか)はhtml要素を | |
return document.documentElement; | |
}; | |
/** | |
* 背面固定時に変数にスクロール量を格納 | |
*/ | |
if (fixed) this.scrollAmount = scrollingElement().scrollTop; | |
/** | |
* CSSで背面を固定 | |
*/ | |
const styles = { | |
height: "100vh", | |
left: "0", | |
overflow: "hidden", | |
position: "fixed", | |
top: `${this.scrollAmount * -1}px`, | |
width: "100vw" | |
}; | |
Object.keys(styles).forEach((key) => { | |
scrollingElement().style[key] = fixed ? styles[key] : ""; | |
}); | |
/** | |
* 背面固定解除時に元の位置にスクロールする | |
*/ | |
if (!fixed) window.scrollTo(0, this.scrollAmount); | |
} | |
} | |
function attachEvent(element, event, handler, options) { | |
element.addEventListener(event, handler, options); | |
return { | |
unsubscribe() { | |
element.removeEventListener(event, handler); | |
} | |
}; | |
} | |
class PrepareCurrent { | |
constructor(root, options) { | |
this.root = root; | |
if (!this.root) return; | |
const defaultOptions = { | |
level: 1, | |
ignoreSelector: ".js-ignore-current" | |
}; | |
const mergedOptions = Object.assign(defaultOptions, options); | |
this.options = mergedOptions; | |
this.targets = Array.from( | |
this.root.querySelectorAll(`a:not(${this.options.ignoreSelector})`) | |
); | |
this.targets.map((target) => { | |
this.setCurrentLocation(target, this.options.level); | |
this.setCurrentPage(target); | |
}); | |
} | |
setCurrentLocation(target, level) { | |
const paths = this.getRootAbsolutePath( | |
this.convertHrefToRootAbsolutePath(target) | |
); | |
const matchedPath = paths.map((path, index) => { | |
if (index <= level - 1) { | |
return `${path}/`; | |
} | |
return null; | |
}); | |
const directories = this.getRootAbsolutePath(window.location.pathname); | |
const matchedDirectory = directories.map((directory, index) => { | |
if (index <= level - 1) { | |
return `${directory}/`; | |
} | |
return null; | |
}); | |
const directory = `/${matchedDirectory.join("")}`; | |
const href = `/${matchedPath.join("")}`; | |
if (href === directory && href !== "//") { | |
target.setAttribute("aria-current", "location"); | |
} | |
} | |
setCurrentPage(target) { | |
const path = this.convertHrefToRootAbsolutePath(target); | |
const locationPathname = window.location.pathname.replace( | |
/index\.html$/, | |
"" | |
); | |
if (path === locationPathname) { | |
target.setAttribute("aria-current", "page"); | |
} | |
} | |
convertHrefToRootAbsolutePath(target) { | |
const absolutePath = | |
target instanceof HTMLElement ? target.href : target.href.baseVal; | |
const protocolHost = `${window.location.protocol}//${window.location.host}`; | |
return absolutePath.replace(protocolHost, "").replace(/index\.html$/, ""); | |
} | |
getRootAbsolutePath(absolutePath) { | |
return absolutePath | |
.replace(/\\/g, "/") | |
.replace(/\/[^/]*$/, "") | |
.slice(1) | |
.split("/"); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script src="https://cdnjs.cloudflare.com/ajax/libs/stickyfill/2.1.0/stickyfill.min.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/focus-visible@5.2.0/dist/focus-visible.min.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/wicg-inert@3.1.0/dist/inert.min.js"></script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// z-indexをmap化して管理する | |
$z-index: (global-header, drawer-menu); | |
@function z-index($module) { | |
@return index($z-index, $module); | |
} | |
html { | |
box-sizing: border-box; | |
font-size: 75%; | |
-webkit-font-smoothing: subpixel-antialiased; | |
-moz-osx-font-smoothing: auto; | |
@media screen and (min-width: 768px) { | |
font-size: 87.5%; | |
} | |
@media screen and (min-width: 1200px) { | |
font-size: 100%; | |
} | |
} | |
:root { | |
--base-color: #434a56; | |
--white-color-primary: #f7f8f8; | |
--gray-color-primary: #676f79; | |
--gray-color-secondary: #e2e2e2; | |
--gray-color-tertiary: #aaa; | |
--active-color: #006e9b; | |
--header-height: 52px; | |
@media screen and (min-width: 768px) { | |
--header-height: 56px; | |
} | |
@media screen and (min-width: 1200px) { | |
--header-height: 60px; | |
} | |
} | |
*, | |
*::before, | |
*::after { | |
box-sizing: inherit; | |
margin: 0; | |
} | |
body { | |
background-color: var(--white-color-primary); | |
color: var(--base-color); | |
font-family: "Helvetica Neue", "Segoe UI", "Hiragino Sans", | |
"Hiragino Kaku Gothic ProN", Meiryo, sans-serif; | |
font-size: 1em; | |
line-height: 1.5; | |
} | |
.menu-button { | |
appearance: none; | |
background-color: var(--base-color); | |
border: none; | |
box-shadow: 0 0 12px rgba(0, 0, 0, 0.15); | |
cursor: pointer; | |
height: var(--header-height); | |
padding: 0; | |
position: relative; | |
transition: background-color 0.3s; | |
width: var(--header-height); | |
&.focus-visible { | |
background-color: var(--gray-color-primary); | |
} | |
@media (hover) { | |
&:hover { | |
background-color: var(--gray-color-primary); | |
} | |
} | |
} | |
.menu-button__icon { | |
background-color: var(--white-color-primary); | |
bottom: 0; | |
height: 2px; | |
left: 0; | |
margin: auto; | |
position: absolute; | |
right: 0; | |
top: 0; | |
width: 18px; | |
&::before, | |
&::after { | |
background-color: #f7f7f7; | |
content: ""; | |
display: inline-block; | |
height: 100%; | |
left: 0; | |
position: absolute; | |
top: 0; | |
transition: transform 0.3s; | |
width: 100%; | |
} | |
&.-open { | |
&::before { | |
transform: translateY(-6px); | |
} | |
&::after { | |
transform: translateY(6px); | |
} | |
} | |
&.-close { | |
background-color: transparent; | |
&::before { | |
background-color: #f7f7f7; | |
transform: translateY(0) rotate(45deg); | |
} | |
&::after { | |
background-color: #f7f7f7; | |
transform: translateY(0) rotate(-45deg); | |
} | |
} | |
} | |
.drawer-menu { | |
height: 100%; | |
left: 0; | |
overflow: hidden; | |
position: fixed; | |
top: 0; | |
width: 100%; | |
z-index: z-index(drawer-menu); | |
} | |
.drawer-menu__overlay { | |
animation-duration: var(--menu-toggle-duration); | |
animation-fill-mode: forwards; | |
background-color: rgba(0, 0, 0, 0.1); | |
height: 100%; | |
left: 0; | |
position: absolute; | |
top: 0; | |
width: 100%; | |
z-index: -1; | |
.drawer-menu:not([inert]) & { | |
animation-name: menu-overlay-appeared; | |
} | |
.drawer-menu[inert] & { | |
animation-name: menu-overlay-leaved; | |
} | |
} | |
@keyframes menu-overlay-appeared { | |
0% { | |
opacity: 0; | |
} | |
100% { | |
opacity: 1; | |
} | |
} | |
@keyframes menu-overlay-leaved { | |
0% { | |
opacity: 1; | |
} | |
100% { | |
opacity: 0; | |
} | |
} | |
.drawer-menu__container { | |
animation-duration: var(--menu-toggle-duration); | |
animation-fill-mode: forwards; | |
background-color: var(--white-color-primary); | |
border-left: var(--gray-color-secondary) 1px solid; | |
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1); | |
display: flex; | |
flex-direction: column; | |
height: 100%; | |
max-width: 440px; | |
min-width: 280px; | |
overflow: hidden; | |
position: absolute; | |
right: 0; | |
top: 0; | |
width: 80%; | |
.drawer-menu[inert] & { | |
animation-name: menu-container-leaved; | |
} | |
.drawer-menu:not([inert]) & { | |
animation-name: menu-container-appeared; | |
} | |
} | |
@keyframes menu-container-appeared { | |
0% { | |
transform: translateX(100%); | |
} | |
100% { | |
transform: translateX(0); | |
} | |
} | |
@keyframes menu-container-leaved { | |
0% { | |
transform: translateX(0); | |
} | |
100% { | |
transform: translateX(100%); | |
} | |
} | |
.drawer-menu__list { | |
flex: 1; | |
list-style: none; | |
margin: 0; | |
overflow-y: auto; | |
padding: 0; | |
} | |
.drawer-menu__item { | |
border-bottom: var(--gray-color-secondary) 1px dashed; | |
} | |
.drawer-menu__link { | |
align-items: center; | |
color: inherit; | |
display: block; | |
justify-content: space-between; | |
letter-spacing: 0.01em; | |
padding: 1em 2.5em 1em 2em; | |
position: relative; | |
text-decoration: none; | |
transition: background-color 0.3s; | |
&::after { | |
border-right: 2px solid var(--gray-color-tertiary); | |
border-top: 2px solid var(--gray-color-tertiary); | |
bottom: 0; | |
content: ""; | |
display: inline-block; | |
height: max(8px, 0.5em); | |
margin: auto 0; | |
position: absolute; | |
right: 24px; | |
top: 0; | |
transform: rotate(45deg); | |
width: max(8px, 0.5em); | |
} | |
&:focus { | |
background-color: rgba(0, 0, 0, 0.05); | |
} | |
&[aria-current] { | |
background-color: rgba(0, 0, 0, 0.1); | |
&::after { | |
content: none; | |
} | |
} | |
@media (hover) { | |
&:hover { | |
background-color: rgba(0, 0, 0, 0.05); | |
} | |
} | |
} | |
.drawer-menu__en-label { | |
display: block; | |
font-family: "Montserrat", sans-serif; | |
font-weight: 500; | |
text-transform: uppercase; | |
} | |
.drawer-menu__jp-label { | |
color: var(--gray-color-tertiary); | |
display: block; | |
font-size: max(10px, 0.75em); | |
} | |
.drawer-menu__close-button { | |
border-bottom: var(--gray-color-secondary) 1px solid; | |
order: -1; | |
text-align: right; | |
} | |
.global-header { | |
background-color: var(--white-color-primary); | |
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); | |
height: var(--header-height); | |
position: sticky; | |
top: 0; | |
z-index: z-index(global-header); | |
} | |
.global-header__container { | |
align-items: center; | |
display: flex; | |
justify-content: space-between; | |
&::before { | |
content: ""; | |
display: inline-block; | |
width: var(--header-height); | |
} | |
} | |
.logo { | |
font-family: "Lobster", cursive; | |
font-size: 20px; // 拡大しないようにあえてのpx指定 | |
white-space: nowrap; | |
} | |
.main-content { | |
overflow-x: hidden; | |
padding: 4.5em 5%; | |
} | |
.article { | |
font-size: 1rem; | |
margin: auto; | |
max-width: 1024px; | |
} | |
.article__title { | |
font-size: 1.778em; | |
font-weight: normal; | |
margin: 0; | |
} | |
.article__sentence { | |
line-height: 1.75; | |
margin-top: 1.5em; | |
& > p + p { | |
margin-top: 1em; | |
} | |
} | |
.article__section { | |
margin-top: 2em; | |
} | |
.article__subtitle { | |
border-bottom: 2px solid var(--gray-color-secondary); | |
font-size: 1.333em; | |
font-weight: normal; | |
padding: 0.2em 0; | |
} | |
.article__list { | |
display: table; | |
margin-top: 1.5em; | |
padding: 0; | |
} | |
.article__list-item { | |
display: flex; | |
& + & { | |
margin-top: 0.5em; | |
} | |
&::before { | |
background-position: center center; | |
background-repeat: no-repeat; | |
background-size: contain; | |
content: ""; | |
display: inline-block; | |
flex-shrink: 0; | |
height: 1.5em; | |
margin-right: 0.5em; | |
vertical-align: middle; | |
width: 1.5em; | |
} | |
&.-checked { | |
&::before { | |
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%3E%20%3Cpath%20d%3D%22M9.86%2018a1%201%200%200%201-.73-.32l-4.86-5.17a1%201%200%201%201%201.46-1.37l4.12%204.39%208.41-9.2a1%201%200%201%201%201.48%201.34l-9.14%2010a1%201%200%200%201-.73.33z%22%20fill%3D%22%2344c08a%22%2F%3E%3C%2Fsvg%3E"); | |
} | |
} | |
&.-not-checked { | |
&::before { | |
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%3E%20%3Cpath%20d%3D%22M13.41%2012l4.3-4.29a1%201%200%201%200-1.42-1.42L12%2010.59l-4.29-4.3a1%201%200%200%200-1.42%201.42l4.3%204.29-4.3%204.29a1%201%200%200%200%200%201.42%201%201%200%200%200%201.42%200l4.29-4.3%204.29%204.3a1%201%200%200%200%201.42%200%201%201%200%200%200%200-1.42z%22%20fill%3D%22%23f72f47%22%20%2F%3E%3C%2Fsvg%3E"); | |
} | |
} | |
&.-link { | |
&::before { | |
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224px%22%20height%3D%2224px%22%20viewBox%3D%220%200%2024%2024%22%20stroke%3D%22%23676f79%22%20stroke-width%3D%221%22%20stroke-linecap%3D%22square%22%20stroke-linejoin%3D%22miter%22%20fill%3D%22none%22%3E%20%3Crect%20width%3D%2213%22%20height%3D%2213%22%20x%3D%223%22%20y%3D%223%22%20%2F%3E%20%3Cpolyline%20points%3D%2216%208%2021%208%2021%2021%208%2021%208%2016%22%20%2F%3E%3C%2Fsvg%3E"); | |
} | |
} | |
} | |
.article__link { | |
color: var(--active-color); | |
@media (hover) { | |
&:hover { | |
opacity: 0.8; | |
text-decoration: none; | |
} | |
} | |
} | |
.js-focus-visible :focus:not(.focus-visible) { | |
outline: 0; | |
} | |
[inert] { | |
cursor: default; | |
pointer-events: none; | |
} | |
[inert], | |
[inert] * { | |
-webkit-user-select: none; | |
-moz-user-select: none; | |
-ms-user-select: none; | |
user-select: none; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<link href="https://fonts.googleapis.com/css2?family=Lobster&family=Montserrat:wght@500&display=swap" rel="stylesheet" /> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment