ざっくり<input>にCSSを適用してしまうと、あまり使われないマイナーなtypeにまで意図せず影響が出てしまうので、いくつかのtypeのデフォルトスタイルを温存しつつ使いたいformパーツのスタイルを揃えるCSSを考えました。
できたもの
Demo
type color, range, checkbox, radioへはCSSが干渉しません。
解説
-webkit-appearance: none;
主にスマホのデフォルトスタイルを無効化します。
box-sizing: border-box;
レスポンシブ用にwidth:100%;を入れますが、width+paddingの併用時にボックスを飛び出してしまわないように。
font-size: 16px;
実寸16px以下の場合、iOSでフォーカス時にページズームが掛かってしまう。
vertical-align: top;
textareaがわかりやすいですが下部に余白が発生しています。vertical-alignを指定すると解消します。
input[type='text'],
input[type='search'],
input[type='tel'],
input[type='url'],
input[type='email'],
input[type='password'],
input[type='datetime'],
input[type='datetime-local'],
input[type='date'],
input[type='month'],
input[type='week'],
input[type='time'],
input[type='number'],
input[type='file'],
textarea,
select {
width: 100%;
height: 2em;
}
type="text"系に対してwidth/heightを指定。
input[type='image'] {
max-width: 100%;
}
type="image"のみ実寸以上に拡大してしまわないように専用指定。
input[type='submit'],
input[type='reset'],
input[type='button'],
button {
height: 2em;
}
ボタン系は横幅いっぱい指定から除外しました。
width:100%で構わない場合はtype="text"系指定にマージできます。
textarea {
min-height: 2em;
resize: vertical;
}
textareaには右下をドラッグすることでユーザー側でリサイズできる機能があります。リサイズの利便性を確保しつつレイアウトへ干渉しないように縦リサイズのみ許可する制御を入れました。必要以上に縮めてしまう事も可能な為、min-heightで最小値を確保しました。
input[type='text'],
input[type='search'],
input[type='tel'],
input[type='url'],
input[type='email'],
input[type='password'],
input[type='datetime'],
input[type='datetime-local'],
input[type='date'],
input[type='month'],
input[type='week'],
input[type='time'],
input[type='number'],
textarea,
select {
padding-left: .4em;
background: #fff;
border: none;
border-radius: 0;
}
input[type='submit'],
input[type='reset'],
input[type='button'],
button {
background: #000;
border: none;
border-radius: 0;
color: #fff;
cursor: pointer;
}
主に見栄えに関する指定。内側がキツキツなのでpaddingを設けましたが、rightに掛かるとselectの右矢印が内側に寄ってしまうのでleftのみとしました。
cursor: pointer;はtype="image"のみカーソルがpointerに変わるので、他のボタンも挙動を揃える目的です。
type="file"について
background-colorやborderを入れてしまうとデフォルトスタイルが死ぬ上に意図したCSSも乗らないブラウザがあります。(IE,Edge系)
デザイン性を求める場合、input本体はdisplay: none;として、対応したlabel要素としてスタイリングするのが主流のようですのでここでは頑張るのをやめました。
type="checkbox" / type="radio"について
type="file"同様、labelを用いた代替要素による表現が主流のようです。
:valid/:invalidに関しての疑問
CSSクラス「:invalid」を使うことでエラー時のスタイル指定が可能ですが、デフォルト挙動を完全に置き換えることができずにいます。
ブラウザデフォルトの挙動
- ページアクセス状態ではエラー表示をしない
- 一度フォーカスが当たり、フォーカスが外れた際に内容に不備があるとエラースタイルが適用される
:invalid指定による問題
- ページアクセス初期状態でエラースタイルが掛かってしまう
そこで、以下の複合指定を試みました。
input[type='text']:not([value='']):not(:focus):invalid,
textarea:not(:empty):not(:focus):invalid {}
inputとtextareaでは文字列の扱いが違うので二種類セレクタを用意しました。
- 「要素が空ではない」
- 「フォーカスが外れている状態」
- 「内容に不備がある」
の条件を満たした場合に合致するはずですが、inputについては意図通りの挙動になりましたがtextareaは:not(:empty)の判定が動いていないようです。