CSS備忘録・後半(テキスト・装飾・アニメーション・ユーザビリティ)

この記事は、CSSの基本から応用までを整理した備忘録です
HTMLやJavaScriptも関連が深い部分については、適宜補足しています

目次
  1. テキスト関連のプロパティ
    1. プロパティ一覧
      1. font-family設定のための基礎知識
      2. Webフォントについて
      3. font-sizeについて
    2. テキストの改行
      1. 日本語と英語の改行の違いとまとめ
      2. max-content / min-content / fit-content
    3. テキストの省略
    4. 縦書きに関連するプロパティ
  2. 装飾系のプロパティ
    1. (border・outline)枠
    2. (box-shadow・text-shadow)シャドウ
    3. (background)背景画像
    4. グラデーション
      1. 線形グラデーション(linear-gradient)
      2. 放射グラデーション(radial-gradient)
      3. 扇形グラデーション(conic-gradient)
    5. フィルターとブレンドモード
      1. (filter・backdrop-filter)フィルター
      2. (mix-blend-mode・background-blend-mode)ブレンドモード
      3. (isolation)スタッキングコンテキストを生成
    6. クリッピングとマスキング
      1. (clip-path)クリッピング
      2. (mask)マスキング
    7. (visibility ・opacity)表示状態
    8. その他
      1. (cursor)カーソルの種類
      2. (list-style)リストの装飾
      3. (quotes)引用符の装飾
      4. (ruby)ルビの装飾
  3. 動作系のプロパティ
    1. (pointer-events)クリックの可否
    2. (user-select)テキスト選択の可否
    3. (scroll-behavior)スムーススクロール
      1. (補足)JSのscrollTo()とscrollIntoView()メソッド
  4. CSSアニメーションとトランスフォーム
    1. (transition)トランジション
    2. (animation)アニメーション
    3. (transform)トランスフォーム
      1. 2Dトランスフォーム
      2. 3Dトランスフォーム
  5. パフォーマンス最適化
    1. (will-change)変更を予測して最適化
    2. (contain)要素の影響範囲を制限
    3. (content-visibility)画面外の要素を描画
    4. CLS対策について
  6. アクセシビリティについて
    1. アクセシビリティを意識したCSS
    2. (補足)スクリーンリーダーのためHTMLと補助的な属性

テキスト関連のプロパティ

プロパティ一覧

  • font-family:フォントの種類を指定
  • font-size:フォントサイズを指定
  • font-weight:フォントの太さを指定
    *フォントによってサポートされない場合がある
    例えば、一部のシステムフォントは400と700しか対応しておらず、最も近い太さに置き換えられる
    • 数字(100~900):値が小さいほど細い、値が大きいほど太い
    • キーワード
      • 100 – Thin(極細)
      • 200 – Extra Light(超細)
      • 300 – Light(細)
      • 400 – Normal(標準)
      • 500 – Medium(やや太)
      • 600 – Semi-Bold(やや太め)
      • 700 – Bold(太字)
      • 800 – Extra Bold(極太)
      • 900 – Black(特太)く
  • font-style:通常のスタイルにするか斜体(イタリック体)にするか
    • normal:通常のスタイルで表示(デフォルト)
    • italic:斜体(イタリック体)で表示
  • text-decoration:下線や打ち消し線
    • none:テキストに装飾を付けない
      リンクの下線を消す場合など
    • underline:テキストに下線を引く
      • text-underline-offset:underlineと一緒につかって下線の位置を調整できる
        text-underline-offset: 3px; ( 3px 下にずらす )
    • overline:テキストの上に線を引く
    • line-through:テキストに打ち消し線を引く
  • text-transform:大文字・小文字の変換
    • none:テキストを変換しない(デフォルト)
    • capitalize:最初の文字を大文字に変換
    • uppercase:全体を大文字に変換
    • lowercase:テキスト全体を小文字に変換
    • full-width:テキストを全角文字で表示
  • text-align:水平方向の配置を指定
    • left:左揃え(デフォルト値、RTL(右から左)の言語以外)
    • right:右揃え
    • center:中央揃え
    • justify:両端揃え
      *日本語のようにスペースが少ない言語では不自然に伸びることがある
      CSS3のtext-justify: inter-word; を併用すると、単語間の均等割り付けが可能
    • start・end:デフォルトの言語設定やdirectionプロパティ に従って、テキストの開始方向(左または右)または終了方向(右または左)にテキストを揃える値
      備考:direction プロパティの値
      ltr:左から右(英語、日本語)
      rtl:右から左(アラビア語、ペルシャ語)
  • text-shadow:テキストに影をつける
    [水平オフセット] [垂直オフセット] [ぼかしの半径] [影の色]
    複数の影を指定可能
    例:3px 3px 5px rgba(0, 0, 0, 0.5);
    • 水平オフセット:影を右(正の値)または左(負の値)にずらす
    • 垂直オフセット:影を下(正の値)または上(負の値)にずらす
    • ぼかしの半径:影をどの程度ぼかすかを指定
      *省略可能、デフォルトは0(影はくっきり)
    • 影の色:影の色を指定
      *省略可能、デフォルトはテキストの色
  • line-height:テキストの行間(行の高さ)を指定
    • 数値(推奨):フォントサイズに対する倍率(単位は不要)
    • 単位付き
    • パーセンテージ
    • normal(デフォルト値): フォントによって自動計算される行間
      *通常フォントサイズの1.2倍程度
  • letter-spacing:テキスト内の文字間隔
    • 数値:文字間隔を単位付き(px、em)で指定
    • normal(デフォルト):フォント固有のデフォルトの文字間隔
  • word-spacing:テキスト内の単語間の間隔を調整
    *日本語や中国語などスペースを使用しない文字は影響しない
  • color:テキストの色を指定

font-family設定のための基礎知識

フォントの種類

  • 総称フォント(ブラウザが自動で代替フォントを選ぶ指定)
    • serif:明朝体やセリフ体
    • sans-serif:ゴシック体やサンセリフ体
    • monospace:等幅フォント(プログラミング向け)
  • システムフォント( OSに依存するフォント)
    (例: Windowsでは「メイリオ」、Macでは「ヒラギノ」など)
  • Webフォント
    環境に依存せず統一可能だが、日本語フォントは容量が大きく表示が遅くなりがち

フォント指定の基本ルール

  • 最初に優先したいフォントを指定(優先度の高い順に書く)
    *英文に「欧文フォント」を使いたいときは、先頭に欧文フォントを指定
  • 最後にフォールバックとして総称フォントを書く(環境依存を防ぐ)

実用的なヒント

  • Webセーフフォント(欧文)
    *ほぼすべてのデバイスに標準でインストールされているフォント
    • sans-serifではArial, Verdana
    • serifではGeorgia, Times New Roman
  • 注意したい日本語フォント
    • 游ゴシック: Windowsでは文字が細く表示されることがある
    • ヒラギノ: Windowsにはインストールされていない
  • 等幅フォント vs プロポーショナルフォント
    • 等幅(monospace): 同じ文字幅、プログラミングに適している
    • プロポーショナルフォント:文字によって幅が異なる、一般的な文章に適している

ゴシック体のフォント設定の例

body {
  font-family: "Helvetica Neue", Arial,
    "ヒラギノ角ゴ Pro W3", "Hiragino Kaku Gothic Pro", 
    "メイリオ", Meiryo, 
    sans-serif;
}

Webフォントについて

「Google Fonts」はCDNから直接読み込めるが、他のWebフォント(有料・無料)はローカルにダウンロードして使う場合が多い
「Google Fonts」は無料で、手軽に使える

Google Fonts の場合(CDN利用)
読み込み方法は<link>@importの2つの方法がある

<!--CSSのレンダリングが最適化されるため、CLSの発生を抑えやすい-->
<head>
  <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet">
</head>
/* CSS内でフォントを一括管理できるが、レンダリングが遅くなりCLSの原因になることがある */
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap');


/*どちらの方法でも、フォントを読み込んだらfont-familyに設定 */
body {
  font-family: 'Roboto', sans-serif;
}

Webフォントはダウンロードして使う場合
ダウンロード後に@font-faceで指定する
*CLS対策としてfont-display: swap;を指定する

font-display: swap;はフォントがまだ読み込まれていないときは、すぐにフォールバックフォントを表示してレイアウトのズレを防ぎ、Webフォントがロードされたら自動で切り替える

/*
swapを指定すると、まずデフォルトフォントを表示し
フォントが読み込まれたら置き換えられ
*FOUTになるがCLS(累積レイアウトシフト)は減る
*/
@font-face {
  font-family: 'CustomFont';
  src: url('custom-font.woff2') format('woff2');
  font-display: swap;
}

body {
  font-family: 'CustomFont', sans-serif;
}

font-sizeについて

フォントサイズは、最低限12px以上、基準値16pxを推奨
iOSでは小さいフォントサイズは、自動的に拡大されることがあり、その解決策として
-webkit-text-size-adjust: 100%;を設定する

htmlでfont-size: 16px;を設定して、remの基準にするのが一般的
理由は、remを基準にすると、ユーザーがブラウザのデフォルトサイズを変更しても適用さる
emは親要素のfont-sizeに依存するため、入れ子構造が深くなると予測が難しくなる

html {
    font-size: 16px; /* ルートフォントサイズ(remの基準) */
}

body {
    font-size: 1rem; /* 基本フォントサイズ */
}

絶対値と相対値

  • システムの文字サイズ設定
    • 絶対値(px): サイズは固定されて変更の影響を受けない
    • 相対値(rem/em): 変更に対応する(レイアウト崩れに注意
  • ブラウザのズーム機能 / スマホのピンチイン・アウト
    ページ全体がズームされるため、相対値でも絶対値でも影響を受ける

テキストの改行

空白や改行全般を制御するプロパティ

white-spaceプロパティ
要素内の空白と改行の扱い全般を指定

  • normal(デフォルト):自動で折り返し、連続する空白を1つにまとめる
  • nowrap:1行で表示し、折り返さない
  • pre:入力された空白や改行をそのまま表示(折り返さない)
  • pre-wrap:空白や改行をそのまま表示しつつ、自動で折り返しも行う
  • pre-line:改行はそのまま保持し、連続する空白はまとめる
  • break-spaces:連続する空白をそのまま保持しつつ、改行が必要な場合には適切に折り返す(CSS3の追加仕様)

長い単語や文字列が幅を超える場合の制御

  • overflow-wrapプロパティ(またはword-wrapプロパティ)
    長い単語や文字列が要素の幅を超えた場合にどう処理するか
    *word-wrapプロパティは過去にInternet Explorer向けに開発されたもので、現在は overflow-wrap推奨
    • normal(デフォルト):折り返さず親要素からはみ出す
    • break-word:長い単語を適宜折り返す
    • anywhere:単語の途中や任意の位置で折り返しを許可
  • word-breakプロパティ
    単語を保持するか、途中で改行するかを指定
    • normal(デフォルト):通常の改行規則(英語は単語単位、日本語は文字単位で改行)
    • break-all:単語の途中でも改行を許可(文字単位で改行)
    • keep-all:単語単位で改行を保持(日本語では文字単位で改行、英語の単語は切り離さない)

主に日本語や中国語の改行ルールの調整

line-breakプロパティ
日本語や中国語の改行ルールを調整

  • auto(デフォルト):自然な改行をブラウザに任せる
  • loose:緩やかな改行(句読点や括弧の直前でも改行を許可)
  • normal:標準的な改行ルール
  • strict:厳格な改行ルール(句読点や括弧の直前では改行しない)
  • anywhere:任意の位置で改行を許可(CSS3の拡張)

日本語と英語の改行の違いとまとめ

  • 日本語は文字単位で改行される
    *単語間のスペースがないため、コンテナの幅に応じて自動で折り返される
    日本語向けプロパティ
    • white-space:空白や改行の全体的な扱いを指定
    • line-break:句読点や括弧の直前での改行ルールを調整
    • word-break:長い日本語文字列が要素幅を超える場合に使う
  • 英語は単語単位で改行される
    *単語間のスペースや特定の区切り文字(例: -、 ?)が改行の目安になり、長い単語やURLがコンテナをはみ出す場合がある
    英語向けプロパティ
    • white-space:空白や改行の扱いを調整
    • overflow-wrap:長い単語を折り返すために必要
    • word-break:単語の途中で切りたい場合に使う

overflow-wrapは日本語では不要
line-breakは英語では不要

/*日本語メインの場合、通常は以下の指定で十分 */
p {
  overflow-wrap: break-word; /* URLや長い英数字を折り返す */
}

/* 
英単語の途中で改行しない、英単語が長すぎる場合は適切な位置で折り返す
日本語は通常通り
*/
p {
  word-break: keep-all;
  overflow-wrap: anywhere;
}

max-content / min-content / fit-content

width・height / max-width・min-width / max-height・min-height
/ flex-basis / grid-template-columns・grid-template-rows
で使えるプロパティ
コンテンツの幅をどこまで広げるか、もしくはどこまで狭くするかを指定する

  • max-content :コンテンツが収まる最大限の幅を確保(テキストや画像が切れない)
  • min-content :コンテンツが収まる最小限の幅を確保
  • fit-content :指定範囲内で収める(max-content と min-content の間)
  • 日本語テキストでは
    • max-content → テキストを1行にした幅
    • min-content → 単語区切りがないので強制改行しない限りmax-contentと同じになりがち
    • fit-content→ 上限を超えたら改行する
  • 英語テキストでは
    • max-content → 1行(スペース含めてフル表示)
    • min-content → 最長単語の幅(単語区切りで改行)
    • fit-content→ min-contentとmax-contentの間で最適化

テキストの省略

単一行の省略

text-overflowプロパティ
テキストが要素をはみ出すときに省略表示する
親要素にoverflow: hidden; またはoverflow: scroll; を指定
子要素にwhite-space: nowrap; を指定して1行に収める

  • clip(デフォルト):テキストを単純に切り捨てる
  • ellipsis:テキスト末尾に「…」を表示
<div style="width: 200px; 
white-space: nowrap; 
overflow: hidden; 
text-overflow: ellipsis;">
  このテキストは省略されます。
</div>

複数行の省略

-webkit-line-clampプロパティ
指定した行数を超えた場合に省略表示する(CSS3)
*現在一部のブラウザ(特にWebKit系)でのみ完全対応

<div style="width: 100px;
 display: -webkit-box; 
 -webkit-box-orient: vertical; 
 -webkit-line-clamp: 3; 
 overflow: hidden;">
  このテキストは3行を超えると省略されます。このテキストは3行を超えると省略されます。
</div>

サイズや領域に基づく省略

  • overflow: hidden / scroll;で要素のはみ出し部分を非表示に
  • heightmax-heightで必要な高さに制限

縦書きに関連するプロパティ

writing-modeで縦書き方向を設定
text-orientationtext-combine-uprightを追加して文字の見た目を調整
日本語特有の改行ルールにはline-break(テキストの改行を参照)を活用

  • writing-modeプロパティ
    テキストの書字方向(縦書き・横書き)を指定
    • horizontal-tb(デフォルト):横書き、上から下に進む
    • vertical-rl:縦書き、右から左に進む(日本語の縦書きスタイル)
    • vertical-lr:縦書き、左から右に進む
  • text-orientationプロパティ
    縦書きテキストでの文字の向きを指定
    • mixed(デフォルト):文字種によって向きを自動調整(例: 日本語は縦、英数字は横)
    • upright:全ての文字を縦に立てたまま表示
    • sideways:全ての文字を90度回転して横向きに表示
  • text-combine-upright
    縦書きの中で数字や短い文字列を1文字幅にまとめて表示
    • none(デフォルト):通常の文字幅で表示。
    • all:複数の文字を1文字幅にまとめて表示。
    • digits X:X桁の数字を1文字幅にまとめて表示
      例) digits 2 は2桁の数字をまとめる

装飾系のプロパティ

(border・outline)枠

borderoutline
ボックスの内側の枠ボックスの外側の枠
レイアウト影響する
*ボックスのサイズに含まれる
レイアウトに影響なし
*ボックスサイズに含まれない
要素の枠線、デザインフォーカス強調、アクセシビリティ
border: 2px solid black; /* 線の太さ, 種類, 色 の一括指定*/
border-width: 1px 2px 3px 4px; /* 上 右 下 左 */
border-style: solid | dashed | dotted | double | groove | ridge | inset | outset | none; /* 枠線の種類 */
border-color: red green blue yellow; /* 各辺の色(上 右 下 左) */
border-radius: 10px; /* 角を丸くする */
border-radius: 10px 20px 30px 40px;/* 左上, 右上, 右下, 左下の順に設定 */
border-radius: 10px 20px;/* 左上&右下、右上&左下を対称に設定 */
border-image: url(border.png) 30 round; /* 画像で枠を作る */
border-collapse: collapse | separate; /* テーブルの境界線を統合 or 分離 */
border-spacing: 10px; /* セルの間隔(`separate`時) */
outline: 2px solid blue; /* 線の太さ, 種類, 色 */
outline-width: 3px; /* 線の太さ */
outline-style: dashed; /* 線の種類 */
outline-color: green; /* 線の色 */
outline-offset: 5px; /* 枠と要素の間の距離 */

(box-shadow・text-shadow)シャドウ

立体感を出したりするための装飾プロパティ

  • box-shadow:要素のボックスに影を付ける
  • text-shadow:文字そのものに影を付ける

box-shadowの基本構文

box-shadow: [offset-x] [offset-y] [blur-radius] [spread-radius] [color];
  • offset-x:影を水平方向にどれだけずらすか(右方向がプラス)
  • offset-y:影を垂直方向にどれだけずらすか(下方向がプラス)
  • blur-radius:省略可・ぼかしの大きさ (デフォルトは0でくっきりした影)
  • spread-radius:省略可・影の広がり具合 (デフォルトは0でプラスで大きく、マイナスで小さく)
    *spread-radiusを指定する場合、blur-radiusも必須
  • color:省略可・影の色 (省略時は要素のcolorに基づく)

オプションとしてinsetをつけると影を内側に入れられる

.my-box {
  box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.3);
}
/* 影を内側に(inset) */
box-shadow: inset 0px 0px 10px rgba(0, 0, 0, 0.3);

/* 影のサイズを大きく(spread-radiusの違い) */
box-shadow: 0px 5px 10px 5px rgba(0, 0, 0, 0.5);

複数のシャドウ
カンマ区切りで書くと、いくつも影を重ねられる

.my-box {
  box-shadow: 
    2px 4px 10px rgba(0, 0, 0, 0.2), 
    0 0 3px rgba(255, 0, 0, 0.5);
}

text-shadowの基本構文

text-shadow: [offset-x] [offset-y] [blur-radius] [color];
  • spread-radiusやinsetはない
  • カンマ区切りで複数のシャドウを重ねられる

(background)背景画像

  • 背景色を指定:background-color
    デフォルトbackground-color: transparent; (親要素の背景が透ける)
    background-clipに影響を受けるが、他のbackgroundプロパテとは独立して動作する
  • 背景画像を指定:background-image
  • 配置 :background-position
    • left: 背景を要素の左端に配置
    • right :背景を要素の右端に配置
    • top: 背景を要素の上端に配置
    • bottom :背景を要素の下端に配置
    • center :背景を要素の中央に配置
    • x% y%: 水平方向(x%)と垂直方向(y%)の位置を割合で指定
      例: 50% 50%(中央)
    • xpos ypos :固定位置を指定
      例: 10px 20px
    • calc() を使うとより細かい制御ができる
      例:calc(50% – 10px) calc(50% – 5px);(中央より少し左にずらす)
    • デフォルト値は “0% 0%”(左上)
  • サイズ :background-size
    • auto :(デフォルト)元の画像サイズそのままで表示します
    • cover :画像を要素全体にフィットさせて、隙間を埋めるように拡大または縮小
    • contain :画像全体が要素内に収まるように拡大または縮小(要素内に余白が残る)
    • x% y% :横幅(x%)と高さ(y%)を割合で指定
    • xpos ypos :横幅と高さを固定サイズで指定
  • 繰り返し:background-repeat
    • repeat :(デフォルト)背景画像を水平方向と垂直方向に繰り返す
    • no-repeat :背景画像を1回だけ表示します
    • repeat-x :背景画像を横方向だけに繰り返す
    • repeat-y :背景画像を縦方向だけに繰り返す
    • space :背景画像を繰り返し、余白を均等に配置(画像のサイズ変更なし)
    • round :背景画像を繰り返し、要素内にフィット(画像のサイズを調整)

制御するプロパティ

  • background-clip :背景をどこまで表示するかを指定
    • border-box: (デフォルト)ボーダーを含めた範囲 まで背景を描画
    • padding-box :パディング内のみ に背景を描画(ボーダー部分は背景なし)
    • content-box :コンテンツ領域のみ に背景を描画(パディング・ボーダー部分は背景なし)
    • text :文字の形に切り抜いて背景を描画
      -webkit-background-clip: text; (要ベンダープレフィックス)
      color: transparent; を設定しないと効果が見えない
  • background-origin: 背景画像の基準位置を指定
    • border-box :(デフォルト)ボーダーの外側から 背景画像を開始
    • padding-box: パディングの外側から 背景画像を開始
    • content-box :コンテンツの外側から 背景画像を開始
  • background-attachment :背景画像をスクロールするか固定するか
    • scroll :(デフォルト)背景画像はスクロールする
    • fixed :背景画像はビューポートに固定される(スクロールしても動かない)
      *パララックス効果に使われる
    • local :背景画像は要素のスクロールとともに動く

backgroundの一括指定

background: <background-color> <background-image> <background-position> / 
            <background-size> <background-repeat> 
            <background-attachment> <background-origin> <background-clip>;

/*シンプルな例*/
.box {
  background: red url(bg.jpg) center / cover no-repeat fixed;
}

複数の背景画像を設定することも可能
background-imageの順番は、最初に書いたものが最前面になる
background-color一番下のレイヤーとして適用されるため、background-imageより後(最後)に書く必要がある

.multi-bg {
  width: 400px;
  height: 300px;
  background: 
    url("pattern.png") repeat,  /*一番上(最前面) */
    url("logo.png") no-repeat center, /*その下の背景 */
    linear-gradient(to bottom, rgba(255, 255, 0, 0.5), rgba(255, 0, 0, 0.5)), /*さらに下の背景 */
    #87CEEB; /* 最も下(最後のレイヤー) */ 
}

グラデーション

グラデーションは背景画像(background-image)の一種

線形グラデーション(linear-gradient)

一直線上に色が変化していくグラデーション

  • 方向(キーワードまたは角度)
  • カラーストップ(色とオプションの位置)を指定
/* 
「左から右」に向かって、最初の色が red(自動的に0%)、最後の色が blue(自動的に100%)に変化
 to top right, to bottom left など、対角線方向を指定可能
 */
background-image: linear-gradient(to right, red, blue);

/* 
45度の方向に沿って、20%地点で red から始まり、80%地点で blue へ変化 
角度は時計回りに測定
0degは上から下、90degは左から右の方向になる(時計回りに角度を測る)
*/
background-image: linear-gradient(45deg, red 20%, blue 80%)

repeating-linear-gradient
linear-gradient() と同じ引数構成で、パターンを繰り返す
*カラーストップによって1周期の範囲が決定され、その周期が繰り返される

/* 
  右方向に、赤から青へ変化するパターンが横幅20pxごとに繰り返される
 */
background-image: repeating-linear-gradient(
  to right,
  red,
  red 10px,
  blue 10px,
  blue 20px
);

放射グラデーション(radial-gradient)

中心から外側へ向けて放射状に色が広がるグラデーション

  • 形状
    • circle:円形
    • ellipse:楕円形(デフォルト)
  • サイズ(グラデーションの広がり方を決定する値)
    • closest-side:最も近い辺まで広がる
    • farthest-side:最も遠い辺まで広がる(デフォルト)
    • closest-corner:最も近い角まで広がる
    • farthest-corner:最も遠い角まで広がる
    • 具体的な長さ(例: 50px、30%)で指定
  • 位置:at でグラデーションの中心を決定
    • at center(デフォルト)
    • at top left
    • at 20% 30%(水平20%、垂直30%の位置)
  • カラーストップ(色とオプションの位置)
    *位置を指定しない場合、ブラウザが自動的に配置

形状・サイズ・位置指定が省略された場合、グラデーションは中心から最も遠い角まで広がる楕円形

background: radial-gradient(
  circle farthest-side at 50% 50%,
  yellow 0%,
  green 100%
);

repeating-radial-gradient()
radial-gradient() と同じ引数構成で、パターンが放射状に繰り返す
カラーストップによって1周期の範囲が決定され、その周期が繰り返される

/* 
 中心を起点に、黄色から緑に変わるパターンが半径30pxごとに繰り返される
 */
background: repeating-radial-gradient(
  circle,
  yellow,
  yellow 15px,
  green 15px,
  green 30px
);

扇形グラデーション(conic-gradient)

円の中心から放射状に色が変化するグラデーション
色を角度で指定

  • from 角度(省略可):開始角度(デフォルトは 0deg)
  • at X% Y%(省略可):グラデーションの中心位置(デフォルトは 50% 50% = 中心)
  • 色と位置(省略可):指定した色ごとに変化する位置を決める
background: conic-gradient(from 角度 at X% Y%, 色1 位置, 色2 位置, ...);

/* 360度のカラーホイール(虹色) のような見た目 */
background: conic-gradient(red, yellow, green, cyan, blue, magenta, red);

repeating-conic-gradient()
conic-gradient() と同じ引数構成で、指定した範囲を繰り返す

/*
red 0deg 30deg → yellow 30deg 60deg
このパターンが360度まで繰り返される
 */
background: repeating-conic-gradient(red 0deg 30deg, yellow 30deg 60deg);

フィルターとブレンドモード

  • フィルターはピクセル単位で見た目を変換するイメージ
    ぼかしや彩度の変更など「写真加工アプリ」的
  • ブレンドモードは色の計算で前景と背景を合体させるイメージ

(filter・backdrop-filter)フィルター

filterbackdrop-filter
対象は要素自身対象は要素の背後
画像やボックスにフィルターを適用背景をぼかしたり加工する
背後のに影響を与えるので要素が完全に不透明だと、背後が隠れてしまいい効果が見えない場合がある
*Safariでは -webkit-backdrop-filterが必須

値について

  • none:フィルター効果を適用しない
  • blur(px):ぼかし(ピクセル単位)
    blur(5px) なら5px分ぼかし
  • brightness(value):明度・brightness(1)がデフォルト値
    2なら2倍明るく、0.5なら暗くなる
  • contrast(value):コントラストcontrast(1)が通常
    2ならコントラスト強め、0.5 なら弱め
  • drop-shadow(offset-x offset-y blur-radius color):要素にドロップシャドウ
    *ただし通常のbox-shadowと挙動が若干異なり、透過部分にも影がかかる
  • grayscale(%):白黒度
    grayscale(100%) で完全なモノクロ・grayscale(0%)は変化なし
  • hue-rotate(deg):色相を回転
    hue-rotate(180deg) で色相環を半周する
  • invert(%):階調を反転
    invert(100%) なら反転・invert(0%) ならもとのまま
  • opacity(%):不透明度
    opacity(50%) なら50%不透明
  • saturate(%):彩度
    saturate(200%) なら2倍の彩度、鮮やかになる
  • sepia(%):セピア加工
    sepia(100%) で完全なセピア色
<div style="width:150px; height:50px; background:red; 
            filter: blur(5px) brightness(0.7);"
></div>

<div style="position:relative;">
  <div style="width:150px; height:50px; background:red;"></div>
  <div style="position:absolute; top:0; left:0; width:100%; height:70%;
              background: rgba(255, 255, 255, 0.3); 
              backdrop-filter: blur(5px);
              -webkit-backdrop-filter: blur(10px);"
  >backdrop-filter</div>  
</div>
backdrop-filter

Safariではfilterプロパティを使うとGPUが効率的に使われず処理が重くなるという報告がある
要素にtransform: translateZ(0); を加えてGPUを有効にするテクニックがあるが、基本的には、filterを多用した背景やアニメーションは重くなるのでパフォーマンスに注意

(mix-blend-mode・background-blend-mode)ブレンドモード

  • mix-blend-mode
    要素自身(前景)とその背後にある要素や背景を、特定のブレンドモードで合成する
  • background-blend-mode
    背景画像(background-image)や色(background-color)が複数指定されている場合、それぞれの背景が独立して描画されますがbackground-blend-mode を利用することで、重なり合った背景同士を指定したブレンドモードで合成できる

主な合成モード(値)

multiply (乗算)常に暗くなる(黒は影響なし、白は変化なし)
screen常に明るくなる(黒は変化なし、白は影響最大)
overlay明るい部分はscreen、暗い部分はmultiply
darken暗い方の色を採用
lighten明るい方の色を採用
color-dodge明るい色を強調(白に近づく)
color-burn暗い色を強調(黒に近づく)
difference色の差を強調(コントラストがはっきり)
exclusiondifferenceよりコントラスト控えめ
hue背景の明度・彩度をそのまま、前景の色相を適用
/*
childはmultiplyの影響を受け、parentの背景とブレンドされる
*/
.parent {
  background: yellow;
}
.child {
  background: red;
  mix-blend-mode: multiply;
}

/*
グラデーション(background-image)と混ざる
*/
.element {
  width: 300px;
  height: 300px;
  background-image: 
    linear-gradient(to right, rgba(255, 0, 0, 0.5), rgba(255, 255, 0, 0.5)),
    url('image.jpg');
  background-blend-mode: multiply;
}

mix-blend-mode
画像の上にテキストを重ねてテキストの色を変化させる

ブレンドモードです

background-blend-mode
背景画像に「黒から白のグラデーション」を重ねている

(isolation)スタッキングコンテキストを生成

isolationプロパティは、要素が新しいスタッキングコンテキストを生成するかを定義する
これにより、要素のmix-blend-modefilterの影響をコントロールできる

  • auto :(デフォルト値) 通常通り
  • isolate :新しいスタッキングコンテキストを作成する
    要素を独立したレイヤーとして扱いブレンドモードの影響を受けないようにする
/*
childは独立したレイヤーとして扱われ、背景のyellowとブレンドされない
*/
.parent {
  background: yellow;
}
.child {
  background: red;
  mix-blend-mode: multiply;
  isolation: isolate;
}

クリッピングとマスキング

クリッピングマスキング
指定した形状の内側のみを表示
外側は完全に非表示
黒~白(輝度)や透明~不透明(アルファチャンネル)を基に、表示・非表示を調整
完全に表示 or 完全に非表示(型抜きフェードアウトや半透明もOK
clip-pathmask-image / mask-mode
-webkit-mask-image が必要
適用対象
境界(ボーダー)を定義する形状データ型
適用対象
画像やグラデーション
SVGのパス使用
clip-path: path(); で可能だが
mask-imageのほうが便利
SVGのパス使用
mask-image: url(svg-mask.svg); で可能

(clip-path)クリッピング

形状データ型(四角形・ 円形・多角形など)や SVGパスを利用して切り抜き可能
要素は切り抜いた形の部分だけが表示され、それ以外は表示されない

.element{
 clip-path: 形状データ型;
}

形状データ型

inset(10px 20px)四角形(内側の余白指定)
circle(50px at 50% 50%)円形
ellipse(60px 40px at 50% 50%)楕円形
polygon(50% 0%, 100% 100%, 0% 100%)三角形や自由な形状
  • inset()
    「上下左右」からの余白を指定して四角形を切り取る
    *上下左右はmarginの一括指定ルールと同じ
    オプションでroundを付けると角丸矩形になる(round 上下左右の角円の半径)
  • circle()
    「中心」と「半径」を指定して、まん丸を作る
    半径 (radius) と 中心 (at X Y) を指定
    省略するとデフォルトは要素の中央 (at 50% 50%) になり、半径は自動計算される場合もある
  • ellipse()
    「横」と「縦」の半径を個別に指定して、楕円を作るイメージ
    2つの半径 (rx ry) と 中心 (at X Y) を指定
  • polygon() :多角形
    「点 (X Y) を結んで」好きな多角形を作るイメージ
    いくつかの頂点の座標を指定して多角形を定義する
    *最後の頂点から最初の頂点に線が引かれ形を閉じる
    座標は (x% y%) や (xpx ypx) のように、ピクセルやパーセントで指定可能
  • path() : SVG のパス
    SVGのパス記法であらゆる曲線・図形を描ける

(余談)
形状データ型は(shape-outside)要素の回り込みの形を決めるプロパティでも使用できる

.circle {
  float: left;
  width: 150px;
  height: 150px;
  shape-outside: circle();
  clip-path: circle(); /* 見た目も円にする */
}

Safariのclip-pathで起きやすい問題と対処法
Safariでは他のブラウザと挙動が異なり、うまくアニメーションしないなどの問題が発生することがある

  1. プレフィック -webkit-clip-pathの必要性
    *Safari14以降ではベンダープレフィックスなしで動く場合が多い
  2. clip-pathのアニメーションが意図しない挙動をする場合は
    カスタムプロパティ(CSS変数)を使ってその変数をアニメーションさせると正しく動く場合があります
.element {
  --radius: 20px;
  clip-path: circle(var(--radius) at 50% 50%);
  -webkit-clip-path: circle(var(--radius) at 50% 50%);

  transition: --radius 1s;
}

.element:hover {
  --radius: 80px;
}

画像やコンテンツを「切り抜き画像の形」で表現したい場合は
clip-pathでSVGのパスを参照する」よりも、「mask-image」を使うと、SVG以外の画像を使用できたり透明度のグラデーションを実装できたりするため便利です

参考まで
「clip-pathでSVGのパスを参照」して画像を切り抜く場合

  1. 可変にする場合はかなり複雑になる
  2. path() はサポートしていないブラウザがあるがるので不安な場合
    SVGに定義されたクリップパス要素を外部リソースとして参照する書式
    clip-path: url(…) で従来からある手法を使ったほうが安定
  3. SVGコンテンツ内だけの話「CSSのclip-pathプロパティ」ではなくてSVGの画像要素に「clip-path属性」を使ってもいい
<svg width="0" height="0" style="display:none" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <clipPath id="myClip">
      <!-- クリップしたい形状を定義 -->
      <path d="M10,10 L90,10 L90,90 L10,90 Z"/>
    </clipPath>
  </defs>
</svg>

<style>
.some-img {
  clip-path: url(#myClip);          /* 同じHTML内ならこれでOK */
  -webkit-clip-path: url(#myClip);  /* Safari/iOS 対応のために併記 */
}
</style>
<!-- 例: 幅・高さを明示して表示する -->
<svg width="320" height="180" 
     xmlns="http://www.w3.org/2000/svg">
  <defs>
    <clipPath id="myClip">
      <path d="M10,10 L90,10 L90,90 L10,90 Z"/>
    </clipPath>
  </defs>
  
  <!-- ここで実際に画像をクリップ -->
  <image href="sample.jpg"
         clip-path="url(#myClip)"
         x="0" y="0" 
         width="320" 
         height="180" />
</svg>

(mask)マスキング

mask-系プロパティは、background-系と同様のイメージ
ブラウザのサポートや(-webkit-mask-)が必要なケースが多い点は注意が必要

  • mask-image
    要素に適用する「マスク画像」を指定
    画像のアルファチャネルまたは輝度mask-modeで設定:デフォルトはアルファチャネル)を使って、要素のどの部分を表示非表示を決定
    *画像ではなく、グラデーション関数(linear-gradient、radial-gradient、conic-gradient)も指定できる
  • mask-repeat
    指定したマスク画像を要素内でどのように繰り返すか
    • no-repeat:(デフォルト)マスク画像を一度だけ描画
    • repeat:横・縦両方向に繰り返す
    • repeat-x: 横方向にのみ繰り返す
    • repeat-y:縦方向にのみ繰り返す
  • mask-position
    マスク画像の描画開始位置を決定
    background-position と同様に、キーワード(center、top、left など)
    パーセンテージ、または長さ(pxなど)で指定
    デフォルト値は “center”( 50% 50%)
  • mask-size
    マスク画像のサイズを指定する
    background-sizeと同様に、キーワード(auto 、cover 、contain)
    パーセンテージ、またはサイズ(pxなど)を指定
    デフォルト値は “auto”(元の画像サイズ)
  • mask-mode
    マスク画像のどの情報を使うかを決定します
    • alpha:(デフォルト)アルファチャネルを利用
    • luminance:輝度を利用

「輝度(luminance)を使う場合」と「アルファチャンネル(alpha)を使う場合」

輝度
mask-mode: luminance;
white(100%明るい) = 完全に表示
black(0%明るい) = 完全に非表示
gray(中間値) = 半透明
アルファチャンネル
mask-mode: alpha;(デフォルト)
alpha = 1(完全に不透明)= 完全に表示
alpha = 0(完全に透明)= 完全に非表示
alpha = 0.5(50%透明)= 半透明

mask-imageを使って画像の切り抜き

img{
  mask-image: url("枠になる画像のパス");
  mask-size: contain;
  mask-repeat: no-repeat;  
  mask-position: 50% 0;
 -webkit-mask-image: url("枠になる画像のパス");
 -webkit-mask-repeat: no-repeat;
 -webkit-mask-size: contain;
 -webkit-mask-position: 50% 0; /* マスク画像を横中央、上寄せに配置 */
}

グラデーションによるフェードアウト
画像の上部は完全に表示され下部に向かって徐々にフェードアウト

/*アルファチャネルを利用*/
img{
  width:100%;
  height:auto;
  /*上部は不透明(例として赤)から下部は透明になるグラデーション*/
  mask-image: linear-gradient(red 0%, transparent 100%); 
 -webkit-mask-image: linear-gradient(black 0%, transparent 100%); 
}

/*輝度を利用*/
img {
 /*上部は白(完全に表示)から下部は黒(完全に非表示)になるグラデーション*/
  mask-image: linear-gradient(white 0%, black 100%);
  mask-mode: luminance; /* 明度を利用 */
  -webkit-mask-image: linear-gradient(white 0%, black 100%);
  -webkit-mask-mode: luminance;
}

(visibility ・opacity)表示状態

  • opacity:要素の透明度を連続的に変化させるプロパティ
    • 0(完全に透明)から1(完全に不透明)の範囲で設定
  • visibility:要素の表示状態(表示 or 非表示)を制御するプロパティ
    • visible:表示
    • hidden:非表示、ただしスペースは保持
    • collapse:特定の状況で主にテーブル要素において、非表示かつスペースも縮小
opacity: 0;visibility: hidden;display: none;
透明にする
スペースは確保
クリックできる
非表示にする
スペースは確保
クリックできない
要素を消す
スペースは確保しない
クリックできない

その他

(cursor)カーソルの種類

マウスカーソルの見た目を変える

デフォルト値はcursor: auto;でブラウザや要素の種類によって、自動的に適切なカーソルが選ばれる

  • 通常の要素 → default(矢印)
  • aタグやbuttonタグ → pointer(手のひら)
  • input[type=”text”] → text(Iバー)
/* 基本のカーソル */
.cursor-default { cursor: default; } /* 普通の矢印 */
.cursor-pointer { cursor: pointer; } /* 手のひら(クリックできる) */
.cursor-text { cursor: text; } /* テキスト選択時のIバー */
.cursor-move { cursor: move; } /* 移動用のカーソル */
.cursor-grab { cursor: grab; } /* 掴めるカーソル */
.cursor-grabbing { cursor: grabbing; } /* 掴んでる時 */

 /* 特殊なカーソル */
.cursor-not-allowed { cursor: not-allowed; } /* 使用禁止(×マーク) */
.cursor-wait { cursor: wait; } /* 読み込み中(くるくる) */
.cursor-help { cursor: help; } /* ヘルプ(?マーク) */
.cursor-progress { cursor: progress; } /* 作業中(矢印+くるくる) */

 /* カスタムカーソル(画像) */
.cursor-custom {
  cursor: url('custom-cursor.png'), auto;
}

(list-style)リストの装飾

リスト(ulタグolタグ)のマーカーを変更

  • ulタグのデフォルトはdisc(黒丸)
  • olタグのデフォルトはdecimal(数字)
/* マーカーの種類 */
.list-disc { list-style-type: disc; } /* 黒丸(●) */
.list-circle { list-style-type: circle; } /* 白丸(○) */
.list-square { list-style-type: square; } /* 四角(■) */
.list-decimal { list-style-type: decimal; } /* 数字(1,2,3) */
.list-roman { list-style-type: lower-roman; } /* ローマ数字(i, ii, iii) */
.list-alpha { list-style-type: upper-alpha; } /* ABC順 */

/* マーカーの位置 */
.list-outside { list-style-position: outside; } /* デフォルト(マーカーが外側) */
.list-inside { list-style-position: inside; } /* マーカーを内側に */

 /* カスタム画像をマーカーに */
.list-custom {
  list-style-image: url('custom-marker.png');
}

/* list-styleにtype position image をまとめて指定できる */
ul {
  list-style: square inside url('custom-marker.png');
}

(quotes)引用符の装飾

引用符のデザインをカスタマイズ

デフォルト値はquotes: auto;でブラウザごとに適切な引用符が適用される

  • 英語圏 → “ ” や ‘ ’
  • 日本語 → なし(「」 や 『』 はデフォルトでは適用されない)
    日本語で引用符を表示させたい場合は、明示的に設定する必要がある
/* デフォルト(通常の “”) */
p {
  quotes: auto;
}

/* 日本語用の「」を適用 */
.quotes-jp {
  quotes: "「" "」" "『" "』";
}

/* 欧文のカスタム引用符 */
.quotes-custom {
  quotes: "“" "”" "‘" "’";
}

/* コンテンツ内で引用符を使う */
.quote::before {
  content: open-quote;
}
.quote::after {
  content: close-quote;
}

(ruby)ルビの装飾

ふりがな(ルビ)をつけるときのプロパティ
rubyタグはrtタグとセットで使う

デフォルトは

  • ルビは上に(ruby-position: over;
  • 均等配置(ruby-align: space-around;
/* HTMLでルビを設定 */
<ruby>
  漢字<rt>かんじ</rt>
</ruby>

/* ルビの位置 */
.ruby-top { ruby-position: over; } /* 上にルビ(デフォルト) */
.ruby-bottom { ruby-position: under; } /* 下にルビ */

 /* ルビの配置 */
.ruby-space-distribute { ruby-align: space-around; } /* 均等配置(デフォルト) */
.ruby-center { ruby-align: center; } /* 中央揃え */


/* ルビのフォントサイズを調整 */
ruby rt {
  font-size: 0.8em;
  color: red;
}

動作系のプロパティ

(pointer-events)クリックの可否

要素をクリックできるかどうかを制御
クリックやホバーを無効化したいときに使う

動作クリックテキスト選択
auto(デフォルト)通常の動作(デフォルト)可能可能
none完全に無効化不可不可
visiblePaintedSVG専用可能(塗られた部分)不可
visibleFillSVG専用可能(塗られた部分)可能
visibleStrokeSVG専用可能(線部分)可能
visibleSVG専用SVGのすべての部分をクリック可能可能

上に透明なオーバーレイを配置、下の要素はクリック可能」にしたい時
pointer-events: none;を使う

.overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.5);
  pointer-events: none; /* この要素を完全に無視! */
}

button {
  position: relative;
  z-index: 1; /* 下にあるけど、クリックできる! */
}

(user-select)テキスト選択の可否

テキストを選択できるかどうかを制御
コピペ防止や、特定要素だけ選択可能にしたいときに使う

動作ダブルクリック時の挙動
auto(デフォルト)通常の選択テキスト選択可
noneテキスト選択不可
(コピー防止)
選択できない
textテキスト選択可能
(モバイルでコピー可)
選択できる
all1回クリックで全体を選択全選択
contain内部テキストのみ選択可選択可(内側だけ)
word単語単位で選択ダブルクリックで単語単位

(scroll-behavior)スムーススクロール

ページ内リンクやスクロール時の動きを制御
スムーススクロール(なめらかに移動)を適用したいときに使う

/* 通常のスクロール(即時移動) */
html {
  scroll-behavior: auto;
}

/* 
スムーススクロールを有効化 
ページ内リンク(#id)でスクロールがなめらかに
*/
html {
  scroll-behavior: smooth;
}

scroll-behavior: smooth; overflow: hidden; だと機能しない

通常はhtmlに適用して、ページ内リンクのスクロールを滑らかにするが
overflow: scroll(特定の要素内でのスクロール) でも機能する

.scroll-box {
  width: 300px;
  height: 200px;
  overflow: scroll;
  scroll-behavior: smooth;
}

SafariはCSSのscroll-behavior: smooth; 対応していないので
JSで実装するのが確実

scrollTo()メソッドscrollIntoView()メソッドGSAP scrollToPlugin
座標を指定してスクロール要素の位置に応じて自動スクロール高度なアニメーションスクロール
縦スクロール / 横スクロール指定ができるできないできる
スクロール位置の詳細指定
できない
できるできる
細かいアニメーション制御できないできないできる
(ease など追加可能)

(補足)JSのscrollTo()とscrollIntoView()メソッド

scrollTo()(指定位置へスクロール)
*windowとelementに使える
*top(縦スクロール)や left(横スクロール)を指定できる

//ページ全体のスクロールを制御
window.scrollTo({
  top: 500, // 500px の位置へスクロール
  behavior: "smooth" // スムーススクロール
});

//特定の要素のスクロールを制御
document.querySelector(".scroll-box").scrollTo({
  top: 100,
  behavior: "smooth"
});

scrollIntoView()(要素を画面内にスクロール)
指定した要素を「スクロールして画面内に表示」

document.querySelector(".target").scrollIntoView({
  behavior: "smooth",
  block: "start" // "start", "center", "end", "nearest"
});

//ボタンをクリックすると #section2 へスムーズにスクロール
document.querySelector(".scroll-btn").addEventListener("click", () => {
  document.querySelector("#section2").scrollIntoView({ behavior: "smooth" });
});
start(デフォルト)スクロールして要素を画面の上端に配置画面の上に要素がくる
centerスクロールして要素を画面中央に配置画面の真ん中に表示
endスクロールして要素を画面の下端に配置画面の下に表示
nearestできるだけ少ないスクロール量で表示既に画面内ならスクロールしない

CSSアニメーションとトランスフォーム

要素の見た目や位置、形状などを時間の経過とともに変化させ、動的な視覚効果を与える
主な手法

  • transitionプロパティ
    ユーザー操作や状態の変化(例:ホバー時など)に応じた2つの状態間の変化を定義(シンプルな補間効果)
  • animationプロパティ
    キーフレーム(@keyframes)を使って複数段階のアニメーションを作成でき、繰り返しや再生方向などの詳細な制御が可能

アニメーション可能なCSSプロパティはたくさんありますが
transform(拡大縮小、回転、移動など)やopacity(透明度)はGPUによる最適化が可能で、アニメーションのパフォーマンスが向上するため推奨される

(transition)トランジション

  • transition-property→ 「どのプロパティを変化させるか」
    (デフォルト):all(変化するすべてのプロパティ)
    例)background-color、opacity など
  • transition-duration→ 「変化にかかる時間」
    (デフォルト):0s
    例)0.3s(0.3秒)、500ms(500ミリ秒)
  • transition-timing-function→ 「変化の加速・減速のカーブ」
    • linear:最初から最後まで一定の速さ
    • ease:(デフォルト)最初と最後はゆっくり、中間が速い
    • ease-in:最初はゆっくり、後から速くなる
    • ease-out:最初は速く、最後はゆっくり
    • ease-in-out:最初と最後がゆっくりで、中間が速い
    • cubic-bezier(x1, y1, x2, y2):自分で加速カーブを定義できる
      *cubic-bezierの値は、「Chromeの開発者ツール」で確認できます
  • transition-delay→ 「変化を始めるまでの時間」
    (デフォルト): 0s(すぐに開始)
    例)0.5s(0.5秒後に開始)

一括指定

.button {
/*
transition: transition-property, 
            transition-duration, 
            transition-timing-function, 
            transition-delay
*/
  transition: background-color 0.3s ease 0s;
}

(animation)アニメーション

  • animation-name→「 @keyframesの名前を指定」
    (デフォルト):none
  • animation-duration→ アニメーションの時間
    (デフォルト):0s
  • animation-timing-function→「 進行の加速・減速カーブ」
    ease、linear、ease-in、ease-out、ease-in-out、cubic-bezier(…) など
    (デフォルト): ease
  • animation-delay→ 開始までの遅延時間」
    直感的な説明
    (デフォルト): 0s
  • animation-iteration-count→ 「何回繰り返すか」
    → 1、0.5(半分)、infinite(無限ループ) など
    (デフォルト):1
  • animation-direction→ 「再生方向を指定(順/逆/交互)」
    • normal:(デフォルト)通常通り
    • reverse:逆再生
    • alternate:交互に再生(初回は通常の順序から)
    • alternate-reverse:交互に再生(初回は逆再生から)
  • animation-fill-mode→ 「アニメ前後のスタイルを保持するか」
    (アニメーション前後で、要素がどんな見た目を保つか)
    • none:(デフォルト)アニメーションの効果が実行中のみ表示され、アニメーション前後は影響がない
    • forwards:最後の結果をキープ
      アニメーションが終了した後、要素は最後のキーフレームのスタイルを維持
    • backwards:最初の状態を先取り
      アニメーションが始まる前(特に delay がある場合)、要素は最初のキーフレームのスタイルをすぐに適用
    • both:前も後もアニメーションの効果を持続
      アニメーション開始前は最初のキーフレームのスタイル、終了後は最後のキーフレームのスタイルをそれぞれ適用
  • animation-play-state→ 「アニメを一時停止するか(JavaScriptで制御)」
    *「停止したアニメーションを再開」すると「停止した位置」からアニメーションが始まる
    • running : (デフォルト)実行中
    • paused : 停止中

一括指定

/*
animation: animation-name, 
           duration, 
           timing-function, 
           delay, 
           iteration-count, 
           direction, 
           fill-mode, 
           play-state
*/

キーフレームの定義

@keyframes 名前を使って、0%から100%(または fromとto)までの各段階で適用するスタイルを記述

.box {
  width: 100px;
  height: 100px;
  background-color: #3498db;  /* 初期は青 */
  margin: 50px auto;
 /* キーフレームアニメーションの適用 */
  animation: fade 3s ease-in-out infinite;
 }    

@keyframes fade {
      0% {
        opacity: 1;                 /* 不透明 */
        background-color: #3498db;  /* 青 */
      }
      50% {
        opacity: 0.5;                /* 半透明 */
        background-color: #e74c3c;   /* 赤に変化 */
      }
      100% {
        opacity: 1;                 /* 不透明に戻る */
        background-color: #3498db;  /* 青に戻る */
      }
    }

(transform)トランスフォーム

2Dトランスフォーム

2D(平面)上で要素を移動(translate)・回転(rotate)・拡大縮小(scale)・傾斜(skew)

transformプロパティ(基本構文)

transform: 値;

/* 
複数の操作を組み合わせる場合、左から順に実行される
*/
transform: translateX(50px) rotate(30deg) scale(1.5);

2Dトランスフォーム(transformプロパティの値)

  • 移動
    %指定は自身のサイズ に対する割合(親要素の幅ではない)
    • translateX(px % em/rem vw/vh) :水平方向に移動
      translateX(50px) 右に50px移動
      *tマイナス値は左・プラス値は右
    • translateY(px % em/rem vw/vh) :垂直方向に移動
      translateY(-30px) 上に30px移動
      マイナス値は上・プラス値は下
    • translate(x, y) :X軸とY軸を同時に移動(Yは省略可、省略すると0
  • 回転
    • rotate(deg)
      プラス値は時計回り・プラス値は反時計回り
    • 回転の基準点(transform-origin)のデフォルトは中央(center)
  • 拡大縮小
    • scaleX(数値) :横幅を拡大縮小
      scaleX(1.5) 横1.5倍
    • scaleY(数値): 縦幅を拡大縮小
      scaleY(0.8) 縦 80%
    • scale(x, y) :XとYを同時に拡大縮小(Yは省略可、省略するとXの値
  • 傾斜
    • skewX(deg) :X方向に傾斜
    • skewY(deg) :Y方向に傾斜
    • skew(x, y) :XとYを同時に傾斜(Yは省略可、省略すると0
  • 行列
    matrix(a, b, c, d, e, f)
    すべての2D変形を1つの関数で指定
    行列の計算になるので複雑
    • scaleX(sx) (sx, 0, 0, 1, 0, 0)
    • scaleY(sy) (1, 0, 0, sy, 0, 0)
    • skewX(angle) (1, tan(angle), 0, 1, 0, 0)
    • skewY(angle) (1, 0, tan(angle), 1, 0, 0)
    • rotate(angle) (cos(angle), sin(angle), -sin(angle), cos(angle), 0, 0)
    • translate(tx, ty) (1, 0, 0, 1, tx, ty)

transform-originプロパティ
変形の基準点(どこを中心に変形するか)
transform-originはrotateの回転の中心点を変更できるだけでなく、scaleやskewの変形の基準点にもなる

  • X軸(横方向)の基準点→left, center, right, px, %
  • Y軸(縦方向)の基準点→top, center, bottom, px, %
transform-origin:X Y;

transform-origin: left top; /* 左上を基準に */ 

transform-origin: 50% 100%; /* 下中央を基準に */

3Dトランスフォーム

2Dトランスフォームの X軸・Y軸に、Z軸(奥行き)を加えた3Dトランスフォーム
perspective(視点の設定)を適用すると、Z軸の動きにも遠近感が生じ、立体的な表現が可能になる

perspectiveの2つの設定方法

親要素にperspectiveを設定要素自身にperspectiveを設定
子要素は3Dの影響を受ける
transform-styleのデフォルトflat(子要素に3Dの影響が伝わらない)なので
transform-style: preserve-3d; が必要
子要素は影響を受けない
その要素だけ3D効果
複数の子要素を3D空間内で操作する場合特定の要素だけ3D効果を適用する場合
perspective-originの適用可能
カメラの視点(どこから見ているか)を変更
*デフォルト値はcenter center
(画面の中央から見ている)
適用不可

perspective-origin: X Y;で設定できる値
X軸(横方向)→ left, center, right, px, %
Y軸(縦方向)→ top, center, bottom, px, %

/*親要素に*/
.parent {
  perspective: 800px;
  transform-style: preserve-3d;
}
.child {
  transform: rotateY(30deg);
}

/*その要素に*/
.child {
  transform: perspective(800px) rotateY(30deg);
}

perspective(視点)の仕組み

カメラ(視線)は、画面(z=0) よりも後ろ(負の方向)にある
つまり、perspectiveの数値が画面(z=0)とカメラ(視線)の距離 を決める

小さい値(例: 200px)カメラが画面のすぐ近く遠近感が強い
(奥行きが強調される)
大きい値(例: 1000px)カメラが遠くにある遠近感が弱い
(奥行きの変化が少ない)

3Dトランスフォーム(transformプロパティの値:追加分)

  • 移動
    • translateZ(px) Z軸はpxのみ
      マイナス値は奥、プラス値は手前
    • translate3d(x, y, z) :3D移動(X, Y, Z まとめて)
  • 回転
    rotateZ(deg) はZ軸を中心に回転なのrotate(deg)と同じ
    • rotateX(deg) :X軸を中心に回転
    • rotateY(deg) :Y軸を中心に回転
    • rotate3d(x, y, z, deg) :自由な回転軸を設定可能
      *最初の3つ「回転軸の方向」を表すベクトル(x, y, z の比率)
      例)rotate3d(1, 1, 0, 45deg)はX軸とY軸を均等に影響させた斜めの軸で回転
  • 傾斜
    • scaleZ(数値) :Z方向の拡大縮小
    • scale3d(x, y, z) :3Dスケール(X, Y, Z まとめて)

回転と軸のイメージ

transform-originは回転やスケールの基準点(どこを中心に変形するか)を指定するプロパティですが、3Dでは X軸・Y軸 に加えてZ軸(奥行き方向)の基準点(pxのみ)も指定できます

transform-origin: X Y Z;

transform-origin: center center 0px; /*デフォルト 要素の中央を基準*/

/*
100px手前を基準に回転するので、回転の動きがより強調される
(視点に近い部分がより大きく回る)
*/
.box {
  transform-origin: center center 100px;
  transform: rotateY(45deg);
}

/*
100px奥を基準に回転するので、回転の動きが小さくなり、
遠くで回っているように見える
*/
.box {
  transform-origin: center center -100px;
  transform: rotateY(45deg);
}

裏面を表示するか
backface-visibilityプロパティ
*裏返しアニメーションでよく使う(カードの裏面を非表示にする)

/*裏側を隠す*/
.card {
  transform: rotateY(180deg);
  backface-visibility: hidden;
}

備考:SafariのtranslateZ+z-indexのバグ

SafariではtranslateZを設定した要素は、z-indexの影響を受けずに前に出る

/*
Safariでは box1(z-index:10 )が translateZ(100px); により 
box2(z-index:999)より前面に表示される
*/
.box1 {
  position: absolute;
  z-index: 10;
  background: red;
  transform: translateZ(100px);
}
.box2 {
  position: absolute;
  z-index: 999; /* こちらを前に出したい */
  background: blue;
}

対策:transform: translateZ(0);を親要素に設定する

.parent {
  transform: translateZ(0); /* Safariのバグ回避 */
}

.box1 {
  position: absolute;
  z-index: 10;
  background: red;
  transform: translateZ(100px);
}
.box2 {
  position: absolute;
  z-index: 999; /* こちらで正しく前面にくる */
  background: blue;
}

パフォーマンス最適化

ページの表示速度を向上させ、スムーズな動作を実現するための最適化手法
CSSレベルでの最適化には、以下のプロパティが役立つ

パフォーマンス向上のためのプロパティ

will-change事前に「変化する」ことをブラウザに伝え、レンダリングを最適化
contain要素の影響範囲を制限し、レイアウト計算の負荷を軽減
content-visibility画面外の要素の描画を遅延し、スクロール時の負荷を低減

(will-change)変更を予測して最適化

ブラウザに「これから変化する」ことを事前に伝え、アニメーションやスクロール時のカクつきを抑える
特にtransformopacityのアニメーション時に効果を発揮

そもそも、transformopacityは通常GPUで処理されるため
ほとんどの場合will-changeなしでスムーズに動くが
「アニメーションがカクつく or 途中でガクっとなる」場合にwill-changeを使うと
スムーズになることがある

スクロール時のsticky( stickyする要素がガクつく)やrequestAnimationFrame(JSでアニメーションを大量に処理)を使った処理に有効

/* 
transform
要素をスムーズに移動・回転・拡縮したいとき
*/
.card {
  will-change: transform;
}

/* 
opacity
フェードイン・フェードアウトがガクつくとき
*/
.fade-in {
  will-change: opacity;
}

/* 
position: sticky;(スクロール時に要素を固定する)で使うと
スクロールがスムーズに
*/
.sticky-header {
  will-change: transform;
}

will-change使いすぎhoverでの使用はブラウザが余計なリソースを使うのでNG

アニメーション終了後 will-changeをリセットすると、不要な負荷を減らせる

.element {
  will-change: transform;
  transition: transform 0.5s ease;
}

/* アニメーション終了後にリセット */
.element.done {
  will-change: auto;
}

(contain)要素の影響範囲を制限

ブラウザのレンダリング最適化(不要な再描画や再計算を防ぐ)に役立つ
contain: layout; はBFCと似た動作しつつ、レンダリング最適化

  • layout :レイアウトの影響を遮断(外部のレイアウト変更が影響しない)
  • paint :ペイント(描画)を遮断(要素の外に描画しない)
  • size :サイズ計算を遮断(要素の幅や高さが変わっても外部のレイアウト計算に影響を及ぼさない)
  • content :layout + paint(子要素のレイアウトと描画の影響を閉じ込める)
  • strict :layout + paint + size(最も制限が強い)
  • none:(デフォルト)通常通りのレンダリング
/*
カード型UI
親要素の変更が .cardのレイアウトに影響しなくなる
*flexやgridの要素に適用するとレイアウトが崩れることがある
*/
.card {
  contain: layout;
}

/*
モーダル
中の描画が、外部に影響を与えなくなる
*/
.modal {
  contain: paint;
}

/*
ウィジェットや広告
完全に閉じ込める
.widget の中で完結し、外のレイアウトに影響を与えない
*/
.widget {
  contain: strict;
}

(content-visibility)画面外の要素を描画

スクロールで画面に入るまでコンテンツをレンダリングしないことで、初回の描画負荷を軽減

  • visible :(デフォルト)通常の動作(常にレンダリング)
  • hidden :完全に非表示(レイアウト計算もなし)
  • auto:画面に入るまでレンダリングを遅延
    スクロールして画面に入るまで描画されないのでパフォーマンスが向上
/*
.sectionがビューポート内なら、普通にレンダリングされる! 
ビューポート外なら、スクロールして見えるまで描画が遅延
*/
.section {
  content-visibility: auto;
}

CLS対策について

CLS(累積レイアウトシフト)とは、Googleがウェブサイトの視覚的な安定性を評価する指標のひとつで、ページの予期しないレイアウトシフトの合計値
CLSを下げることで、SEOの評価が上がり & ユーザー体験が向上

画像や動画のサイズをHTMLの属性で明示、CSSで上書き

<img src="image.jpg" width="600" height="400">
img {
  width: 600px;
  height: 400px;
}

Webフォントの読み込み
ダウンロードしたWebフォントを利用する場合font-display: swap;を設定
Google FontsをCDN利用する場合は<link>で読み込む

@font-face {
  font-family: 'CustomFont';
  src: url('custom-font.woff2') format('woff2');
  font-display: swap;
}
<head>
  <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet">
</head>

広告や埋め込みコンテンツのスペースを確保

.ad-container {
  min-height: 250px; /* 事前に高さを確保 */
}

遅延読み込みの要素でも高さを確保

.lazy-load {
  display: block;
  min-height: 200px;
  background-color: #eee; /* プレースホルダー */
}

アクセシビリティについて

アクセシビリティ(A11Y)とは、あらゆるユーザーがページを快適に利用できるかを考慮する概念
視覚・聴覚・運動機能の制約がある人でも快適に使えることが目的

アクセシビリティ基準「WCAG(国際基準)」
*「JIS X 8341-3」は、WAIC(日本のアクセシビリティ普及活動を行う団体)の規格で、「JIS X 8341-3」も「WCAG」に基づいている

  • A(最低限の基準)
  • AA(推奨基準:多くのユーザーが快適に利用可能)
  • AAA(最も厳しい基準:全ユーザーに最適)

アクセシビリティを意識したCSS

視覚的なデザイン・ユーザー体験(色・フォーカス・非表示など)

視認性
文字を読みやすくする(フォントサイズ・コントラスト)

  • 基本のフォントサイズは16px以上推奨(WCAG基準)
  • remを使って、ユーザーの設定に応じたサイズ調整が可能
  • 行間(line-height)は 1.5 〜 1.8 程度に設定すると読みやすい
  • 文字と背景のコントラスト比は 4.5:1 以上推奨(WCAG AA 基準)
    *大きな文字の場合は 3:1 でもOK

クリックしやすいデザインにする(ボタンやリンクのサイズ)

  • ボタン・リンクのサイズは「48px × 48px」以上が理想(WCAG推奨)
    小さすぎるとタップしづらく誤クリックが増える
  • paddingを調整して、クリック範囲を広げる
  • 隣接する要素と適度な間隔を確保(gapmarginを活用)
  • クリックできることを視覚的に明確にする(ホバー時の変化、リンクの下線など)

フォーカスの可視化
*キーボード操作をサポートする

デフォルトでフォーカス可能な要素(ブラウザがフォーカスをつけている要素)

  • <a> href属性があればフォーカス可能
  • <button> <input> <select>はデフォルでフォーカス可能

*フォーカスされない<div><span>などにtabindex="0"をつけるとフォーカス可能にできるが、デフォルトでフォーカスできる要素を活用し、不要なtabindexの乱用を避けるのがベスト

キーボード操作では、フォーカス(現在どの要素を操作しているか)が見えることが重要
outline: none; は使わない

button {
  outline: none; /* 絶対にしない! */
}

/* 見やすいフォーカススタイルを設定 */
button:focus {
  outline: 2px solid blue;
  outline-offset: 2px;
}

/* キーボード操作時のみフォーカスが表示(マウス操作時には非表示) */
button:focus-visible {
  outline: 3px solid orange;
}

/* 
フォーム全体をフォーカスしたときに、外枠を強調できる
フォーカスが親要素にも影響する
*/
form:focus-within {
  border: 2px solid #007BFF;
  border-radius: 5px;
}

スクリーンリーダー(音声読み上げソフト)に配慮する

visibility: hidden; display: none; を使うと、スクリーンリーダーでも読まれないので
スクリーンリーダーには読ませたいが、画面には表示させたくない場合は 「.sr-only」クラスを使って非表示にする

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  border: 0;
}
<p class="sr-only">このメッセージはスクリーンリーダー専用</p>

スキップリンクの実装
*スクリーンリーダーやキーボード操作のユーザーが毎回ヘッダーのナビゲーションを通過する負担を軽減する

/* スキップリンクを通常は隠し、フォーカス時に表示 */
.skip-link {
  position: absolute;
  left: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.skip-link:focus {
  position: absolute;
  left: 20px;
  top: 20px;
  background: #ffffff;
  padding: 10px 15px;
  border: 2px solid #000;
  text-decoration: none;
  width: auto;
  height: auto;
  z-index: 1000;
}
<a href="#main" class="skip-link">メニューをスキップする</a>

<header>
  <nav>...</nav>
</header>

<main id="main">
  <h1>メインコンテンツ</h1>
</main>

(補足)スクリーンリーダーのためHTMLと補助的な属性

適切なマークアップ・フォームのラベル付け・WAI-ARIAの適切な活用

「WAI-ARIA」はスクリーンリーダーが正しく情報を理解できるようにするための属性のセットで
role(役割)、aria-*(要素の説明や状態)を使って情報をつたえる

HTMLを適切に使えば、ほとんどの場合「WAI-ARIA」は不要
HTMLを正しく書くのが第一
*むやみにaria-* をつけすぎると、逆にスクリーンリーダーが混乱する

HTMLを正しく書く

  • 見出し(<h1> ~ <h6>)を適切に使い
  • ランドマーク要素(<header> <nav> <main> <aside> <footer>)を活用
    *ちなみに<section>はランドマーク要素ではなくaria-labelledbyで見出しを関連付けると、ナビゲーション可能なランドマークとして扱うことがある
  • フォーカスできる要素(<button> <a> <input> <select>)を正しく使う

画像にはalt属性を適切に設定する(飾り画像には alt="" を指定)
*スクリーンリーダーは alt=""の画像を無視する

<img src="profile.jpg" alt="山田太郎のプロフィール写真">
<img src="border.png" alt="">

アイコンだけでは意味が伝わらないため、aria-labelで意味を補足

<button aria-label="メニューを開く">
  <i class="fa fa-bars"></i>
</button>

意味のない装飾アイコンは、読み上げの対象外にする
スクリーンリーダーに不要な要素はaria-hidden="trueを設定

<i class="fa fa-check" aria-hidden="true"></i>

フォームのアクセシビリティ

<!--  
labelとinputのidを適切に関連付ける
クリック時にinputにフォーカスが当たり、スクリーンリーダーが正しく読み上げる
-->
<label for="username">ユーザー名</label>
<input type="text" id="username">

<!--  
placeholderではなくlabelを使う
<input type="email" placeholder="メールアドレス">のように
placeholderだけだとスクリーンリーダーの読み上げや視認性の問題が発生
-->
<label for="email">メールアドレス</label>
<input type="email" id="email">

メニューボタンやトグルボタンには<button>を使うべき
<div><span>role="button"をつけるのは非推奨(フォーカスなどの追加の対応が必要になる)
*ちなみにこれは、スクリーンリーダーではなく開発上のルールですが
一般的に<button type="button">のようにtype="button"を明示して
意図しないフォーム送信を防ぐ(デフォルトはsubmit)

メニューの開閉ボタンではaria-expandedをJSで書き換えて、スクリーンリーダーに状態を伝える

<!-- 
メニュー開閉ボタン 
aria-controls="menu"でこのボタンはid="menu"の要素を制御することを明示
-->
<button aria-expanded="false" aria-controls="menu" onclick="toggleMenu()">
  メニュー
</button>

<!-- メニュー(最初は hidden で非表示) -->
<ul id="menu" hidden>
  <li><a href="#">項目1</a></li>
  <li><a href="#">項目2</a></li>
</ul>

<script>
  function toggleMenu() {
    const button = document.querySelector("button");
    const menu = document.getElementById("menu");

    // aria-expanded の現在の状態を取得
    const isExpanded = button.getAttribute("aria-expanded") === "true";

    // aria-expanded を切り替え(true → false / false → true)
    button.setAttribute("aria-expanded", !isExpanded);

    // hidden を切り替え(true → false / false → true)
    menu.hidden = isExpanded;
  }
</script>

メニューの開閉だけでもこのような実装が必要になり、複雑なUIではスクリーンリーダー対応はとても難しくなる💦