🐭
[CSS] ホバーした要素以外の兄弟要素の透過率(opacity)を下げる方法
背景
「ある要素にマウスオーバーした際、その兄弟要素の透明度を下げて強調表示する」といったデザインがjQuery全盛期にはよく見られた。
// イメージ
$("a")
.on("mouseenter", function () {
$(this).siblings("a").css("opacity", 0.8);
})
.on("mouseleave", function () {
$(this).siblings("a").css("opacity", "");
});
デザインの流行り廃りやjQueryでの実装もなくなってきて、こういったデザインはあまり見られなくなった。
JavaScript
これをJavaScript(TypeScript)で実装すると結構たいへん。
document.querySelectorAll("a").forEach((anchor) => {
anchor.addEventListener("mouseenter", function () {
const parent = anchor.parentElement;
if (!parent) return;
const siblings = Array.from(parent.children).filter(
(el): el is HTMLAnchorElement => el.tagName === "A" && el !== anchor,
);
siblings.forEach((sib) => {
sib.style.opacity = "0.8";
});
});
anchor.addEventListener("mouseleave", function () {
const parent = anchor.parentElement;
if (!parent) return;
const siblings = Array.from(parent.children).filter(
(el): el is HTMLAnchorElement => el.tagName === "A" && el !== anchor,
);
siblings.forEach((sib) => {
sib.style.opacity = "";
});
});
});
CSSで実装する
これまでCSSだけでは実現が難しかったが、:has()
の登場で、:not()
と組み合わせて以下のような形で実装が出来る。
a {
transition: opacity 0.2s;
}
:has(> a:hover) > a:not(:hover) {
opacity: 0.2;
}
/* aではなくクラス名でもOK */
直下のa
タグからホバーされていないa
だけがopacity: 0.2
となる。ホバー中のa
タグはopacity: 1
のままである。
:has()
を使うことで「ホバーされている要素が存在する親要素」を特定することが出来、その中の「ホバーされていない兄弟a
要素」に限定してスタイルを適用できる。
現在は兄弟要素のフェードアウト効果は、:has()
と:not(:hover)
を組み合わせてCSSのみで実装できる。
Discussion