CSSで条件によってデザインを変える方法【初心者向け】

はい、承知いたしました。
CSSで条件によってデザインを変える方法について、初心者向けの詳細な記事(約5000語)を記述します。


CSSで条件によってデザインを変える方法【初心者向け】

Webサイトのデザインは、常に同じ見た目であるとは限りません。パソコンで見たとき、スマートフォンで見たとき、あるいはマウスを乗せたとき、入力フォームに文字を入力しているときなど、様々な「条件」に応じてデザインが変わることがあります。

このような「条件によってデザインを変える」ことは、現代のWebサイト制作において非常に重要です。

  • レスポンシブデザイン: 異なる画面サイズのデバイスでWebサイトを見やすく、使いやすくするために必須です。
  • インタラクション: ボタンにマウスを乗せたり、リンクをクリックしたりしたときに視覚的なフィードバックを与えることで、ユーザー体験が向上します。
  • アクセシビリティ: キーボード操作でのフォーカス状態を分かりやすく表示するなど、特定の状況にあるユーザーへの配慮になります。
  • 動的な表現: ユーザーの操作やページの特定の状態に応じて、よりリッチな表現が可能になります。

CSSには、このような「条件」を指定してスタイルを適用するための様々な方法が用意されています。この記事では、初心者の方でもこれらの技術を理解し、使いこなせるようになることを目指します。

CSSでの基本的なスタイリング(セレクタ、プロパティ、値など)については理解している前提で解説を進めますが、必要に応じて関連用語も説明しますので安心してください。約5000語かけてじっくり解説していきますので、ぜひ最後までお読みいただき、ご自身のWebサイト制作に役立ててください。

条件によってデザインを変えるとは具体的にどういうこと?

「条件によってデザインを変える」と言われても、ピンとこないかもしれません。いくつか具体的な例を見てみましょう。

  1. 画面サイズによる変化

    • パソコンの広い画面では、コンテンツが横に並んだ2カラムや3カラムのレイアウトになっている。
    • スマートフォンの狭い画面では、コンテンツが縦一列に並んだ1カラムのレイアウトに変わる。
    • 画面幅が広いほど文字サイズを大きく、狭いほど文字サイズを小さくする。
    • 特定の画像や要素を、スマホでは非表示にし、PCでのみ表示する。
  2. ユーザーの操作による変化

    • ボタンにマウスカーソルを乗せると、ボタンの背景色が変わったり、影がついたりする。
    • リンクをクリックするときの「押している」間に、ボタンの色が少し濃くなる。
    • 入力フォームのテキストボックスをクリックして、文字を入力できる状態(フォーカス状態)になったときに、枠線が青く光る。
    • チェックボックスにチェックを入れると、関連するテキストの色が変わる。
  3. 要素の状態や構造による変化

    • すでにアクセスしたことがあるリンクの色を、まだアクセスしたことがないリンクの色と変える。
    • リスト形式の項目で、最初の項目だけ文字を太くする。
    • テーブル(表)で、奇数行と偶数行で背景色を分けて、見やすくする(ゼブラストライプ)。
    • 入力必須のフォームフィールドで、まだ入力されていない場合に赤い枠線を表示する。
  4. HTML属性による変化

    • 特定の種類の入力フィールド(例:パスワード入力欄)だけ、独自のスタイルを適用する。
    • 特定のデータ属性 (data-...) が付いている要素にスタイルを適用する。

これらはほんの一例ですが、共通しているのは「特定の条件が満たされたときに、あらかじめ定めたCSSスタイルが適用される」という点です。

これらの条件を指定する方法はいくつかあり、それぞれ得意な「条件」の種類が異なります。次に、主な方法を簡単に見ていきましょう。

条件付きスタイルのための主なCSS機能

CSSを使って条件によってデザインを変えるための主な方法には、以下のものがあります。

  1. メディアクエリ (Media Queries):
    • 条件: デバイスの特性(画面サイズ、解像度、向きなど)。
    • 得意なこと: レスポンシブデザインの実装。デバイスによってレイアウトや基本的なスタイルを切り替える。
  2. 疑似クラス (Pseudo-classes):
    • 条件: 要素の「状態」(ホバー、アクティブ、フォーカス、訪問済み、チェック済み、有効/無効など)や、「構造上の位置」(最初の子、最後の子、N番目の子など)。
    • 得意なこと: ユーザーインタラクションに対する視覚的フィードバック、リストやテーブルなどの特定の要素へのスタイリング。
  3. 疑似要素 (Pseudo-elements):
    • 条件: 要素の「一部」(最初の行、最初の文字)や、「存在しない要素」(要素の前後)。
    • 得意なこと: 要素の前後に装飾やコンテンツを追加、テキストの特定部分のスタイリング。
  4. 属性セレクタ (Attribute Selectors):
    • 条件: 要素が持つHTML属性の名前やその値。
    • 得意なこと: 特定の属性を持つ要素や、属性値に応じたスタイリング。フォーム要素やリンクなどで便利。
  5. 関係セレクタ (Combinators):
    • 条件: 要素同士の「位置関係」(子孫、直下の子、隣接する兄弟、後続の兄弟)。
    • 得意なこと: 特定の構造の中にある要素へのスタイリング。
  6. CSS変数 (CSS Custom Properties):
    • 条件: (直接的な条件ではないが)変数として定義した値。他の方法と組み合わせることで、デザインの値を動的に変更する。
    • 得意なこと: デザインの共通値管理、テーマ切り替え、JavaScriptとの連携による動的なスタイリング。
  7. JavaScriptとの連携:
    • 条件: より複雑なロジック、ユーザー操作、サーバーからのデータなど、CSSだけでは判断できない条件。
    • 得意なこと: ユーザー操作に応じた要素の表示/非表示、アニメーションの制御、動的なコンテンツの状態変化に応じたスタイリング。

これらの方法は単独で使うだけでなく、組み合わせて使うことで、より複雑で洗練された条件付きスタイリングが可能になります。

それでは、それぞれの方法について、具体的な使い方をコード例とともに詳しく見ていきましょう。

方法1: メディアクエリ (Media Queries)

メディアクエリは、Webサイトを様々なデバイス(パソコン、タブレット、スマートフォンなど)で最適に表示するための「レスポンシブデザイン」に欠かせない技術です。画面のサイズや解像度といったデバイスの特性を条件として、適用するCSSスタイルを切り替えることができます。

なぜメディアクエリが必要?

昔のWebサイトは、パソコンの画面サイズを想定して作られることがほとんどでした。しかし、スマートフォンの普及により、小さな画面でWebサイトを見る人が圧倒的に増えました。さらにタブレットや様々なサイズのディスプレイが登場し、一つのデザインですべてに対応することは不可能になりました。

メディアクエリを使うことで、「画面幅が〇〇ピクセル以下の場合は、このスタイルを適用する」「画面幅が△△ピクセル以上の場合は、別のスタイルを適用する」といったように、デバイスの特性に応じて柔軟にデザインを調整できます。

基本的な書き方 (@mediaルール)

メディアクエリは、@media というルールを使って定義します。基本的な構文は以下のようになります。

css
@media メディアタイプ and (条件) {
/* 条件を満たしたときに適用したいCSSスタイル */
セレクタ {
プロパティ: 値;
/* ... */
}
}

  • メディアタイプ: スタイルを適用したいメディアの種類を指定します。よく使われるのは screen (画面表示用) です。他にも print (印刷用)、all (すべてのメディア) などがあります。通常は screen を指定することが多いです。
  • 条件: メディアタイプに加えて、さらに細かい条件を指定します。最もよく使われるのは、画面の幅に関する条件です。

よく使う条件 (min-width, max-width, orientation)

画面の幅に関する条件は、主に min-widthmax-width を使います。

  • (min-width: 〇〇px): 画面の幅が〇〇ピクセル以上の場合にスタイルを適用します。
  • (max-width: △△px): 画面の幅が△△ピクセル以下の場合にスタイルを適用します。

例:画面幅が768ピクセル以上の場合に適用されるスタイル

css
@media screen and (min-width: 768px) {
.container {
width: 960px; /* コンテナの幅を広くする */
margin: 0 auto; /* 中央寄せにする */
}
nav ul {
display: flex; /* ナビゲーションリストを横並びにする */
justify-content: center;
}
nav li {
margin: 0 10px;
}
}

この例では、「画面タイプがscreenであり、かつ画面幅が768px以上」という条件を満たした場合に、.containernav ul, nav li のスタイルが変更されます。

逆に、画面幅が767ピクセル以下(つまり768ピクセル未満)の場合に適用されるスタイルは、max-widthを使います。

css
/* 767px以下の画面幅に適用 */
@media screen and (max-width: 767px) {
.container {
width: 100%; /* 幅をいっぱいに使う */
padding: 0 15px; /* 左右に余白 */
}
nav ul {
display: block; /* ナビゲーションリストを縦並びにする */
}
nav li {
margin: 10px 0;
text-align: center;
}
}

この二つのメディアクエリを組み合わせることで、画面幅を境にしてスタイルを切り替えることができます。

他にも、以下のような条件があります。

  • (orientation: portrait): 画面が縦向きの場合
  • (orientation: landscape): 画面が横向きの場合
  • (min-resolution: 〇dpi), (max-resolution: △dpi): 画面の解像度

複数の条件を組み合わせることも可能です。

css
/* 画面幅が768px以上 活 画面が横向き の場合に適用 */
@media screen and (min-width: 768px) and (orientation: landscape) {
/* ... */
}

ブレークポイントとは

メディアクエリでスタイルが切り替わる画面幅のことを「ブレークポイント (Breakpoint)」と呼びます。どの幅でブレークポイントを設定するかは、デザインやコンテンツに合わせて決定します。一般的なブレークポイントの例としては、以下のようなものがあります。

  • スマートフォン向け (max-width: 599px など)
  • タブレット向け (min-width: 600px and max-width: 1023px など)
  • PC向け (min-width: 1024px など)

ただし、これはあくまで一般的な例であり、特定のデバイスに合わせるのではなく、コンテンツが崩れるポイントや、レイアウトを切り替えるのが適切だと感じるポイントでブレークポイントを設定するのが良い方法とされています。

モバイルファーストとデスクトップファースト

レスポンシブデザインのCSSを記述するアプローチとして、「モバイルファースト」と「デスクトップファースト」があります。

  • モバイルファースト: まず、最もシンプルなモバイル向けのスタイルを記述します。その後、min-width を使ったメディアクエリで、より広い画面(タブレット、PC)向けのスタイルを追加・上書きしていきます。
    “`css
    / モバイル向け(デフォルト) /
    body { font-size: 16px; }
    .container { width: 100%; }

    / タブレット以上 /
    @media (min-width: 768px) {
    body { font-size: 18px; } / フォントサイズを大きく /
    }

    / PC以上 /
    @media (min-width: 1024px) {
    .container { width: 960px; } / コンテナ幅を固定 /
    }
    * **デスクトップファースト**: まず、デスクトップ向けのスタイルを記述します。その後、`max-width` を使ったメディアクエリで、より狭い画面(タブレット、スマホ)向けのスタイルを**変更・上書き**していきます。css
    / PC向け(デフォルト) /
    body { font-size: 18px; }
    .container { width: 960px; }

    / タブレット以下 /
    @media (max-width: 1023px) {
    body { font-size: 18px; } / 変更なし、あるいは少し小さく /
    }

    / スマホ以下 /
    @media (max-width: 767px) {
    body { font-size: 16px; } / フォントサイズを小さく /
    .container { width: 100%; } / コンテナ幅をいっぱいに /
    }
    “`

モバイルファーストは、デフォルトのスタイルが最もシンプルであるため、CSSのコード量が減りやすく、読み込み速度の観点でも有利とされています。初心者の方にもモバイルファーストのアプローチがおすすめです。

具体的なコード例 (レイアウト変更、フォントサイズ調整)

HTML構造の例:

“`html

記事タイトル

本文テキスト…

“`

モバイルファーストでのCSS例:

“`css
/ ——————– /
/ デフォルト(モバイル向け) /
/ ——————– /
body {
font-family: sans-serif;
margin: 0;
padding: 0;
font-size: 16px; / モバイルでの基本フォントサイズ /
}

.container {
width: 100%; / モバイルでは幅いっぱい /
padding: 0 15px; / 左右に余白 /
box-sizing: border-box; / paddingを幅に含める /
}

main {
margin-bottom: 20px; / mainの下に余白 /
}

aside {
/ asideはmainの下に配置 /
}

/ ——————– /
/ タブレット以上向けのスタイル /
/ ——————– /
@media screen and (min-width: 768px) {
body {
font-size: 17px; / 少しフォントサイズを大きく /
}

.container {
width: 740px; / タブレット向けの幅 /
margin: 0 auto; / 中央寄せ /
display: flex; / mainとasideを横並びに /
gap: 30px; / 要素間の隙間 /
}

main {
flex: 2; / mainはasideより幅広に /
margin-bottom: 0; / 不要になる余白を削除 /
}

aside {
flex: 1; / asideはmainより幅狭に /
}
}

/ ——————– /
/ PC以上向けのスタイル /
/ ——————– /
@media screen and (min-width: 1024px) {
body {
font-size: 18px; / さらにフォントサイズを大きく /
}

.container {
width: 980px; / PC向けの幅 /
}

/ mainとasideのflex比率はそのまま /
}
“`

このように、メディアクエリを使うことで、画面サイズに応じてレイアウト(display: flexwidth)や基本的なスタイル(font-sizepaddingmargin)を柔軟に変化させることができます。

応用例 (特定の解像度、印刷用スタイル)

  • 特定の解像度への対応: min-resolutionmax-resolution を使って、Retinaディスプレイのような高解像度デバイスに最適化された画像を表示したり、スタイルを調整したりできます。
  • 印刷用スタイル: @media print を使うと、Webページを印刷する際に適用されるスタイルを定義できます。不要な要素(ナビゲーション、広告など)を非表示にしたり、文字サイズを調整したり、背景画像を削除したりすることで、印刷に適したデザインにできます。

css
@media print {
header, footer, aside, nav, .ad {
display: none; /* 不要な要素を非表示 */
}
body {
font-size: 12pt; /* 印刷に適したフォントサイズ */
color: black !important; /* 強制的に黒文字に */
margin: 0;
}
a {
text-decoration: none; /* リンクの下線を削除 */
color: black;
}
a[href]::after { /* リンクのURLを括弧書きで追記 */
content: " (" attr(href) ")";
}
}

attr(href) は、要素の href 属性の値を取得して content プロパティに表示するための関数です。

注意点 (ブレークポイントの決め方、複雑化)

  • ブレークポイントの決め方: 特定のデバイスに合わせるのではなく、コンテンツやレイアウトが崩れるポイント、デザインの切り替えが必要になるポイントで設定しましょう。一般的なブレークポイントを参考にしつつ、実際のコンテンツを表示しながら調整するのが現実的です。
  • 複雑化: メディアクエリを多用しすぎると、CSSファイルが肥大化し、管理が難しくなることがあります。モバイルファーストのアプローチを心がけたり、CSSプリプロセッサー(Sassなど)でブレークポイントをまとめて管理したりすると、コードの保守性が向上します。

メディアクエリは、Webサイトが多様なデバイスに対応するための基盤となる技術です。まずは画面幅に応じたスタイルの切り替えからマスターしましょう。

方法2: 疑似クラス (Pseudo-classes)

疑似クラスは、要素の「状態」「構造上の位置」を条件としてスタイルを適用するための機能です。ユーザーが要素とインタラクションする際の変化や、HTML構造の中で特定の役割を持つ要素をスタイリングするのに非常に役立ちます。

なぜ疑似クラスが必要?

通常のCSSセレクタ(クラス名、タグ名、IDなど)は、HTMLの静的な構造に基づいて要素を選択します。しかし、Webサイトは静的なだけでなく、ユーザーの操作によって要素の状態が変化したり、リストの最初や最後といった構造上の特徴を持ったりします。

疑似クラスを使うことで、このような動的な状態や構造上の特徴を捉えて、それに応じてスタイルを変化させることができます。これにより、ユーザーはサイトが自分の操作に反応していることを視覚的に理解できるようになり、使いやすさが向上します。

基本的な書き方 (:疑似クラス名)

疑似クラスは、セレクタの末尾にコロン : と疑似クラス名を付けて記述します。

css
セレクタ:疑似クラス名 {
/* 疑似クラスの条件を満たしたときに適用したいCSSスタイル */
プロパティ: 値;
/* ... */
}

例:button 要素にマウスカーソルが乗ったとき(:hover状態)に背景色を変える

“`css
button {
background-color: #3498db; / 通常の背景色 /
color: white;
padding: 10px 20px;
border: none;
cursor: pointer; / カーソルを指マークに /
transition: background-color 0.3s ease; / 色の変化を滑らかに /
}

button:hover {
background-color: #2980b9; / ホバー時の背景色 /
}
“`

このように、通常の状態のスタイルと、疑似クラスが付いた状態のスタイルを分けて記述することで、条件に応じたデザイン変化を実現します。

代表的な疑似クラス

様々な疑似クラスがありますが、特によく使われるものを紹介します。

リンク関連 (:link, :visited, :hover, :active)

リンク(<a>要素)の状態に応じてスタイルを変える疑似クラスです。特に :hover:active はリンク以外の要素にも広く使われます。

  • :link: まだ訪問していないリンク
  • :visited: すでに訪問したリンク
  • :hover: マウスカーソルが要素の上にあるとき (タッチデバイスではタップ後などに状態が残る場合がある)
  • :active: 要素がアクティブな状態、つまりクリック(またはタップ、キーボード操作で押下)されている間

これらの疑似クラスをリンクに適用する場合、スタイル定義の順序が重要です。以下の「L-V-H-A」の順序で記述するのが慣例です。

css
a:link { color: blue; } /* Link - 未訪問 */
a:visited { color: purple; } /* Visited - 訪問済み */
a:hover { color: red; } /* Hover - マウスが乗った時 */
a:active { color: orange; } /* Active - クリックしている間 */

この順序を守らないと、例えば :visited のスタイルが :hover:active のスタイルよりも詳細度が高くなってしまい、ホバーやアクティブ時のスタイルが適用されなくなることがあります。

フォーム関連 (:focus, :checked, :disabled)

入力フォームの要素(<input>, <textarea>, <button>, <select>など)の状態を表す疑似クラスです。

  • :focus: 要素がフォーカスされているとき。キーボード入力が可能になった状態や、Tabキーで要素が選択された状態です。アクセシビリティの観点から非常に重要です。
  • :checked: ラジオボタン (<input type="radio">) やチェックボックス (<input type="checkbox">)、オプショングループ (<option>) が選択(チェック)されている状態。
  • :disabled: 要素が無効化されている状態 (disabled 属性が付いている)。
  • :enabled: 要素が有効な状態 (デフォルト)。
  • :read-only: 要素が読み取り専用の状態 (readonly 属性が付いている)。
  • :read-write: 要素が読み書き可能な状態 (デフォルト)。
  • :required: 必須入力フィールド (required 属性が付いている)。
  • :optional: 任意入力フィールド (デフォルト)。
  • :valid: 入力値が有効な状態 (バリデーションルール required, type, pattern などに適合している)。
  • :invalid: 入力値が無効な状態 (バリデーションルールに適合していない)。

例:

“`css
input[type=”text”]:focus {
outline: none; / デフォルトのアウトラインを消す場合 /
border-color: blue;
box-shadow: 0 0 5px rgba(0, 0, 255, 0.5); / 青い影をつける /
}

input[type=”checkbox”]:checked + label { / チェックされたチェックボックスの直後にあるlabel /
font-weight: bold;
color: green;
}

input:disabled {
opacity: 0.6;
cursor: not-allowed;
}

input:invalid {
border-color: red;
}

input:valid {
border-color: green;
}
``:checked + label` のように、疑似クラスと関係セレクタを組み合わせて使うこともよくあります。

構造関連 (:first-child, :last-child, :nth-child)

親要素の子要素の中で、特定の「位置」にある要素を条件とする疑似クラスです。リスト (<ul>, <ol>) やテーブル (<table>) の行などでよく使われます。

  • :first-child: 親要素の最初の子要素。
  • :last-child: 親要素の最後の子要素。
  • :only-child: 親要素にとって、唯一の子要素である場合。
  • :nth-child(n): 親要素の子要素の中で、n番目の子要素。n には数値、even (偶数), odd (奇数)、あるいは an+b の形式で指定できます。
    • li:nth-child(2): 2番目の li
    • li:nth-child(odd) または li:nth-child(2n+1): 1番目、3番目、5番目… (奇数番目の li)
    • li:nth-child(even) または li:nth-child(2n): 2番目、4番目、6番目… (偶数番目の li)
    • li:nth-child(3n): 3番目、6番目、9番目… (3の倍数番目の li)
    • li:nth-child(n+3): 3番目以降の li
    • li:nth-child(-n+3): 3番目までの li

nth-child は、要素の「タイプ」に関係なく、単に子要素として数えます。特定のタイプの要素だけを数えたい場合は、:nth-of-type() などを使います。

  • :first-of-type: 同じ要素タイプの中で、最初のもの。
  • :last-of-type: 同じ要素タイプの中で、最後のもの。
  • :only-of-type: 同じ要素タイプの中で、唯一のものである場合。
  • :nth-of-type(n): 同じ要素タイプの中で、n番目のもの。

例:

“`css
ul li:first-child {
font-weight: bold; / リストの最初の項目を太字に /
}

ul li:last-child {
border-bottom: none; / リストの最後の項目の下線を消す /
}

table tr:nth-child(even) {
background-color: #f2f2f2; / テーブルの偶数行に背景色(ゼブラストライプ) /
}

table td:nth-of-type(3) {
text-align: right; / 各行の3番目のtd(列)のテキストを右寄せに /
}

p:only-child {
font-style: italic; / 親要素の中にp要素が一つしかない場合、斜体に /
}
“`

その他の疑似クラス (:not(), :target, :empty)
  • :not(セレクタ): 指定したセレクタにマッチしない要素を選択します。
    “`css
    / クラス名が “active” でないすべてのdiv要素 /
    div:not(.active) {
    display: none;
    }

    / 最初のp要素以外すべて /
    p:not(:first-child) {
    margin-top: 20px;
    }
    * `:target`: URLのフラグメント識別子(`#` の後の部分)と一致するIDを持つ要素を選択します。ページ内リンクで特定のセクションにジャンプしたときに、そのセクションのスタイルを変えるなどに使えます。css
    / URLが #section-a のときに、IDが section-a の要素に適用 /

    section-a:target {

    background-color: yellow;
    }
    * `:empty`: 子要素(テキストノードも含む)を全く持たない要素を選択します。css
    / 中身が空のdiv要素 /
    div:empty {
    height: 20px;
    background-color: red;
    }
    “`

応用例 (チェックボックスとラベルで要素表示を切り替えるなど)

疑似クラスと関係セレクタを組み合わせると、JavaScriptを使わずにCSSだけで要素の表示/非表示を切り替えるといったトリックが可能です。

例:チェックボックスのチェック状態に応じて、非表示エリアを表示する

“`html

ここに、チェックボックスがオンの時だけ表示したいコンテンツが入ります。

“`

“`css
/ CSS側 /

/ チェックボックス自体は非表示にする /
.toggle-checkbox {
display: none;
}

/ 表示/非表示したいコンテンツは、デフォルトで非表示 /
.toggle-content {
display: none;
border: 1px solid #ccc;
padding: 15px;
margin-top: 10px;
background-color: #f9f9f9;
}

/ チェックボックスがチェックされた状態(:checked)かつ /
/ その直後の隣接兄弟要素(+)である label に続く(~) /
/ 一般兄弟要素である .toggle-content を表示する /
.toggle-checkbox:checked ~ .toggle-content {
display: block; / または flex, grid など /
}

/ ラベルにカーソルを乗せたときのスタイル変化なども可能 /
.toggle-label {
cursor: pointer;
color: blue;
text-decoration: underline;
}

.toggle-label:hover {
color: darkblue;
}
``
この例では、
.toggle-checkbox:checked ~ .toggle-contentというセレクタが、「.toggle-checkboxというクラスを持つ要素がチェックされており、**かつ**その要素と同じ親を持ち、その要素の**後方に**位置する.toggle-content` というクラスを持つ要素」を選択しています。

このように、疑似クラスは様々な条件で要素を選択し、動的なデザイン変化を実現するための強力なツールです。

注意点 (セレクタの優先順位、タッチデバイスでの:hover)

  • セレクタの優先順位 (詳細度): 疑似クラスも他のセレクタと同様に詳細度を持ちます。特定の要素に複数のスタイルが適用される可能性がある場合、詳細度の高いスタイルが優先されます。:hover, :focus, :active などのインタラクティブな状態は、通常のスタイルよりも詳細度が高くなることが多いですが、他のクラスやIDと組み合わせるとさらに詳細度が変わります。スタイルの適用順が意図した通りにならない場合は、セレクタの詳細度を確認しましょう。
  • タッチデバイスでの :hover: スマートフォンなどのタッチデバイスでは、マウスカーソルが存在しないため、:hover の挙動が期待通りにならないことがあります。一般的には、要素をタップした後に :active 状態が解除されず :hover 状態が残ってしまう、あるいは :hover が全く適用されないといった挙動が見られます。タッチデバイスでも機能するインタラクションは、クリックイベントをJavaScriptで処理したり、:active 状態や特定のクラスの有無でスタイルを制御したりすることを検討しましょう。

方法3: 疑似要素 (Pseudo-elements)

疑似要素は、要素の「一部」に対してスタイルを適用したり、HTMLには存在しない要素をCSSで生成したりするための機能です。主に装飾目的や、コンテンツの一部をCSSで操作したい場合に利用されます。

なぜ疑似要素が必要?

特定の要素の「最初の行だけスタイルを変えたい」「段落の最初の文字だけ大きくしたい」といった場合、その部分だけを別のタグ(例: <span>)で囲むのはHTML構造を複雑にしてしまいます。また、「要素の前後にかっこを付けたい」「見出しの前にマークを付けたい」といった装飾のために、HTMLに余分な要素を追加するのも避けたいところです。

疑似要素を使うことで、HTML構造を変えることなく、CSSだけでこのような「要素の一部」や「見た目上の追加要素」をスタイリングできます。

基本的な書き方 (::疑似要素名)

疑似要素は、セレクタの末尾にコロン二つ :: と疑似要素名を付けて記述します。

css
セレクタ::疑似要素名 {
/* 疑似要素に適用したいCSSスタイル */
プロパティ: 値;
/* ... */
}

過去のCSSの仕様ではコロン一つ : でしたが、疑似クラス (:hover など) と疑似要素を区別するために、現在はコロン二つ :: を使うことが推奨されています。ほとんどのモダンブラウザはコロン一つでも解釈できますが、新しいコードでは :: を使いましょう。

代表的な疑似要素

::before::after

おそらく最もよく使われる疑似要素です。要素の「内容」の直前 (::before) または直後 (::after) に、インライン要素を生成します。

これらの疑似要素を使う際は、content プロパティが必須です。content には、生成するコンテンツ(文字列、URL、空白、カウンターなど)を指定します。

“`css
/ h2見出しの前に青い四角を挿入 /
h2::before {
content: “”; / コンテンツは空でもOK(装飾目的の場合) /
display: inline-block; / インライン要素だが、幅高さを指定するためにブロック化 /
width: 10px;
height: 10px;
background-color: blue;
margin-right: 10px;
vertical-align: middle; / 中央寄せ /
}

/ 外部リンクにアイコンやテキストを追加 /
a[href^=”http”]::after { / httpまたはhttpsで始まるリンク /
content: ” 🔗”; / 絵文字やテキスト /
font-size: 0.8em;
margin-left: 3px;
}

/ class=”required” な input の後に米印を追加 /
input.required::after {
content: ” *”;
color: red;
}
``::before::afterはデフォルトではdisplay: inlineですが、装飾目的でサイズや余白を細かく制御したい場合は、display: inline-blockdisplay: block` に変更することが多いです。

これらは、CSSだけでアイコンや小さな装飾要素を挿入したり、コンテンツの補足情報を加えたりするのに非常に便利です。

::first-line::first-letter

ブロックレベル要素のテキストの「最初の行」または「最初の文字」にスタイルを適用します。

  • ::first-line: ブロック要素(p, h1など)の、表示されている最初の行。行の折り返しは画面幅によって変わるので、どのテキストが最初の行になるかは動的です。
  • ::first-letter: ブロック要素の、最初の文字。全角記号や空白はスキップされます。

“`css
/ 段落の最初の行を太字に /
p::first-line {
font-weight: bold;
}

/ 段落の最初の文字を大きく、ドロップキャップのように /
p::first-letter {
font-size: 2.5em; / 文字サイズを大きく /
font-weight: bold;
color: #333;
float: left; / 後続のテキストを回り込ませる /
margin-right: 5px;
line-height: 1; / 行の高さを調整 /
}
``::first-line::first-letter` に適用できるプロパティは限られています(フォント関連、カラー、背景、text-decoration、vertical-align、word-spacing、letter-spacing、text-transform、line-height、clearなど)。

::selection

ユーザーがマウスでテキストを選択した際に、その選択範囲の背景色や文字色を変更できます。

“`css
::selection {
background-color: #ffb7b7; / 選択範囲の背景色 /
color: #333; / 選択範囲の文字色 /
}

/ Firefox 用 (ベンダープレフィックスが必要な場合がある) /
::-moz-selection {
background-color: #ffb7b7;
color: #333;
}
``:selectionに適用できるプロパティはcolor,background-color,text-shadow,text-decoration` のみです。

応用例 (clearfix, カスタムチェックボックス/ラジオボタン)

  • clearfix: float を使ったレイアウトで親要素が子要素の高さを囲まなくなる問題を解消する伝統的な手法です。::after 疑似要素を使ってクリアフロート要素を生成します。
    css
    .clearfix::after {
    content: "";
    display: table; /* または block */
    clear: both; /* floatを解除 */
    }

    現在は Flexbox や Grid の方が推奨されますが、古いコードや特定の場面で使われることがあります。
  • カスタムチェックボックス/ラジオボタン: 元の <input type="checkbox"><input type="radio"> を非表示にし、対応する <label> 要素と ::before/::after 疑似要素を組み合わせて、オリジナルのデザインのチェックボックスやラジオボタンを作成します。これは :checked 疑似クラスと組み合わせて使います。

注意点 (contentプロパティの必要性、インライン要素/ブロック要素)

  • ::before/::after には content プロパティが必須です。何も表示したくない場合でも content: ""; を指定する必要があります。
  • ::before/::after はデフォルトではインライン要素として生成されます。幅や高さを指定したり、ブロック要素として振る舞わせたりしたい場合は、display: block;display: inline-block; などを指定する必要があります。
  • 疑似要素はCSSで生成される見た目上の要素であり、HTMLのDOMツリーには存在しません。JavaScriptで直接操作することはできません(疑似要素を持つ本体要素を操作します)。
  • 一部の古いブラウザでは、:: ではなく : で疑似要素を指定する必要がありますが、現代のWeb開発では :: を使用すればほとんど問題ありません。

疑似要素を使うことで、HTMLをきれいに保ちながら、デザインの自由度を高めることができます。特に ::before::after は、様々な装飾やマイクロコンテンツの挿入に非常に便利なのでぜひ活用してみてください。

方法4: 属性セレクタ (Attribute Selectors)

属性セレクタは、要素が持つHTML属性の名前やその「値」を条件としてスタイルを適用するための機能です。クラス名やIDを使うほどではない、特定の属性を持つ要素や属性値に応じたスタイリングに便利です。

なぜ属性セレクタが必要?

HTML要素には、href, src, alt, type, title, lang, data-* など、様々な属性があります。これらの属性は、要素の機能や情報を示すために使われます。

例えば、すべてのリンクに同じスタイルを適用するのは簡単ですが、「PDFファイルへのリンクだけにアイコンを付けたい」「特定の言語の要素だけにフォントを変えたい」「入力フィールドの種類(テキスト、メール、パスワードなど)によってスタイルを変えたい」といった場合はどうでしょう?

属性セレクタを使うことで、これらの属性を条件として要素を選択し、スタイルを適用することができます。これにより、HTMLに余分なクラス名を追加することなく、セマンティックなHTML構造を保ったままスタイリングが可能になります。

基本的な書き方 ([属性名], [属性名=”値”], …)

属性セレクタは、角括弧 [] を使って記述します。

  • [属性名]: 指定した属性を持つ要素すべてを選択します。
    css
    /* title属性を持つすべての要素 */
    [title] {
    border-bottom: 1px dotted #ccc;
    cursor: help; /* カーソルをヘルプ表示に */
    }
  • [属性名="値"]: 指定した属性を持ち、かつその値が完全に一致する要素を選択します。
    “`css
    / type=”text” のinput要素 /
    input[type=”text”] {
    width: 200px;
    padding: 5px;
    }

    / target=”_blank” のa要素(新しいタブで開くリンク) /
    a[target=”_blank”] {
    font-weight: bold;
    }
    * `[属性名~="値"]`: 属性値が**スペース区切り**の単語リストであり、その中に指定した単語が**完全に**含まれている要素を選択します。これは、複数のクラス名がスペースで区切られている `class` 属性で特定のクラスだけを条件にしたい場合によく使われます(ただし、単に `.クラス名` と書くのが一般的です)。css
    / class=”button primary” や class=”secondary button” などにマッチ /
    / class=”buttonary” にはマッチしない /
    [class~=”button”] {
    display: inline-block;
    padding: 10px 15px;
    }
    * `[属性名|="値"]`: 属性値が**ハイフン区切り**の単語リストであり、指定した単語で始まるか、完全に一致する要素を選択します。主に `lang` 属性や `xml:lang` 属性に使われます。css
    / lang=”en” や lang=”en-US” などにマッチ /
    [lang|=”en”] {
    font-family: Georgia, serif;
    }
    * `[属性名^="値"]`: 属性値が指定した文字列で**始まる**要素を選択します。css
    / hrefが “https://” で始まるa要素 /
    a[href^=”https://”] {
    color: green;
    }
    * `[属性名$="值"]`: 属性値が指定した文字列で**終わる**要素を選択します。css
    / hrefが “.pdf” で終わるa要素 /
    a[href$=”.pdf”] {
    font-weight: bold;
    / PDFアイコンなどを追加することも /
    }
    * `[属性名*="値"]`: 属性値に指定した文字列が**どこかに**含まれている要素を選択します。css
    / hrefに “example.com” が含まれるa要素 /
    a[href*=”example.com”] {
    color: orange;
    }

    / class名に “icon” が含まれる要素 /
    [class*=”icon”] {
    background-repeat: no-repeat;
    padding-left: 20px;
    }
    “`

具体的なコード例 (特定のinput type, data属性)

HTML例:

“`html




“`

CSS例:

“`css
/ input typeに応じて枠線の色を変える /
input[type=”text”] {
border-color: blue;
}

input[type=”email”] {
border-color: green;
}

input[type=”password”] {
border-color: red;
}

/ data属性の値に応じてボタンの色を変える /
button[data-type=”confirm”] {
background-color: #2ecc71; //
color: white;
}

button[data-type=”cancel”] {
background-color: #e74c3c; //
color: white;
}
“`

このように、属性セレクタを使うことで、要素の属性が持つ意味合いに基づいてスタイルを適用することができます。特に data-* 属性と組み合わせると、HTMLの意味付けを保ちつつ、JavaScriptやCSSで柔軟に要素を操作・スタイリングできるようになります。

注意点 (属性値の大文字小文字、パフォーマンス)

  • 属性値の大文字小文字: HTML属性名自体は通常大文字小文字を区別しませんが、属性値は多くの場合大文字小文字を区別します。例えば [type="Text"]type="text" にはマッチしません。HTMLの慣習に従い、属性値は小文字で記述するのが安全です。CSS Selectors Level 4では大文字小文字を区別しない指定 ([attr="value" i]) も可能になっていますが、まだ全てのブラウザでサポートされているわけではありません。
  • パフォーマンス: 一般的に、単純なクラスセレクタ (.my-class) やIDセレクタ (#my-id) に比べて、属性セレクタ、特に *=~= などを含むものは、ブラウザの要素検索に時間がかかる可能性があります。要素数が非常に多い場合や、パフォーマンスが重要な場面では、多用しない方が良い場合があります。ただし、ほとんどの一般的なWebサイトでは大きな問題にならないレベルです。

属性セレクタは、特定の属性を持つ要素を効率的に選択し、HTMLに余分なクラスを追加することなくスタイリングするための便利な方法です。

方法5: 関係セレクタ (Combinators)

関係セレクタ(結合子とも呼ばれます)は、複数のセレクタを組み合わせて、要素同士の「位置関係」や「階層構造」を条件としてスタイルを適用するための機能です。特定の構造の中にある要素だけを選んでスタイリングしたい場合に役立ちます。

なぜ関係セレクタが必要?

WebページのHTMLは、要素が入れ子になった階層構造を持っています。例えば、div の中に p があり、さらにその p の中に span がある、といった具合です。また、同じ親を持つ要素同士(兄弟要素)も存在します。

クラス名やタグ名だけでは、特定の要素を選択できても、「この div中にあるすべての p」「この ul直下にある li」「この h2すぐ後ろにある p」といった、位置関係を条件にした選択はできません。

関係セレクタを使うことで、要素間の構造的な関係を指定して、より precise なセレクタを作成することができます。

基本的な書き方 (スペース, >, +, ~)

関係セレクタとして使われる記号は以下の4種類です。

  1. 子孫セレクタ (親要素 子孫要素):
    親要素(左側のセレクタ)の中にある、子孫要素(右側のセレクタ)すべてを選択します。子要素だけでなく、孫要素、曾孫要素… と、階層の深さに関わらず中に含まれるすべての該当要素が対象になります。スペース一つで区切ります。
    “`css
    / div要素の中にあるすべてのp要素 /
    div p {
    color: #333;
    }

    / header要素の中にあるすべてのa要素 /
    header a {
    text-decoration: none;
    }
    ``
    例えば

    テキスト強調

    という構造の場合、div p

    テキスト強調

    に、div span強調` にマッチします。

  2. 子セレクタ (親要素 > 子要素):
    親要素(左側のセレクタ)の直下にある子要素(右側のセレクタ)のみを選択します。子孫セレクタと異なり、階層が一つ下の直接の子要素だけが対象になります。> 記号で区切ります。
    “`css
    / ul要素の直下にあるli要素のみ /
    ul > li {
    margin-bottom: 5px;
    list-style: square;
    }

    / id=”sidebar” の要素の直下にあるすべてのp要素 /

    sidebar > p {

    font-size: 0.9em;
    }
    ``
    例えば

    • 項目1
    • 項目2
      • サブ項目

    という構造の場合、ul > liは「項目1」と「項目2」のliにマッチしますが、「サブ項目」のli(これは内側のulの子)にはマッチしません。一方、ul liは3つのli` すべてにマッチします。

  3. 隣接兄弟セレクタ (要素1 + 要素2):
    要素1(左側のセレクタ)の直後に位置し、かつ同じ親を持つ要素2(右側のセレクタ)を選択します。プラス + 記号で区切ります。要素2は要素1のすぐ隣になければなりません。
    “`css
    / h2要素の直後にあるp要素 /
    h2 + p {
    margin-top: 0; / 通常、見出しの下にはマージンがあるが、直後のpのマージンを調整 /
    font-style: italic;
    }

    / .itemクラスを持つ要素の直後にある.itemクラスを持つ要素 /
    .item + .item {
    border-top: 1px solid #eee; / item同士の間に線を入れる /
    }
    “`
    このセレクタは、特定の要素の「一つだけ後続する兄弟要素」にスタイルを適用したい場合に便利です。

  4. 一般兄弟セレクタ (要素1 ~ 要素2):
    要素1(左側のセレクタ)の後方に位置し、かつ同じ親を持つ要素2(右側のセレクタ)すべてを選択します。チルダ ~ 記号で区切ります。隣接兄弟セレクタと異なり、直後である必要はなく、後方にあればすべて対象になります。
    “`css
    / h2要素の後方にあるp要素すべて /
    h2 ~ p {
    text-indent: 1em; / 見出し後の段落を字下げ /
    }

    / input[type=”checkbox”]:checked ~ .target-div { display: block; } /
    / ↑ これは、疑似クラスと組み合わせた例で、チェックボックスの後ろにある特定のdivを表示する /
    “`
    このセレクタは、特定の要素以降の兄弟要素群にまとめてスタイルを適用したい場合に便利です。

具体的なコード例 (リストの最後の項目にだけスタイルを付けない)

リストの項目に下線を付けたいが、最後の項目には付けたくない、という状況はよくあります。これを関係セレクタと疑似クラスで実現できます。

HTML例:

“`html

  • リスト項目 1
  • リスト項目 2
  • リスト項目 3

“`

CSS例:

“`css
/ ulの直下にあるli要素すべてに下線を付ける /
ul > li {
border-bottom: 1px solid #ccc;
padding: 10px 0;
}

/ ulの直下にあるli要素のうち、最後の子要素に下線を付けない /
ul > li:last-child {
border-bottom: none;
}
``
ここでは子セレクタ
>と疑似クラス:last-childを組み合わせています。ul > liで「直下のすべてのli」を選び、それにスタイル(下線)を適用します。次にul > li:last-child` で「直下のliのうち最後の子」を選び、下線を削除するスタイルを適用して上書きしています。

同様に、最初の項目だけスタイルを変える場合は ul > li:first-child を使います。

応用例 (CSSだけでアコーディオンメニュー/タブ切り替え)

属性セレクタの箇所で少し触れましたが、関係セレクタ(特に +~)と:checked 疑似クラスを組み合わせると、JavaScriptを使わずにCSSだけでアコーディオンメニューやタブ切り替えのようなUIを実現できます。これは、チェックボックスやラジオボタンの :checked 状態をトリガーとして、その兄弟要素や後続の兄弟要素の表示を切り替えるという仕組みです。

注意点 (詳細度、複雑化)

  • 詳細度: 関係セレクタを含むセレクタの詳細度は、含まれる個々のセレクタの詳細度の合計によって計算されます。複数の関係セレクタを組み合わせるほど詳細度は高くなります。
  • 複雑化: 関係セレクタを多用しすぎたり、長いチェーンにしたりすると、セレクタの意図が分かりにくくなり、CSSコードの可読性や保守性が低下する可能性があります。必要な範囲で適切に使うことが重要です。
  • 親セレクタは存在しない: CSSには、子要素を条件に親要素を選択する「親セレクタ」は現在の仕様では存在しません(一部ブラウザで :has() 疑似クラスがサポートされ始めていますが、広く使える状況ではありません)。「リスト項目にホバーしたら、親の ul に背景色を付けたい」といったことは、CSS単体では直接できません(JavaScriptを使う必要があります)。

関係セレクタは、HTMLの構造を利用して要素を選択するための強力なツールです。子要素や兄弟要素といった関係性を理解すると、より柔軟なスタイリングが可能になります。

方法6: CSS変数 (CSS Custom Properties)

CSS変数(CSSカスタムプロパティとも呼ばれます)は、スタイルシート内で再利用可能な値を定義するための機能です。これ自体は直接的な「条件」を指定するものではありませんが、他の方法(メディアクエリやJavaScript)と組み合わせることで、条件によってデザインの値を動的に変更する際に非常に強力な手段となります。

なぜCSS変数が必要?

Webサイト全体で共通して使われる色(ブランドカラー)、余白のサイズ、フォントサイズなど、同じ値を複数の場所で何度も使うことがあります。これらの値を後から変更したい場合、CSSファイル全体を検索してすべての該当箇所を修正する必要があり、手間がかかる上にミスの原因にもなりやすいです。

また、例えばダークモードとライトモードのように、サイト全体の配色を条件によってガラッと切り替えたい場合、CSS変数を使わないと非常に複雑なコードになります。

CSS変数を使うと、これらの問題を解決できます。

基本的な書き方 (–変数名: 値;, var(–変数名);)

CSS変数は、二つのハイフン -- から始まる任意の名前で定義します。変数の値を使用するには、var() 関数を使います。

“`css
/ 変数の定義 /
:root { / :root に定義するとグローバル変数になる /
–main-color: #3498db; / メインカラー /
–text-color: #333; / テキストカラー /
–base-padding: 10px; / 基本的なパディング /
}

/ 変数の使用 /
body {
color: var(–text-color);
padding: var(–base-padding);
}

h1 {
color: var(–main-color);
}

.button {
background-color: var(–main-color);
padding: var(–base-padding) calc(var(–base-padding) * 2); / 変数を使った計算も可能 /
}
``:root疑似クラスは、HTMLドキュメントのルート要素(通常は` 要素)を選択します。ここに変数を定義すると、その変数はドキュメント全体で利用可能なグローバル変数になります。

特定の要素の中に変数を定義することも可能で、その場合はその要素とその子孫要素内でのみ有効なローカル変数になります(スコープ)。

“`css
.component {
–component-bg: #f0f0f0; / この.component要素内だけで有効な変数 /
background-color: var(–component-bg);
}

.component .inner-element {
/ 親要素で定義された変数を使用できる /
color: var(–component-bg);
}
“`

var() 関数には、第二引数にフォールバック値を指定できます。これは、指定した変数が見つからなかった場合に使われる値です。古いブラウザでCSS変数がサポートされていない場合などに有用です。
css
/* --my-variable が定義されていなければ red を使う */
color: var(--my-variable, red);

条件による変更

CSS変数の最も強力な使い方は、メディアクエリやJavaScriptと組み合わせて、条件によって変数の値を変更することです。

メディアクエリ内で変数の値を上書きする

メディアクエリを使って、特定のブレークポイントでCSS変数の値を再定義すると、そのブレークポイント以下のすべての要素でその変数の値が変わります。

“`css
/ デフォルト(モバイル向け)/
:root {
–heading-font-size: 1.5em;
–padding-size: 10px;
}

h1 {
font-size: var(–heading-font-size);
padding: var(–padding-size);
}

/ PC以上の画面幅の場合 /
@media (min-width: 768px) {
:root {
/ 変数を上書き /
–heading-font-size: 2.5em;
–padding-size: 20px;
}
/ h1のスタイル定義は変更不要、var()が参照する値が変わるだけ /
}
“`
このように、変数の定義箇所だけをメディアクエリ内に記述すれば、変数を使っている全ての要素のスタイルが一括で変更されます。個々の要素のフォントサイズやパディングをメディアクエリごとに記述する必要がなくなります。

JavaScriptを使って変数の値を変更する

JavaScriptを使うと、ユーザーの操作やより複雑な条件に基づいて、CSS変数の値を動的に変更できます。これは、テーマ切り替え(ダークモードなど)や、ユーザー設定によるスタイルの変更に非常に有効です。

“`javascript
// JavaScriptで:rootに定義されたCSS変数の値を変更する例

const root = document.documentElement; // :root は html 要素

const toggleDarkMode = () => {
const isDarkMode = root.style.getPropertyValue(‘–is-dark-mode’) === ‘true’; // 現在の状態を取得
if (isDarkMode) {
// ライトモードに切り替え
root.style.setProperty(‘–is-dark-mode’, ‘false’);
root.style.setProperty(‘–background-color’, ‘#fff’);
root.style.setProperty(‘–text-color’, ‘#333’);
} else {
// ダークモードに切り替え
root.style.setProperty(‘–is-dark-mode’, ‘true’);
root.style.setProperty(‘–background-color’, ‘#333’);
root.style.setProperty(‘–text-color’, ‘#eee’);
}
};

// ボタンクリックなどで toggleDarkMode() を呼び出す
// document.getElementById(‘darkModeToggleBtn’).addEventListener(‘click’, toggleDarkMode);
“`

CSS側では、これらの変数を使ってスタイルを定義しておきます。

“`css
/ CSS側 /
:root {
/ デフォルト値(ライトモード)/
–is-dark-mode: false;
–background-color: #fff;
–text-color: #333;
}

body {
background-color: var(–background-color);
color: var(–text-color);
}

h1 {
color: var(–text-color); / テキストカラーと同じ /
}

/ ダークモード固有のスタイル調整が必要なら、–is-dark-mode 変数を使うこともできるが、 /
/ 通常は変数で色を切り替えるだけで済むことが多い /
/ 例:ダークモードの時だけ特定のボーダーの色を変えるなど /
/ .my-element {
border-color: var(–is-dark-mode) === ‘true’ ? ‘#555’ : ‘#ccc’; // 残念ながらCSSだけでは三項演算子は難しい
}
/
/ 上記のような複雑な条件はCSS変数だけでは難しく、JavaScriptでのクラス切り替えと組み合わせる方が現実的 /
“`
このように、JavaScriptでCSS変数を操作することで、Webサイト全体のテーマを簡単に切り替えるといったことが実現できます。

応用例 (ダークモード、テーマ切り替え)

CSS変数は、Webサイトの「テーマ」を管理するのに非常に適しています。メインカラー、アクセントカラー、背景色、文字色、余白サイズなどを変数として定義しておけば、これらの変数の値を変更するだけで、サイト全体の見た目をガラッと変えることができます。これは、ダークモードやユーザーが選択できる複数のテーマを実装する際に、CSSコードを大幅に削減し、管理を容易にします。

注意点 (IE非対応、フォールバック)

  • IE非対応: CSS変数はInternet Explorer (IE) では完全にサポートされていません。IEをサポートする必要がある場合は、フォールバック値 (var(--my-var, default-value)) を使うか、CSSプリプロセッサー(Sassなど)の変数機能(これはコンパイル時に静的な値に置き換えられる)を使うなどの代替手段を検討する必要があります。
  • 計算: calc() 関数と組み合わせて四則演算は可能ですが、if文のような条件分岐はCSS変数単体ではできません。より複雑な条件に基づく値の決定はJavaScriptで行う必要があります。

CSS変数は、デザインの値を柔軟に管理し、他の技術と組み合わせて動的なデザイン変更を効率的に行うための、比較的新しいながらも非常に強力な機能です。

方法7: JavaScriptとの連携 (クラスの切り替え)

これまでに見てきたCSS単体の方法だけでは対応できない、より複雑な条件やユーザー操作に基づくデザイン変更は、JavaScriptとCSSを連携させることで実現します。この連携の最も一般的な方法は、JavaScriptでHTML要素に特定のCSSクラスを追加したり削除したりすることで、CSS側でそのクラスの有無を条件にスタイルを適用するというものです。

なぜJavaScriptとの連携が必要?

CSSの疑似クラス (:hover, :active, :focus など) はユーザーの基本的な操作に対応できますが、以下のようなより複雑なシナリオには対応できません。

  • ボタンをクリックしたら特定の要素が表示/非表示される
  • スクロール位置に応じてヘッダーのデザインが変わる
  • 外部から取得したデータの内容に応じて要素の色を変える
  • ユーザーがフォームを送信しようとしたときに、入力値のバリデーション結果に応じてエラーメッセージを表示したり、フィールドの枠線を赤くしたりする
  • アニメーションを特定のタイミングで開始・停止する

このような、ユーザーの多様な操作や、ページの動的な状態変化を条件とする場合は、JavaScriptでその変化を検知し、CSSに伝える必要があります。

考え方: JSでクラスを操作し、CSSでスタイリングする

JavaScriptとCSSを連携させて条件によってデザインを変える際の基本的な考え方は以下の通りです。

  1. CSS側: デザインが変化する状態を表すためのCSSクラスを定義しておきます。例えば、非表示状態を表す .hidden クラス、アクティブ状態を表す .is-active クラスなどです。これらのクラスが付いている場合と付いていない場合で、要素のスタイルが異なるように定義しておきます。
  2. JavaScript側: 特定のイベント(クリック、スクロール、データ受信など)を監視し、条件が満たされたときに、対象のHTML要素に対してCSSクラスを追加 (add)、削除 (remove)、または切り替え (toggle) ます。

基本的なJavaScriptコード (.classList API)

要素のクラスを操作するには、JavaScriptの .classList APIが非常に便利です。

“`javascript
// 例:IDが “myElement” の要素を取得
const myElement = document.getElementById(‘myElement’);

// クラスを追加
myElement.classList.add(‘new-class’);

// クラスを削除
myElement.classList.remove(‘old-class’);

// クラスがあるかないかを確認して、あれば削除、なければ追加する(付け外し)
myElement.classList.toggle(‘active’);

// クラスが要素に付いているか確認する(真偽値を返す)
if (myElement.classList.contains(‘special’)) {
console.log(‘この要素には special クラスが付いています’);
}
“`

具体的なコード例 (ボタンクリックで要素を表示/非表示)

先ほど疑似クラスの応用例でCSSだけで実現しましたが、JavaScriptを使うとより汎用的に実装できます。

HTML例:

“`html

“`

CSS例:

“`css
/ CSS側:非表示状態を定義 /
.hidden {
display: none; / または visibility: hidden; opacity: 0; など /
}

/ 必要であれば、表示状態のためのスタイルも定義(.visible など) /
/ .visible {
display: block;
}
/

/ アニメーションを付けたい場合は、transitionプロパティを追加 /
/ .toggle-content {
transition: opacity 0.5s ease;
}
.hidden {
opacity: 0;
}
/
“`

JavaScript例:

“`javascript
// JavaScript側:ボタンのクリックイベントを監視し、クラスを切り替える

// 必要な要素を取得
const toggleButton = document.getElementById(‘toggleButton’);
const contentDiv = document.getElementById(‘content’);

// ボタンにクリックイベントリスナーを追加
toggleButton.addEventListener(‘click’, function() {
// contentDiv要素に “hidden” クラスがあれば削除、なければ追加する
contentDiv.classList.toggle(‘hidden’);

// ボタンのテキストも切り替えたい場合
if (contentDiv.classList.contains(‘hidden’)) {
toggleButton.textContent = ‘詳細を表示’;
} else {
toggleButton.textContent = ‘詳細を非表示’;
}
});
``
このJavaScriptコードは、ボタンがクリックされるたびに
contentDiv要素のhiddenクラスを付け外します。CSS側では.hiddenクラスが付いている場合にdisplay: none;` が適用されるように定義されているため、要素が表示/非表示されるという仕組みです。

応用例 (タブ切り替え、アコーディオンメニュー、モーダルウィンドウ)

これらの高度なUIコンポーネントは、JavaScriptによるクラスの付け外しと、CSSによるそのクラスに応じたスタイリングを組み合わせて実現されるのが一般的です。

  • タブ切り替え: タブボタンをクリックしたときに、クリックされたタブに対応するコンテンツ要素に .is-active クラスなどを追加し、他のコンテンツ要素からはそのクラスを削除します。CSSでは、.is-active クラスが付いているコンテンツだけ display: block; などで表示し、それ以外は display: none; で非表示にします。
  • アコーディオンメニュー: ヘッダー部分をクリックしたときに、対応するコンテンツ部分に .is-open クラスなどを追加/削除します。CSSでは、.is-open クラスが付いている場合にコンテンツの高さを auto にしたり、max-heightoverflow: hidden を組み合わせてアニメーション付きで開閉させたりします。
  • モーダルウィンドウ: ボタンクリックで、モーダルウィンドウの要素と、背景のオーバーレイ要素に .is-visible クラスなどを追加します。CSSでは、.is-visible クラスが付いている場合に display: block;visibility: visible; opacity: 1; などで表示します。閉じるボタンやオーバーレイクリックでクラスを削除します。

注意点 (CSSとJSの役割分担、パフォーマンス)

  • CSSとJSの役割分担: デザインの見た目(色、レイアウト、フォントなど)はCSSで管理し、ユーザーの操作や状態変化のロジック、およびそれに応じたクラスの操作はJavaScriptで行う、という役割分担を明確にしましょう。JavaScriptの中に直接スタイルを書き込むことも可能ですが、保守性が低下するため推奨されません。
  • クラス名の設計: JavaScriptで操作するクラス名は、そのクラスが要素の「状態」を表すように命名するのが良い習慣です (例: is-active, is-open, has-error, is-loading, is-fixed など)。
  • パフォーマンス: スクロールイベントやマウス移動イベントなど、頻繁に発生するイベントの中でDOM操作(クラスの付け外し)を行うと、パフォーマンスに影響を与える可能性があります。イベントの発生頻度を制限する「デバウンス」や「スロットル」といったテクニックをJavaScript側で利用することを検討しましょう。
  • アニメーション: JavaScriptでクラスを付け外しする際に、CSSの transition プロパティと組み合わせることで、デザイン変化に滑らかなアニメーションを付けることができます。

JavaScriptとの連携は、CSSだけでは難しい動的なデザイン変化を実現するための強力な手段です。クラスの付け外しというシンプルな仕組みを理解すれば、様々なUIの実装に応用できます。

複数の方法を組み合わせる

実際のWebサイト制作では、これまで見てきたこれらの方法を単独で使うだけでなく、組み合わせて使うことがほとんどです。各方法の得意な「条件」を理解し、目的に応じて最適な組み合わせを選ぶことが重要です。

いくつか組み合わせの例を見てみましょう。

  • メディアクエリ + 疑似クラス:
    「画面幅が狭いとき(メディアクエリ)だけ、リンクにマウスが乗ったとき(疑似クラス :hover)の下線の色を変える」といったスタイル。
    “`css
    / PCではリンクの下線はデフォルト /
    a:hover {
    text-decoration-color: blue;
    }

    / スマホ以下の画面幅の場合 /
    @media (max-width: 767px) {
    / その中でのリンクのホバー時のスタイルを上書き /
    / ただしスマホでhoverの挙動は限定的 /
    a:hover {
    text-decoration-color: red;
    }
    / もしくは、スマホ以下では特定の疑似クラスのスタイルを無効にする /
    a:hover {
    text-decoration: none; / 下線を消すなど /
    }
    }
    ``
    また、「PCの広い画面では、リストの偶数項目に背景色を付ける(
    :nth-child(even)`)が、スマホでは行を分けずに縦に並ぶため、このスタイルを無効にする」といった場合も、メディアクエリ内で疑似クラスのスタイルを上書きします。

  • 属性セレクタ + 関係セレクタ:
    「特定の data-type 属性を持つ div 要素の直下にある p 要素だけをスタイリングする」といった場合。
    css
    /* data-type="feature" の属性を持つdivの直下にあるp要素 */
    div[data-type="feature"] > p {
    margin-bottom: 5px;
    font-size: 0.9em;
    }

  • 疑似クラス + 関係セレクタ:
    「チェックボックスがチェックされた状態(:checked)の後にある~ または +)特定の要素」を選択し、表示状態を切り替える(CSSハック)。これは先ほど「応用例」で見たものです。

  • CSS変数 + メディアクエリ + JavaScript:
    「デフォルトのテーマカラーをCSS変数で定義しておき、画面幅が狭い場合はメディアクエリでその変数の値を少し暗くし、さらにダークモード切り替えボタンが押されたらJavaScriptでその変数の値を完全にダークモード用の色に変更する」といった、複数の条件と技術を組み合わせた複雑なテーマ制御。

このように、CSSの各機能をパズルのピースのように組み合わせて、必要な条件とスタイルを実現していきます。どの方法が最適かは、変更したい条件の種類、対象となる要素、コードの管理のしやすさなどを考慮して判断します。

最初はそれぞれの方法を単独で試してみて、慣れてきたら少しずつ組み合わせる練習をしてみましょう。

まとめ

この記事では、CSSを使って条件によってデザインを変えるための様々な方法を、初心者向けに詳しく解説しました。

  • メディアクエリ: 画面サイズやデバイスの特性を条件に、主にレスポンシブデザインを実現します。
  • 疑似クラス: 要素のインタラクティブな状態(ホバー、フォーカスなど)や構造上の位置を条件に、ユーザー操作への反応やリストなどのスタイリングに役立ちます。
  • 疑似要素: 要素の一部やCSSで生成する要素を条件に、装飾やコンテンツの追加を行います。
  • 属性セレクタ: 要素のHTML属性やその値を条件に、特定の属性を持つ要素をスタイリングします。
  • 関係セレクタ: 要素同士の構造的な位置関係を条件に、特定の階層や並びにある要素をスタイリングします。
  • CSS変数: デザインの値を変数として管理し、他の方法と組み合わせて値の変更を効率化します。
  • JavaScriptとの連携: クラスの付け外しを通じて、より複雑な条件やユーザー操作に基づく動的なデザイン変更を実現します。

これらの方法は、それぞれ異なる「条件」に強く、Webサイトの見た目を豊かにし、使いやすさ(ユーザビリティ)やアクセシビリティを向上させるために不可欠な技術です。

初心者の方は、まず以下から試してみるのがおすすめです。

  1. メディアクエリで、PCとスマホでレイアウトやフォントサイズが変わるようにしてみる。
  2. 疑似クラスで、ボタンやリンクにホバーしたときに色が変わるようにしたり、フォーム入力中に枠線が付くようにしたりする。リストの :nth-child(odd) でゼブラストライプを試してみる。
  3. 簡単なJavaScriptで、ボタンクリックで要素が表示/非表示されるように、クラスを付け外ししてみる。

これらの基本的な使い方が理解できたら、他の方法にも挑戦し、最終的にはそれらを組み合わせて使うことで、より高度で表現力豊かなWebサイトを制作できるようになるでしょう。

CSSでの条件付きスタイリングは、単なる見た目の変更にとどまらず、ユーザーがWebサイトとどのようにインタラクションし、どのような環境で閲覧しているかに寄り添った、より親切で使いやすい体験を提供するための重要なステップです。

これで、CSSで条件によってデザインを変えるための基本的な考え方と主な技術は網羅できたはずです。ぜひこれらの知識を元に、実際にコードを書いて試してみてください。学んだことを実践することが、スキル習得への一番の近道です。

これからもCSSの世界は進化し続けます。今回学んだ内容を土台として、さらに新しい技術や表現方法を積極的に学び続けていきましょう。


コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール