やあ。今日も今日とてCSSの沼にハマっているかい?
フロントエンドをやっていると、「フォーム周りのスタイリング、なんでこんなに泥臭いんだ……」と頭を抱えたくなる瞬間が必ず訪れる。特に、ユーザーが入力できる状態なのか、それとも読み取り専用(readonly)なのか、あるいは無効化(disabled)されているのかによって、スタイルの切り替えに苦労した経験はないだろうか。
今日は、そんなフォームスタイリングのモヤモヤを鮮やかに解決してくれる、中級者なら絶対に押さえておきたい隠し味――いや、実務で超強力な武器になる擬似クラス `:read-write` について話をしよう。
公式リファレンスを読めば「ユーザーが編集可能な要素を選択する」と一言で書いてある。だが、現場のプロが知りたいのはそんな表面的定義じゃない。「ブラウザの裏側でどう動いていて、どの要素にヒットし、どう実務のコードを美しく保てるか」だよね。
さあ、深掘りしていこうか。
—
1. `:read-write` とは何か?(仕様と現場での解釈)
一言で言えば、`:read-write` は「ユーザーが値を書き換えられる状態にあるDOM要素」をスナイパーのように正確に撃ち抜く擬似クラスだ。
対になる存在として `:read-only` がある。こいつらは兄弟のような関係で、だいたいセットで語られることが多い。
だが、実務で触っていると「えっ、お前もそれに反応するの!?」というブラウザの気まぐれ(仕様の厳密な解釈)にぶつかる。
ブラウザの裏側:こいつは一体どこをターゲットにしているのか?
CSS Selector Level 4で定義されたこの `:read-write`、実は以下の要素たちにマッチする。
1. 通常の `` 要素 (`type=”text”`, `type=”email”`, `type=”number”` など、デフォルトで入力できるもの)
2. ` (テキストエリア)
3. `contenteditable=”true”` が付与されたあらゆる要素 (`
` など)
4. 上記の中で、`readonly` 属性や `disabled` 属性がついていないもの
逆に言うと、`readonly` が付いた `` や、そもそも入力不可の ``、ただの静的な `
` タグなどは容赦なく弾かれる(それらは `:read-only` の世界だ)。
ここで中級エンジニアの君が「おっ?」と気づくべきポイントがある。
そう、「JavaScriptで動的に `contenteditable` にされた要素」や「現代のリッチテキストエディタの土台」も、この `:read-write` 一発でスタイリングできるという点だ。これがめちゃくちゃ実務で効いてくる。
—
2. なぜ `:read-write` が実務で重宝されるのか?
昔の俺たちは、入力可能かどうかをスタイリングするときにこんなコードを書いていた。
/ 昔やりがちだった泥臭いセレクタの指定 /
input[type=”text”]:not([readonly]):not([disabled]),
input[type=”email”]:not([readonly]):not([disabled]),
textarea:not([readonly]):not([disabled]) {
background-color: #fff;
border-color: #3b82f6;
}
……見ていて涙が出そうにならないかい? `:not()` の数珠つなぎ。新しいHTML5の入力タイプ(`tel`, `url` など)が増えるたびにこのセレクタをメンテしなきゃいけない地獄。
ここで `:read-write` の登場だ。先ほどのコードは、こう書き換えられる。
/ 現代的で美しいアプローチ /
:read-write {
background-color: #fff;
border-color: #3b82f6;
}
圧倒的にスマートだと思わないか?
「ユーザーが書き込める状態のすべての要素」を、たった一言で捕捉できる。保守性が桁違いに跳ね上がる瞬間だ。
—
3. 実戦投入:コピペで使えるモダン・フォームスタイリング
理屈はこれくらいにして、実際に明日の案件からそのまま使えるコードを見せよう。
今回は、フォームの「通常入力可能」「読み取り専用」「無効化」のステータスを、`:read-write` を主軸にして美しく整理したサンプルだ。
HTML
CSS
/ ==========================================
ベースのフォームコンポーネント設計
========================================== /
.form-group {
margin-bottom: 1.5rem;
font-family: sans-serif;
}
.form-group label {
display: block;
margin-bottom: 0.5rem;
font-weight: 600;
font-size: 0.875rem;
color: #374151;
}
/ 1. 編集可能なすべての要素に対する共通スタイル(ここがキモ!) /
input:not([type=”submit”]):not([type=”button”]):not([type=”checkbox”]):not([type=”radio”]),
textarea,
.rich-editor {
width: 100%;
padding: 0.75rem 1rem;
font-size: 1rem;
background-color: #f9fafb;
border: 1px solid #d1d5db;
border-radius: 0.375rem;
transition: all 0.2s ease-in-out;
outline: none;
box-sizing: border-box;
}
/ 2. ユーザーが書き込める(編集可能)状態のときのインタラクション /
:read-write {
background-color: #ffffff;
color: #111827;
cursor: text;
}
/ フォーカス時のアプローチ /
:read-write:focus {
border-color: #2563eb;
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.15);
}
/ 3. 読み取り専用(readonly)や非編集時のスタイルは対抗馬を使う /
input:read-only,
:read-only:not(input) {
background-color: #f3f4f6;
color: #6b7280;
border-color: #e5e7eb;
cursor: not-allowed;
}
/ リッチエディター特有の調整(contenteditable用) /
.rich-editor {
min-height: 100px;
overflow-y: auto;
}
このコードの美しいところは、通常の ``、`
もしデザイナーから「入力できるフィールドは、すべてフォーカス時に青いグローを光らせてくれ」と言われたら、`:read-write:focus` を一枚定義するだけで、HTMLのタグ構造を意識せずに要件を満たせる。
—
4. 現場でハマりがちな「落とし穴」とシニアからのアドバイス
さて、ここまで絶賛してきた `:read-write` だが、ベテランの俺からいくつか現場の教訓(ハマりポイント)を伝授しておこう。これを忘れると、思わぬバグを踏むことになる。
注意点1:詳細度(Specificity)の罠
`:read-write` はあくまで「擬似クラス」なので、セレクタの詳細度には影響を与えない(0-1-0)。
しかし、既存のUIライブラリ(BootstrapやTailwindのコンポーネントなど)を上書きする際、クラス名(例: `.form-control`)のほうが詳細度が強くてスタイルが負けることがある。
そんなときは、要素セレクタやクラスと組み合わせよう。
/ 詳細度を上げたい場合の書き方 /
input.form-input:read-write {
/ スタイル /
}
注意点2:ブラウザのデフォルトスタイル(User Agent Stylesheet)
一部のブラウザでは、`[contenteditable=”true”]` や特定の入力要素に対して独自のフォーカスリングや背景色を持っていることがある。
`:read-write` を使うときは、必ず自分で `outline: none;` や `background-color` を明示的にリセットしてコントロールする癖をつけよう。ブラウザ任せにすると、MacのSafariとWindowsのChromeで見た目がズレる原因になる。
注意点3:対応ブラウザはもう怖くない
「新しめの機能だから、古いブラウザで死なない?」という心配性な後輩もいるかもしれない。
安心してほしい。`:read-write` は主要モダンブラウザ(Chrome, Safari, Firefox, Edge)の何年も前から完全にサポートされている。Can I use を見ても緑一色だ。実務で使わない理由がない。
—
まとめ
CSSの擬似クラスを使いこなせるようになると、HTMLのマークアップやCSSの記述量が減り、「状態(State)ベースでUIを考える」というモダンなフロントエンド設計の頭に切り替わる。
今回紹介した `:read-write` も、まさにそのための強力なツールだ。
「入力できるものすべてに同じルールを適用する」というボイラープレートなコードから脱却し、よりセマンティックで、メンテナンス性の高いスタイルシートを構築してほしい。
さて、コーヒーブレイクはこのへんにして、さっそく君のプロジェクトのフォーム周りのコードを `:read-write` でリファクタリングしてみなよ。きっとコードが軽くなって気持ちがいいはずだ。
何か詰まったら、いつでも俺のところへ聞きに来いよ。

コメント