【CSS】placeholderのスタイル完全ガイド|色・フォント変更からフローティングラベルまで

【CSS】placeholderのスタイル完全ガイド|色・フォント変更からフローティングラベルまで HTML/CSS

フォームの入力欄に薄いグレーで表示されるプレースホルダーテキスト。デフォルトの見た目はブラウザ任せですが、CSSの::placeholder疑似要素を使えば色・フォントサイズ・字間など自由にカスタマイズできます。

この記事では、基本の色変更から:placeholder-shownを使ったフローティングラベル、フォーカス時アニメーション、ダークモード対応、アクセシビリティの注意点まで、placeholderのスタイリングに必要な知識をすべてまとめました。

この記事で分かること

::placeholder疑似要素でplaceholderの色・フォント・サイズを変更する方法、適用できるCSSプロパティの一覧、:placeholder-shown疑似クラスを使ったフローティングラベルの実装、フォーカス時のアニメーション、ダークモード対応、そしてplaceholderをラベル代わりに使ってはいけない理由まで解説します。

スポンサーリンク

::placeholder 疑似要素の基本

::placeholderは、<input><textarea>のplaceholder属性で指定したテキストにスタイルを適用する疑似要素です。

/* placeholderの色を変更 */
::placeholder {
  color: #94a3b8;
}

/* 特定の要素のplaceholderだけ変更 */
.search-input::placeholder {
  color: #64748b;
  font-style: italic;
}

デフォルトのplaceholder
カスタムplaceholder

ベンダープレフィックスはもう不要

かつては以下のようにブラウザごとのプレフィックスが必要でした。

/* 旧: ベンダープレフィックス付き(もう不要) */
::-webkit-input-placeholder { color: #999; }  /* Chrome, Safari, Edge */
::-moz-placeholder { color: #999; }           /* Firefox */
:-ms-input-placeholder { color: #999; }        /* IE 10-11 */

/* 現在: これだけでOK */
::placeholder {
  color: #999;
}

2025年現在、すべてのモダンブラウザ(Chrome, Firefox, Safari, Edge)が::placeholderをプレフィックスなしで対応済みです。IE対応が不要なプロジェクトでは、プレフィックスは書く必要がありません。

::placeholder に適用できるCSSプロパティ一覧

::placeholderすべてのCSSプロパティに対応しているわけではありません。CSS仕様では::first-lineと同じプロパティセットが適用可能と定義されています。

カテゴリ プロパティ
フォント系 font, font-size, font-weight, font-style, font-family, font-variant
テキスト色 color, opacity
テキスト装飾 text-decoration, text-transform, text-shadow
間隔・行 letter-spacing, word-spacing, line-height
背景 background, background-color, background-image
/* 様々なプロパティを活用した例 */
.styled-input::placeholder {
  color: #94a3b8;
  font-size: 13px;
  font-style: italic;
  letter-spacing: 0.5px;
  text-transform: uppercase;
}

/* 注意: 以下のプロパティは ::placeholder には効かない */
/* padding, margin, display, width, height, border など */

ブラウザごとのデフォルトplaceholderスタイル

ブラウザによってplaceholderのデフォルトの見た目が微妙に異なります。

ブラウザ デフォルトの色 仕組み
Chrome / Edge darkgray(#757575相当) color: darkgray を直接指定
Firefox 半透明の黒 入力テキスト色に opacity: 0.54 を適用
Safari darkgray(#757575相当) color: darkgray を直接指定

Firefoxはopacityで制御しているため、colorだけを変更しても意図した色にならないことがあります。確実にクロスブラウザで統一するにはcoloropacity: 1の両方を指定しましょう。

/* クロスブラウザで確実に色を統一する */
::placeholder {
  color: #94a3b8;
  opacity: 1;  /* Firefox のデフォルト opacity をリセット */
}

::placeholder と :placeholder-shown の違い

名前が似ていますが、役割がまったく異なる2つのセレクタです。

セレクタ 種類 対象 用途
::placeholder 疑似要素 placeholderテキスト自体 色・フォント等のスタイリング
:placeholder-shown 疑似クラス input/textarea 要素自体 「placeholderが表示されている(= 未入力)」状態の検出
/* ::placeholder → テキストのスタイルを変える */
input::placeholder {
  color: #94a3b8;
  font-style: italic;
}

/* :placeholder-shown → 入力欄が空のときのスタイル */
input:placeholder-shown {
  border-color: #e2e8f0;  /* 未入力 → 薄いボーダー */
}

/* :not(:placeholder-shown) → 入力済みのとき */
input:not(:placeholder-shown) {
  border-color: #3b82f6;  /* 入力済み → 青いボーダー */
}

:placeholder-shownは「placeholderが表示されている = まだ何も入力されていない」ことを検出できるため、フローティングラベルやバリデーションで活躍します。

フォーカス時にplaceholderをフェードアウトさせる

入力欄にフォーカスしたときに、placeholderをふわっと消すアニメーションです。

/* フェードアウト */
input::placeholder {
  color: #94a3b8;
  opacity: 1;
  transition: opacity 0.3s ease;
}

input:focus::placeholder {
  opacity: 0;
}

フォーカス前
メールアドレスを入力…
フォーカス後
メールアドレスを入力…

スライドアップで消すパターン

/* フォーカスでplaceholderが上にスライドして消える */
input::placeholder {
  color: #94a3b8;
  transition: transform 0.3s ease, opacity 0.3s ease;
}

input:focus::placeholder {
  transform: translateY(-100%);
  opacity: 0;
}

フローティングラベルの実装

フローティングラベルは、未入力時にplaceholder風に表示し、入力開始時にラベルが上に移動するパターンです。CSSだけで実装できます

<div class="float-label">
  <input type="email" id="email" placeholder="メールアドレス" required>
  <label for="email">メールアドレス</label>
</div>
.float-label {
  position: relative;
}

.float-label input {
  width: 100%;
  padding: 16px 12px 8px;
  border: 2px solid #e2e8f0;
  border-radius: 8px;
  font-size: 15px;
  outline: none;
  transition: border-color 0.2s;
}

/* placeholder は透明にする(:placeholder-shown の判定用に必要) */
.float-label input::placeholder {
  color: transparent;
}

/* ラベルの初期位置(placeholder の位置に重ねる) */
.float-label label {
  position: absolute;
  left: 14px;
  top: 50%;
  transform: translateY(-50%);
  color: #94a3b8;
  font-size: 15px;
  pointer-events: none;
  transition: all 0.2s ease;
}

/* 入力済み or フォーカス時 → ラベルを上に移動 */
.float-label input:not(:placeholder-shown) + label,
.float-label input:focus + label {
  top: 6px;
  transform: translateY(0);
  font-size: 11px;
  color: #3b82f6;
}

.float-label input:focus {
  border-color: #3b82f6;
}

未入力時
メールアドレス
入力時
メールアドレス
user@example.com

仕組みのポイント

  • placeholder属性には空でない文字列を設定する必要がある(:placeholder-shownの判定に必須)
  • ::placeholder { color: transparent; }でplaceholder自体は見えなくする
  • :not(:placeholder-shown)で「入力済み」を検出し、+ label(隣接兄弟セレクタ)でラベルのスタイルを変更
  • HTMLの順序は必ず input → labelの順にする(CSSの隣接兄弟セレクタは後方の要素しか選択できないため)

フォームバリデーションとの連携

:placeholder-shown:valid/:invalidと組み合わせると、CSSだけでバリデーション表示が可能です。

/* 入力済み + バリデーションOK → 緑ボーダー */
input:not(:placeholder-shown):valid {
  border-color: #22c55e;
}

/* 入力済み + バリデーションNG → 赤ボーダー */
input:not(:placeholder-shown):invalid {
  border-color: #ef4444;
}

/* 未入力の required フィールドは :invalid だが、
   :placeholder-shown で除外してスタイルを適用しない */
input:placeholder-shown:invalid {
  border-color: #e2e8f0;  /* 通常のボーダーのまま */
}

未入力
メール…
有効な入力
user@example.com
無効な入力
abc

:placeholder-shownのおかげで、「まだ何も入力していないのにエラー表示」を防げるのがポイントです。required属性付きのフィールドは空の状態で:invalidですが、:placeholder-shownと組み合わせることで未入力時のエラー表示を抑制できます。

textarea の placeholder

<textarea>にも同様に::placeholderが使えます。

textarea::placeholder {
  color: #94a3b8;
  opacity: 1;
  line-height: 1.6;
}

/* textarea のリサイズ時もplaceholderは自然に追従する */
textarea {
  resize: vertical;
  min-height: 120px;
}

textareaで複数行のplaceholderを表示

HTML属性内では改行できませんが、実体参照&#13;&#10;を使うと改行が可能です。

<!-- 改行入りplaceholder -->
<textarea placeholder="1行目のテキスト&#13;&#10;2行目のテキスト"></textarea>

ただし、この方法はブラウザによって挙動が異なる場合があります。確実に複数行のヒントテキストを表示したい場合は、placeholderではなく入力欄の下にヒントテキストを配置する方がアクセシビリティ的にも安全です。

input type 別のplaceholder対応

placeholder属性が使えるinput typeは限られています。

input type placeholder 備考
text 対応 最も一般的な使用
email 対応 例: user@example.com
password 対応 例: 8文字以上の英数字
search 対応 Safariでのリセットが必要な場合あり
tel 対応 例: 090-1234-5678
url 対応 例: https://example.com
number 対応 例: 0
date / time 非対応 ブラウザ独自のUIが表示される
checkbox / radio 非対応 テキスト入力ではないため

input[type=”search”] の注意点

Safari / WebKit ではinput[type="search"]に独自のスタイルが適用されるため、placeholderのカスタマイズが効かない場合があります。

/* Safari でsearch inputのスタイルをリセット */
input[type="search"] {
  -webkit-appearance: none;
  appearance: none;
}

input[type="search"]::placeholder {
  color: #94a3b8;
}

ダークモード対応

ダークモードではplaceholderの色も調整が必要です。

/* ライトモード */
::placeholder {
  color: #94a3b8;
  opacity: 1;
}

/* ダークモード */
@media (prefers-color-scheme: dark) {
  ::placeholder {
    color: #64748b;
  }
}

/* CSS変数で管理するパターン */
:root {
  --placeholder-color: #94a3b8;
}

@media (prefers-color-scheme: dark) {
  :root {
    --placeholder-color: #64748b;
  }
}

::placeholder {
  color: var(--placeholder-color);
  opacity: 1;
}

ライトモード
検索キーワード…
ダークモード
検索キーワード…

Tailwind CSS での placeholder スタイリング

Tailwind CSS ではplaceholder:修飾子でplaceholderのスタイルを指定できます。

<!-- 基本的な色とスタイル -->
<input
  type="text"
  placeholder="検索..."
  class="placeholder:text-gray-400 placeholder:italic placeholder:text-sm"
/>

<!-- フォーカス時にplaceholderの色を変更 -->
<input
  type="email"
  placeholder="メールアドレス"
  class="placeholder:text-slate-400 focus:placeholder:text-slate-300"
/>

<!-- ダークモード対応 -->
<input
  type="text"
  placeholder="名前"
  class="placeholder:text-gray-400 dark:placeholder:text-gray-600"
/>

よく使う Tailwind placeholder クラス

クラス CSS出力
placeholder:text-gray-400 ::placeholder { color: #9ca3af; }
placeholder:italic ::placeholder { font-style: italic; }
placeholder:text-sm ::placeholder { font-size: 0.875rem; }
placeholder:opacity-50 ::placeholder { opacity: 0.5; }
focus:placeholder:text-transparent :focus::placeholder { color: transparent; }

アクセシビリティ: placeholderをラベル代わりにしてはいけない

placeholderはスタイリング以前に、使い方自体に注意が必要です。

placeholderの問題点

  • 入力すると消える: ユーザーは何を入力すべきだったか忘れてしまう
  • デフォルトの色がWCAGのコントラスト基準を満たさないことが多い(4.5:1未満)
  • スクリーンリーダーによって読み上げられない場合がある(ブラウザ・AT依存)
  • 翻訳ツールで翻訳されないことがある
  • 入力済みの値と見間違えることがある(特に高齢者やロービジョンのユーザー)

正しいパターン

<!-- NG: placeholderだけでラベルを省略 -->
<input type="email" placeholder="メールアドレス">

<!-- OK: labelを使い、placeholderは入力例として使う -->
<label for="email">メールアドレス</label>
<input type="email" id="email" placeholder="例: user@example.com">

<!-- OK: フローティングラベル(視覚的にはplaceholder風、実装はlabel) -->
<div class="float-label">
  <input type="email" id="email2" placeholder=" " required>
  <label for="email2">メールアドレス</label>
</div>

placeholderは「入力例」や「ヒント」として使い、何を入力すべきかは必ず<label>で示すのがベストプラクティスです。

placeholderの色とコントラスト比

placeholderテキストもWCAG 2.1のコントラスト比基準を考慮してください。デフォルトの薄いグレーは基準を満たしていないことが多いです。

/* デフォルト(コントラスト不足の場合あり) */
::placeholder { color: #c0c0c0; }  /* 白背景で 1.6:1 → NG */

/* WCAG AA 基準(4.5:1)を満たす色 */
::placeholder { color: #767676; }  /* 白背景で 4.5:1 → OK */

/* ただし濃すぎると入力済みテキストと見間違えるため、
   入力テキストの色より明確に薄くする */
input { color: #1e293b; }           /* 入力テキスト: 濃い */
::placeholder { color: #94a3b8; }   /* placeholder: 薄い */

まとめ

やりたいこと 使うもの
placeholderの色・フォントを変更 ::placeholder { color: ...; }
Firefoxで色を確実に統一 ::placeholder { opacity: 1; } を追加
入力済み/未入力で見た目を変える :placeholder-shown / :not(:placeholder-shown)
フローティングラベルを実装 :placeholder-shown + :not() + 隣接兄弟セレクタ
フォーカスでplaceholderを消す input:focus::placeholder { opacity: 0; }
CSSだけでバリデーション表示 :not(:placeholder-shown):valid / :invalid

::placeholderは「見た目」を変えるだけのシンプルな疑似要素ですが、:placeholder-shownと組み合わせることでフローティングラベルやバリデーションといった高度なUI表現がCSSだけで実現できます。ただし、placeholderはラベルの代替ではないことを忘れずに。

関連記事