やあ。今日も今日とてCSSの沼にハマっているかい?
フロントエンドの現場にいると、「動くには動くけど、もっとスマートに書けないか?」と悶絶する瞬間に何度も出くわすよな。特にフォーム周りのスタイリングなんて、CSSハックの歴史みたいなカオスになりがちだ。
今回は、そんなフォームスタイリングのモヤモヤを鮮やかに吹き飛ばしてくれる隠し玉、`:read-write` 疑似クラスについて話をしよう。
「なんだ、ただの `input` のセレクタか?」と思ったそこの君。
それ、もったいない。この疑似クラスの本当のポテンシャルを知れば、君の書くフォームのCSSは一気にモダンで、かつ異様にメンテナンス性の高いものに生まれ変わるはずだ。
さあ、現場のリアルな知見を交えながら、深く掘り下げていこうか。
—
1. `:read-write` とは何か?(標準仕様と現場での解釈)
まずは基本のおさらいだ。
`:read-write` 疑似クラスは、ユーザーが編集可能(editable)な状態にある要素にマッチする。逆に、ユーザーが触って内容を変えられない状態の要素(例えば `readonly` がついた入力欄や、そもそもテキストだけの通常の `p` 要素など)は、対抗馬である `:read-only` がキャッチする仕組みだ。
仕様上、対象となるのは主に以下の要素たちだ。
- `input` 要素(`type=”hidden”` や `disabled`、`readonly` が付いていないもの)
- `textarea` 要素(同じく `disabled` や `readonly` が付いていないもの)
- `contenteditable` 属性が付与されたすべてのHTML要素(`div` や `span` など)
なぜ今、この疑似クラスがアツいのか?
実務で考えてみてくれ。
「テキスト入力欄」をスタイルするとき、君は普段どう書いている?
/ よく見るコード /
input[type=”text”],
input[type=”email”],
input[type=”password”],
textarea {
/ スタイルをゴニョゴニョ… /
}
これ、ダサい上に拡張性がないだろ?
後から `input[type=”tel”]` が追加されたり、ECサイトのリニューアルで新しいカスタム入力タイプが入ってきた瞬間に、このセレクタの列挙地獄に修正漏れが発生する。フラグが立つ瞬間だ。
ここで `:read-write` の登場だ。
「ユーザーが文字を入力できる場所」という本質的な状態(State)に着目してセレクタを組めば、面倒な `type` 属性の列挙から解放される。これが、シニアが `:read-write` を推す最大の理由だ。
—
2. ブラウザの裏側の動きと、少しの「罠」
さて、フロントエンド・スペシャリストとして、ブラウザが裏側でどう動いているかも少し覗いておこう。
ブラウザのレンダリングエンジン(BlinkやGeckoなど)は、DOMツリーが構築される際、各要素の属性(`readonly`, `disabled`, `contenteditable` など)やHTMLのデフォルト仕様を評価し、要素に内部的な「ステータス(State)」を付与している。
`:read-write` は、要素の属性をガチャガチャと直接監視しているわけではなく、このブラウザが内部で持っている「編集可能フラグ」が `true` になっているノードに対して瞬時にマッチするように最適化されているんだ。
注意すべき「現場の罠」
ここで一つ、実務で絶対にハマるポイントをシェアしておこう。
HTMLの仕様上、デフォルトの `input`(`type=”text”` など)は、何も属性を指定していなくても「編集可能」なので `:read-write` にマッチする。
つまり、次のようなコードを書いたとき:
/ 注意:意図しない要素まで巻き込む可能性がある /
:read-write {
border: 2px solid #333;
}
なんと、ページ内にある `contenteditable` を持った要素や、ありとあらゆるテキスト入力欄がこのスタイルの影響を受ける。
「ページ全体のリセットCSSや、汎用的なWYSIWYGエディタの領域までぶっ壊れた!」なんて笑えない事故を防ぐためにも、`:read-write` は必ずタグ名やクラス名と組み合わせて名前空間を絞る(スコープを切る)のが、プロの現場の作法だ。
—
3. 実務ですぐに使える!スマートなコード例
百聞は一見にしかず。
実際のプロジェクトで即戦力になる、エレガントなフォームのスタイリングコードを書いてみよう。
今回は、「通常時はすっきり、フォーカス時やエラー時に滑らかに変化し、かつ `readonly` の時は自動的にスタイルが除外される」という堅牢なフォームを構築する。
HTML
CSS
/ ==========================================
フォームスタイリング:実践ベストプラクティス
================================———- /
.form-group {
margin-bottom: 24px;
font-family: sans-serif;
}
.form-group label {
display: block;
margin-bottom: 8px;
font-size: 14px;
font-weight: bold;
color: #333;
}
/
【ポイント】
input, textarea, さらに contenteditable な div を一網打尽にしつつ、
readonly要素を綺麗に除外する。type属性の列挙はもう必要ない!
/
input:read-write,
textarea:read-write,
.custom-editor:read-write {
width: 100%;
padding: 12px 16px;
font-size: 16px;
color: #222;
background-color: #fff;
border: 1px solid #cbd5e1;
border-radius: 6px;
outline: none;
transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
/ フォーカス時のインタラクション /
input:read-write:focus,
textarea:read-write:focus,
.custom-editor:read-write:focus {
border-color: #3b82f6;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15);
}
/
【比較用】readonly属性がついた要素(自動的に :read-only になる)
これらは上記の :read-write スタイルから完全に除外されるため、
別途 readonly 用の落ち着いたスタイルを安全に適用できる。
/
input:read-only {
background-color: #f1f5f9;
border-color: #e2e8f0;
color: #64748b;
cursor: not-allowed;
}
このコードの美しさは、「属性セレクタの網羅漏れ」というヒューマンエラーをCSSの構造自体で完全にシャットアウトしている点にある。
将来的に `type=”search”` や `type=”url”` が追加されても、CSS側を1文字も書き換える必要はない。ブラウザが「今、編集できる状態か?」を判断し、勝手に正しいスタイルを適用してくれるのだ。
—
4. チーフアーキテクトからのメッセージ
CSSの疑似クラスを使いこなすということは、単に「見た目を綺麗にする」ことじゃない。
「HTMLの構造や要素の『状態』に、コードの意図を正確にシンクロさせる」ということだ。
`:read-write` は、モダンなWebアプリケーション開発において、フォームのボイラープレート(お決まりのコード)を劇的にスリム化してくれる頼もしい武器になる。
次に新しい画面やフォームを設計するとき、`input[type=”text”]…` と書き殴りそうになったら、ふっと立ち止まって自問してみてほしい。
「おっと、ここは属性じゃなくて『状態』で選ぶべきじゃないか?」とね。
君のコードが、より洗練されたものになることを期待している。
それじゃあ、また次の現場で!

コメント