サイトロゴ

Enjoy Creating
Web & Mobile Apps

MENU BOX
WEB
MOBILE
OPEN

ホーム

 > 

 > 

【CSS】新しい擬似クラス:has( )の使い方と有効活用法

【CSS】新しい擬似クラス:has( )の使い方と有効活用法

この記事にはプロモーションが含まれています。

CSSの擬似クラスは色々ありますが、今回はその中でも最近(2022年10月)主要なブラウザが対応するようになった擬似クラス:has( )を紹介します。

擬似クラスには、特定の条件下でスタイルの変更を調整するもの(:hoverや:activeなど)、セレクタ指定に条件指定を加えるもの(:first-childや:not( )など)がありますが、:has( )は後者の分類になります。

つまり、:has( )はセレクタの指定を楽に、便利にしてくれるものということになります。

擬似クラスの種類の例
擬似クラスの種類(一部)

:has( )は、2022年前半頃まではブラウザが未対応だったので使いたくても使えない…という状況でしたが、ブラウザの対応が広がってきたことでだいぶ使いやすくなりました。

この記事では擬似クラス:has()の基本的な使い方と、実際の利用シーンなどをご紹介します!

– 目次 –

:has( )のブラウザ対応状況

冒頭で“主要なブラウザが:has( )に対応するようになった”と述べましたが、2022年10月現在、まだ全てのブラウザがサポートしているわけではありません。

2023/12 追記:FireFox(PC)が :has をサポートしたことにより、主要なブラウザはほぼサポートしていると言える状況になりました!

将来的には全てのブラウザでサポートされ、各ブラウザの対応状況を気にしなくても良い状況になると思いますが、現時点で導入する際はブラウザの対応状況のチェックが必要となります。

ということで、まずは2022年10月2023年12月現在の:has( )の対応状況を確認してみましょう。
なお、下の表は同時点での各ブラウザの最新バージョンのみで比較した表です。

スマホでは表を横にスクロールできます。

PC向けブラウザ スマホ向けブラウザ(Android/iOS)
Chrome
Safari
Firefox ◯(New) ×
Opera ◯(New)
Edge

参考:Can I Use

上の表の通り、利用者の多いChromeとSafari(iOS)でサポートされている点は大きいですね。

ちなみに日本の場合、PCではChromeEdgeのシェアが大きく、両者を合わせて約83%のシェアとなっています。

スマホではChromeSafariのシェアが大きく、両者を合わせてなんと約94%のシェアという状況です。

[参考記事]:Shift Asia 【2022年6月】日本とグローバルのWEBブラウザシェアランキング(PC・モバイル)

上記のデータは2022年6月時点のものなので信用して良い数値だと思います。

PCでもスマホでも、8割以上の場合において問題なく:has( )を使える状況というのはWeb製作者にとって心強いですね。

ただし、PCでは:has( )未対応のFirefoxのシェアもそれなりにあります。(7.1%)
なので、全てのユーザーに確実に:has( )を使った調整が有効になるようにしたい場合は、もう少し待ってみると良いでしょう。

2023/12 追記:繰り返しますが、FireFox(PC)が :has のサポートを完了させたので、Firefoxでも問題なく使えるようになりました!

表には入れませんでしたが、当然のごとくIEは非対応です。
特別な事情がない限り…いえ、事情があったとしても、IEにこだわり続けるのはやめた方が良いでしょう。時代遅れです。

    POINT!
  1. ・:has( )は2022年10月現在、主要なブラウザは既にサポートしている!
  2. ・ブラウザのシェア的に、PC/スマホどちらでも8割以上をカバー可能!
  3. ただしFirefoxが未対応な点には少し注意が必要かも 2023年、Firefoxも無事に対応!

:has( )の基本的な使い方

この章では、:has( )の基本的な使い方について解説します。

:has( )はその名の通り、特定の要素やid、class等を含む(=子孫要素に持つ)親要素をセレクタ指定にできる…というものです。

例えば、<span>要素が含まれる<p>要素のテキストカラーをとし、<span>要素を含まない<p>要素のテキストカラーを黒(デフォルト)にしたい場合は以下のようなコードになります。

HTML

<p>This text-color is <span>red</span>.</p>
<p>This text-color is black</p>

CSS

p:has(span) {
	color: red;
}

*表示結果*

This text-color is red.

This text-color is black.

表示結果のように、<span>要素でマークアップした”red”の部分だけでなく、<p>(親)要素全体のテキストカラーが赤になります。

has( )の( )かっこの中は条件を指定するものであり、適用させたい要素やclassを指定するものではないということです。

もし<p>要素の中の<span>要素だけテキストを赤くしたければ、これまで通り次のようなセレクタ指定をすれば良いですからね。

CSS

p span {
	color: red;
}

また、基本的な使い方としては特定の要素・class等を持つ親要素をセレクタ指定するためのものですが、+プラスと組み合わせることで、特定の要素が後続する兄弟要素を指定することも可能です。

HTML

<h2>タイトル</h2>
<p>サンプルテキスト</p>

<h2>タイトル2</h2>
<h3>サブタイトル2</h3>
<p>サンプルテキスト2</p>

CSS

/*直後にp要素が続くh2要素に対する調整*/
h2:has(+p) {
	color: red;
}

*表示結果*

タイトル

サンプルテキスト

タイトル2

サブタイトル2

サンプルテキスト2

特定の条件を( )の中に指定するという意味では、擬似クラス:notと考え方が似ています。
:not( )の使い方も合わせて知りたい方は、下のリンクよりどうぞ!

    POINT!
  1. ・:has( )で、特定の要素やclassを含む親要素を指定できる!
  2. ・:has( )のかっこの中に要素やclassの条件を指定する!
  3. ・+(プラス)と併用することで、特定の兄弟要素を指定することも可能!

:has( )の有効活用その1

:has( )の基本を押さえたら、次はどのような場面で:has( )を使用すると便利なのかを考えてみましょう。

:has( )の活用例としてここでは、画像リンクにのみマウスオーバーアクションを設定するということをしてみたいと思います。

Webページのリンクは通常、テキスト(見た目をボタンのように調整したものを含む)にリンクを設定したテキストリンクと、画像にリンクを設定した画像リンクに分けられます。

そしてテキスト(ボタン)リンクと画像リンクでは、マウスカーソルが乗っかった時の変化を使い分けたい場合が多いですよね。

以下のようなCSS調整をしてしまうと、全ての<a>要素に同じマウスオーバー効果が出てしまうことは言わずもがなでしょう。

CSS

/*全てのa要素に同じマウスオーバー効果が出てしまう*/
a:hover {
	opacity: .7;
}

そこで、:has(img)という条件を加えてみるとどうなるでしょうか?

<img>要素を子要素に持つ<a>要素に対してのみ、マウスオーバー効果を指定することができるようになります。

CSS

/*img要素を子要素に持つa要素にのみ有効*/
a:has(img):hover {
	opacity: .7;
}

*表示結果*(動画サイズ:約8KB)

このように指定することで、テキストリンクにマウスがホバーした際は要素が透過することなく、画像リンクにマウスがホバーした場合にのみ要素を透過させることができます。

画像リンクにいちいち専用のclassを付けなくても良いのでとても便利で楽ちんです。
<button>要素など、<img>要素を含まないリンクボタンにも影響を与えないので、安心して指定することができるのも良いですね。

    POINT!
  1. ・:has( )は、テキストリンクと画像リンクでマウスホバー時の挙動を変えたい時に便利!
  2. ・たとえばimg要素(画像)を含むa要素にのみ指定したければ、a:has(img)と指定すればOK!
  3. ・:has( )で限定することで、img要素を含まないa要素には影響を与えないので安心!

:has( )の有効活用その2

:has( )のかっこの中の指定は要素やclassによる指定だけでなく、他の疑似クラスによる指定も可能となっています。

これを利用して、グリッドレイアウトのカラム数をグリッドアイテムの個数によって変化させるといった調整も簡単にできます。

例として、<li>(リスト)要素をグリッドレイアウトにした上でカラム数を3にしたものを用意してみます。

HTML

<ul>
	<li>リスト</li>
	<li>リスト</li>
	<li>リスト</li>
	<li>リスト</li>
	<li>リスト</li>
	<li>リスト</li>
</ul>

CSS

ul {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 20px;
}
li {
	background-color: white;
	padding: 10px;
	border: solid black 2px;
	list-style: none;
}

*表示結果*

  • リスト
  • リスト
  • リスト
  • リスト
  • リスト
  • リスト

ここに<li>要素を1つ追加すると、当然ですが3行目ができて<li>要素が1つ孤立したような形になります。(下の表示結果参照)

*表示結果*

  • リスト
  • リスト
  • リスト
  • リスト
  • リスト
  • リスト
  • リスト

リスト項目が少ない場合は良いのですが、リスト項目が多くなってくるともう1列増やしたいということもあるかと思います。

そこで:has( ):nth-child( )を組み合わせて、リスト項目が7個以上になったら列数を1つ増やすという調整をしてみたいと思います。

グリッドのカラム数を指定している<ul>要素に対し、:has( )のかっこの中に7番目のリストが存在するなら → li:nth-child(7)という条件を加えます。

HTML

<ul>
	<li>リスト</li>
	<li>リスト</li>
	<li>リスト</li>
	<li>リスト</li>
	<li>リスト</li>
	<li>リスト</li>
	<li>リスト</li>
</ul>

CSS

ul {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 20px;
}
li {
	background-color: white;
	padding: 10px;
	border: solid black 2px;
	list-style: none;
}
ul:has(li:nth-child(7)) {
	grid-template-columns: repeat(4, 1fr);
}

*表示結果*

  • リスト
  • リスト
  • リスト
  • リスト
  • リスト
  • リスト
  • リスト

上の表示結果は実際に:has( )を使って調整しているので、非対応のブラウザでは違った(4列になっていない)表示結果になっているかと思います。
それ以外のChromeやSafariなどでは、問題なく4列表示になっていることが確認できます。

テキストリンクor画像リンクの時と同様に、リストの数によってわざわざclassを追加したりする必要がない…という点がとても便利です。

逆に言えば:has( )を使わなくともclassを追加したり使い分けたりすることで対応は可能ですが、作業効率の面を考えると、今後新しくWebサイトを制作する際は積極的に:has( )の使用を検討したいですね。

    POINT!
  1. ・グリッドアイテムの数によってカラム数を変えたい場合も:has( )を使うと簡単!
  2. ・:has( )のかっこの中には他の疑似クラスによる指定も可能!
  3. ・今後ブラウザのサポートが完全に広がったら、積極的に:has( )を使ったコーディングを検討してみよう!
– 注目の人気記事 –

今回の動画で紹介したコード!

今回の解説動画で使用したコードです。学習用としてご自由にコピペしてお使い下さい。(※スクロールできます)

HTML・CSS

<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>has()</title>
	<style>
		body {
			height: 100vh;
			display: grid;
			justify-content: center;
			align-items: center;
		}
	</style>
</head>

<body>
	<style>
		p:has(span) {
			color: red;
		}
		div:has(.red_color) {
			color: red;
		}
		
		h2:has(+p) {
			color: green;
		}
	</style>
	
	<div>
		<p>This text-color is <span>red</span>.</p>
		<p>This text-color is black</p>
	</div>
	
	<div>
		<p>This text-color is <span class="red_color">red</span>.</p>
		<p>This text-color is black</p>
	</div>
	
	<div>
		<h2>タイトル</h2>
		<p>サンプルテキスト</p>
		<hr>
		<h2>タイトル</h2>
		<h3>サブタイトル</h3>
		<p>サンプルテキスト</p>
	</div>
</body>
</html>

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>has-img</title>
	<style>
		a {
			display: block;
			margin: 150px;
			transition: .2s;
		}
		a:has(img):hover {
			opacity: .5;
		}
	</style>
</head>

<body>
	<a href="#">テキストリンク</a>
	<a href="#">
		<img src="サムネイル画像.png" width="200" height="113">
	</a>
</body>
</html>

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>has-list</title>
	<style>
		body {
			height: 100vh;
			display: grid;
			justify-content: center;
			align-items: center;
		}
		
		li {
			background-color: white;
			padding: 10px;
			border: solid black 2px;
			list-style: none;
		}
		ul {
			width: 90vw;
			padding-inline-start: 0;
			display: grid;
			grid-template-columns: repeat(3, 1fr);
			gap: 20px;
		}
		ul:has(li:nth-child(7)) {
			grid-template-columns: repeat(4, 1fr);
		}
	</style>
</head>

<body>
	<ul>
		<li>リスト</li>
		<li>リスト</li>
		<li>リスト</li>
		<li>リスト</li>
		<li>リスト</li>
		<li>リスト</li>
		<li>リスト</li>
		<li>リスト</li>
	</ul>
</body>
</html>

« »

カテゴリーリンク

著者について- author profile -

ROYDOプロフィール写真
Michihiro

モバイルアプリ(iOS・Android)ディベロッパー&デザイナー

これまでに、可読性の高いカラーパターンを自動で生成するアプリや、『第3火曜日』といった形式で通知をスケジュールできるアプリなどを制作。

サブでWebデザイン・フロントエンドエンジニアとしても活動しています。

📝ツール・言語:JavaScript/React Native/Kotlin/Android Studio/Swift/SwiftUI

🎓資格:応用情報技術者/基本情報技術者/ウェブデザイン技能検定3級

Twitterアイコン Instagramアイコン