ど素人から毛を生やす。<延>

ブラウザ差異に悩まない、凝らないフォームのノーマライズCSS

Web > css 2026年6月25日(最終更新:2日前)

最近、簡易なHTMLを書く機会が多かったので、ウン年前に書いたリセット(ノーマライズ)CSSを見直しました。

で、かねがねフォーム系のCSSのブラウザ差異に悩まされていたので、ブラウザ差異ができるだけ生じないフォーム用のリセット(ノーマライズ)CSSも書くことにしました。
見た目をがらりと変えてしまうお洒落なCSSはネットを探せばいくらでも出回っていますが、そういうのじゃなくて、洒落にする前のスタート地点。
デフォルトっぽい感じの絵面で、デフォルトCSSから脱却し、極力ブラウザ差異をなくすことが目標です。

input, textarea, button, select, option, input::file-selector-button{
    font-family:var(--gothic-font);
    color:var(--main-color);
    font-size:95%;
}

最初に、input等にはbodyに指定したフォントが当たらないので、明示的にフォントとサイズを当てます。
ここでは種別と色はrootで指定しておいたものを使用。
サイズは相対値にすることで、ブラウザ依存から親サイズ依存に切り替わります。固定値でもOK。

label{
    display:inline-block;
    cursor:pointer;
}

ラベルはinline-blockにします。

textarea, input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="hidden"]):not([type="submit"]):not([type="reset"]):not([type="button"]):not([type="image"]){
    padding:2px 10px;
    border:1px solid #aaa;
    border-radius:0;
    background-color:#fff;
}



※numberの矢印など各操作部はブラウザ依存のままです。個々の調整は割愛。
テキスト入力系inputの外見を統一。

textarea{
    resize:vertical;
}


テキストエリアの変形は縦方向のみ許可。横変形を許可すると往々にしてレイアウトが崩れます。

button, input::file-selector-button, input[type="submit"], input[type="button"], input[type="reset"]{
    padding:2px 10px;
    background:#eee;
    border:1px solid #aaa;
    border-radius:2px;
    cursor:pointer;
}
:is(button, input::file-selector-button, input[type="submit"], input[type="button"], input[type="reset"]):active:not(:disabled){
    background-color:#ddd;
}


ボタン系の外見を統一。active時のスタイルも必ず指定するように。

label>input[type=checkbox]{
    appearance:none;
    border:1px solid #aaa;
    background-color:#fff;
    width:14px;
    height:14px;
    border-radius:2px;
    box-shadow:none;
    accent-color:#ddd;
    display:inline-block;
    vertical-align:-2px;
    margin-right:2px;
    position:relative;
    cursor:pointer;
}
label>input[type=checkbox]:checked{
    background-color:#eee;
}
label>input[type=checkbox]:checked::after{
    display:block;
    content:'';
    width:3px;
    height:10px;
    border-right:1px solid var(--main-color);
    border-bottom:1px solid var(--main-color);
    transform:rotate(45deg);
    position:absolute;
    bottom:1px;
    left:4px;
}



チェックボックスを描写し直す。appearance:noneでブラウザ指定の描写を削除し、それっぽいものを書き直します。選択時のチェックマークは疑似要素で描写。

label>input[type=radio]{
    appearance:none;
    border:1px solid #aaa;
    background-color:#fff;
    width:14px;
    height:14px;
    border-radius:14px;
    box-shadow:none;
    accent-color:#ddd;
    display:inline-block;
    vertical-align:-2px;
    margin-right:2px;
    position:relative;
    cursor:pointer;
}
label>input[type=radio]:checked{
    background-color:#eee;
}
label>input[type=radio]:checked::after{
    display:block;
    content:'';
    width:4px;
    height:4px;
    background-color:var(--main-color);
    border-radius:4px;
    position:absolute;
    bottom:4px;
    left:4px;
}



同様にラジオボタンも再描写。

select{
    appearance:none;
    -webkit-appearance:none;
    -moz-appearance:none;
    padding:4px 8px;
    padding-right:20px;
    border:1px solid #aaa;
    border-radius:0;
    outline:0;
    box-shadow:none;
    text-overflow:ellipsis;
    cursor:pointer;
    background:#fff;
    background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='18' height='18' viewBox='0 0 24 24'><path fill='none' stroke='%23666666' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' d='M6 9l6 6 6-6'/></svg>");
    background-repeat:no-repeat;
    background-position:right 4px center;
    background-size:18px;
}
option:checked{
    background:#eee;
}


最大の敵はselectです。selectはブラウザに依存する部分が大きく、残念ながら統一描写が今のところ不可能。

appearance:base-selectはまあまあ諸刃の剣で、widthと一緒に指定したとき、optionの幅が指定したwidthを超過するとどうしてもどこかしらレイアウトが崩れるため、動的にoptionを生成する場合には不向き。
魔改造しない場合は原始的にappearance:noneの方を使い、ピッカーの部分はブラウザの仕様を許容した方が無難です。

また、selectには疑似要素が使えないので、プルダウンを示す下矢印はSVGで表示させておきます。
text-overflow:ellipsisはsafariとかがまだ対応していないのもあって導入は好き好きで。

:is(textarea, select, input:not([type="file"]):not([type="hidden"]):not([type="submit"]):not([type="reset"]):not([type="button"]):not([type="image"])):disabled{
    background-color:#ddd;
    cursor:default;
    opacity:1;
}
:is(button, input::file-selector-button, input[type="submit"], input[type="button"], input[type="reset"]):disabled{
    opacity:0.7;
    cursor:default;
}
label:has(:disabled){
    cursor:auto;
}

最後に、disabled時の描画も統一しておきます。

この記事は役に立ちましたか?
  • _(:3」∠)_ 面白かった (0)
  • (・∀・) 参考になった (0)
  • (`・ω・´) 役に立った (0)