



WithCodeMedia-1-pc
WithCodeMedia-2-pc
WithCodeMedia-3-pc
WithCodeMedia-4-pc




WithCodeMedia-1-sp
WithCodeMedia-2-sp
WithCodeMedia-3-sp
WithCodeMedia-4-sp









生徒お問い合わせフォームを作ったんですが、入力欄の見た目がブラウザごとにバラバラで…。どこから直せばいいですか?
ペン博士フォームはブラウザ標準スタイルを打ち消してから積み上げるのがコツだよ。今日は入力欄・セレクト・チェックボックス・ボタンまで、コピペで使える形で順番に渡すね。
お問い合わせフォームは、サイトの中で最もコンバージョンに近い場所です。それなのに、入力欄の高さがバラバラだったり、スマホでタップすると画面が勝手に拡大したりと、細かい粗が残りやすいパーツでもあります。
原因のほとんどは「ブラウザが最初から当てているスタイル」です。inputやselectはブラウザごとに独自の見た目を持っているため、そこを整えないまま装飾を足すと差が出ます。
この記事では、ベースのリセットから入力欄・セレクトボックス・チェックボックス・送信ボタン・レイアウト・フォーカス表示まで、コピペしてそのまま使えるCSSを順番に紹介します。最後に全部入りの完成版フォームも置いています。

最初に、なぜフォームだけ他のパーツより崩れやすいのかを押さえておきましょう。原因を知っていれば、対処は一度で済みます。
フォーム部品はブラウザが独自に描画しています。ボタンの角丸、セレクトの矢印、チェックボックスの四角はすべてOSとブラウザが用意した見た目で、CSSを当てていない状態では環境ごとに違う姿になります。
box-sizingの指定がないとpaddingで幅がはみ出すつまり、装飾の前に「継承させる」「計算をそろえる」「独自描画を消す」の3点を済ませておけば、あとは自由に作れます。
すべてのフォームに共通で入れておくリセットです。これだけで、環境差の大半が消えます。
/* フォーム共通のベース */
input,
textarea,
select,
button {
font: inherit; /* 親のフォントを継承させる */
color: inherit;
box-sizing: border-box; /* padding込みで幅を計算 */
max-width: 100%;
}
/* ブラウザ独自の見た目を消す */
input,
textarea,
select {
appearance: none;
-webkit-appearance: none;
background-color: #fff;
border: 1px solid #d1d5db;
border-radius: 8px;
padding: 0.75em 1em;
width: 100%;
}
/* テキストエリアは縦だけリサイズ可に */
textarea {
min-height: 8em;
resize: vertical;
line-height: 1.7;
}ポイントはfont: inheritとbox-sizing: border-boxの2つです。特にfontの継承漏れは、フォームだけ書体が違うという違和感の主犯なので必ず入れてください。
appearance: noneはセレクトの矢印やiOSの丸みを消します。消したあとは自分で見た目を足す前提なので、次のセクションから順に組み立てます。

入力欄はサイトの雰囲気に合わせて選べるよう、3種類用意しました。どれもコピペで動きます。
.form-underline input,
.form-underline textarea {
border: none;
border-bottom: 2px solid #d1d5db;
border-radius: 0;
padding: 0.6em 0.2em;
background: transparent;
transition: border-color .2s;
}
.form-underline input:focus,
.form-underline textarea:focus {
border-bottom-color: #0ea5e9;
outline: none;
}余白の広いデザインや、コーポレートサイトの静かなトーンに合います。枠がない分、ラベルとの距離をしっかり取るのがコツです。
.form-box input,
.form-box textarea {
border: 1px solid #d1d5db;
border-radius: 8px;
padding: 0.8em 1em;
transition: border-color .2s, box-shadow .2s;
}
.form-box input:focus,
.form-box textarea:focus {
border-color: #0ea5e9;
box-shadow: 0 0 0 3px rgba(14, 165, 233, .18); /* 外側に光る枠 */
outline: none;
}迷ったらこれです。フォーカス時にbox-shadowで外側に光る枠を出すと、どこを入力しているかが一目で伝わります。
.form-filled input,
.form-filled textarea {
border: 1px solid transparent;
border-radius: 10px;
background-color: #f3f4f6;
padding: 0.85em 1em;
transition: background-color .2s, border-color .2s;
}
.form-filled input:focus,
.form-filled textarea:focus {
background-color: #fff;
border-color: #0ea5e9;
outline: none;
}入力欄が背景から浮いて見えるので、フォームだと気づいてもらいやすい形です。入力中に白へ変わる動きで、状態の変化も伝わります。
selectはブラウザ差が最も大きい部品です。appearance: noneで矢印を消し、背景画像またはラッパー要素で自分の矢印を置きます。
.select-wrap {
position: relative;
display: block;
}
.select-wrap select {
appearance: none;
-webkit-appearance: none;
width: 100%;
padding: 0.8em 2.6em 0.8em 1em; /* 右側に矢印のぶんの余白 */
border: 1px solid #d1d5db;
border-radius: 8px;
background-color: #fff;
cursor: pointer;
}
/* 擬似要素で三角の矢印を描く */
.select-wrap::after {
content: "";
position: absolute;
top: 50%;
right: 1em;
width: 8px;
height: 8px;
border-right: 2px solid #6b7280;
border-bottom: 2px solid #6b7280;
transform: translateY(-70%) rotate(45deg);
pointer-events: none; /* クリックをselectに通す */
}<div class="select-wrap">
<select name="subject">
<option value="">お問い合わせ内容を選択</option>
<option value="estimate">お見積りについて</option>
<option value="service">サービス内容について</option>
<option value="other">その他</option>
</select>
</div>忘れやすいのがpointer-events: noneです。これが無いと矢印の上をクリックしても反応しないフォームになります。
チェックボックスは標準の四角を消して、自前の四角と「レ点」を描くのが定番です。labelで囲むと、文字をタップしても切り替わります。
.check {
display: inline-flex;
align-items: center;
gap: 0.6em;
cursor: pointer;
}
.check input[type="checkbox"] {
appearance: none;
-webkit-appearance: none;
width: 22px;
height: 22px;
flex: none;
border: 2px solid #d1d5db;
border-radius: 6px;
position: relative;
transition: background-color .15s, border-color .15s;
}
/* チェック時の色とレ点 */
.check input[type="checkbox"]:checked {
background-color: #0ea5e9;
border-color: #0ea5e9;
}
.check input[type="checkbox"]:checked::after {
content: "";
position: absolute;
inset: 0;
margin: auto;
width: 6px;
height: 11px;
border-right: 2px solid #fff;
border-bottom: 2px solid #fff;
transform: rotate(45deg) translate(-1px, -1px);
}
/* ラジオは丸くして中に点を置く */
.check input[type="radio"] {
appearance: none;
-webkit-appearance: none;
width: 22px;
height: 22px;
flex: none;
border: 2px solid #d1d5db;
border-radius: 50%;
position: relative;
}
.check input[type="radio"]:checked {
border-color: #0ea5e9;
}
.check input[type="radio"]:checked::after {
content: "";
position: absolute;
inset: 0;
margin: auto;
width: 10px;
height: 10px;
border-radius: 50%;
background-color: #0ea5e9;
}<label class="check">
<input type="checkbox" name="agree" value="1">
<span>プライバシーポリシーに同意する</span>
</label>flex: noneを入れておくと、文言が長く折り返したときも四角が縦に潰れません。細かいですが、同意チェックは文章が長くなりがちなので効きます。
送信ボタンはフォームの結論です。押せる場所だと一目で分かる大きさと、押した感触が返る動きを付けます。
.form-submit {
display: block;
width: 100%;
max-width: 320px;
margin-inline: auto;
padding: 1em 2em;
border: none;
border-radius: 999px;
background-color: #0ea5e9;
color: #fff;
font-weight: 700;
cursor: pointer;
transition: transform .15s, box-shadow .15s, background-color .15s;
box-shadow: 0 4px 0 #0284c7;
}
.form-submit:hover {
background-color: #0284c7;
}
.form-submit:active {
transform: translateY(3px); /* 押し込まれる動き */
box-shadow: 0 1px 0 #0284c7;
}
/* 送信できない状態は見た目でも伝える */
.form-submit:disabled {
background-color: #cbd5e1;
box-shadow: none;
cursor: not-allowed;
}:activeで沈み込ませ、影を薄くすると物理ボタンのような手応えになります。送信処理中はdisabledを付けて二重送信も防ぎましょう。
入力項目の並べ方は、PCでは2カラム、スマホでは1カラムに落とすのが基本です。Gridなら数行で切り替えられます。
.form-grid {
display: grid;
gap: 1.25rem 1.5rem;
grid-template-columns: 1fr 1fr;
}
/* 住所や本文など、横幅いっぱい使いたい項目 */
.form-grid .full {
grid-column: 1 / -1;
}
.form-field label {
display: block;
margin-bottom: 0.4em;
font-weight: 700;
font-size: 0.95em;
}
/* 必須マーク */
.form-field .req {
margin-left: 0.5em;
padding: 0.1em 0.5em;
border-radius: 4px;
background-color: #ef4444;
color: #fff;
font-size: 0.75em;
}
@media (max-width: 640px) {
.form-grid {
grid-template-columns: 1fr; /* スマホは縦積み */
}
}ラベルは入力欄の真上に置くのが最も速く読める配置です。左横並びは視線移動が増え、スマホでは折り返して崩れやすいので避けます。

outline: noneだけ書いて終わりにすると、キーボード操作の人が現在位置を見失います。消すなら代わりを必ず用意します。
/* マウスクリック時は出さず、キーボード操作時だけ出す */
input:focus-visible,
textarea:focus-visible,
select:focus-visible,
button:focus-visible {
outline: 3px solid #0ea5e9;
outline-offset: 2px;
}
/* ラベルと入力欄の関連付けが取れていれば読み上げも通る */
.form-field label {
cursor: pointer;
}<div class="form-field">
<label for="email">メールアドレス<span class="req">必須</span></label>
<input type="email" id="email" name="email" autocomplete="email" required>
</div>labelのforとinputのidを必ず一致させる:focus-visibleを使えば、マウス操作では枠が出ず見た目も保てるHTMLの検証機能とCSSを組み合わせると、JavaScriptなしでも入力状態を伝えられます。ポイントは:user-invalidを使うことです。
/* 一度入力して離れた後にだけエラー色にする */
input:user-invalid,
textarea:user-invalid {
border-color: #ef4444;
background-color: #fef2f2;
}
input:user-invalid + .error-text {
display: block;
}
.error-text {
display: none;
margin-top: 0.4em;
color: #dc2626;
font-size: 0.9em;
}
/* 入力が正しいときは静かに知らせる */
input:user-valid {
border-color: #10b981;
}従来の:invalidは、ページを開いた瞬間から未入力の必須項目を赤くしてしまいます。:user-invalid なら「触ったあと」だけ反応するので、初見で怒られる不快感がありません。
スマホのフォームで最も多い不満は「タップしたら画面が拡大した」「キーボードが合わない」の2つです。どちらもすぐ直せます。
/* iOSは16px未満の入力欄でズームする */
input,
textarea,
select {
font-size: 16px;
}
/* タップ領域は十分な高さを確保する */
input,
select,
.form-submit {
min-height: 48px;
}<input type="tel" name="tel" inputmode="numeric" autocomplete="tel" placeholder="09012345678">
<input type="email" name="email" inputmode="email" autocomplete="email">
<input type="text" name="zip" inputmode="numeric" autocomplete="postal-code">| 属性 | 役割 | 指定例 |
|---|---|---|
inputmode | 出るキーボードの種類を変える | numeric / email / tel |
autocomplete | 保存済みの情報で自動入力させる | email / tel / postal-code |
type | 入力形式の検証と初期キーボード | email / tel / url |
| font-size | 16px以上でiOSの自動ズームを防ぐ | 16px |
この4点を入れるだけで、スマホの入力完了率は目に見えて変わります。特に電話番号と郵便番号はinputmode="numeric"を忘れずに。
ここまでの内容をまとめた、そのまま使える一式です。クラス名はプロジェクトに合わせて変えてください。
<form class="form-box" action="/contact/" method="post">
<div class="form-grid">
<div class="form-field">
<label for="name">お名前<span class="req">必須</span></label>
<input type="text" id="name" name="name" autocomplete="name" required>
</div>
<div class="form-field">
<label for="email">メールアドレス<span class="req">必須</span></label>
<input type="email" id="email" name="email" autocomplete="email" required>
<span class="error-text">メールアドレスの形式で入力してください</span>
</div>
<div class="form-field full">
<label for="subject">お問い合わせ内容</label>
<div class="select-wrap">
<select id="subject" name="subject">
<option value="">選択してください</option>
<option value="estimate">お見積りについて</option>
<option value="service">サービス内容について</option>
</select>
</div>
</div>
<div class="form-field full">
<label for="body">ご相談内容<span class="req">必須</span></label>
<textarea id="body" name="body" required></textarea>
</div>
<div class="form-field full">
<label class="check">
<input type="checkbox" name="agree" value="1" required>
<span>プライバシーポリシーに同意する</span>
</label>
</div>
</div>
<button type="submit" class="form-submit">送信する</button>
</form>/* 完成版の土台(前述のベース+レイアウトをまとめたもの) */
.form-box {
max-width: 720px;
margin-inline: auto;
}
.form-box input,
.form-box select,
.form-box textarea {
font: inherit;
font-size: 16px;
box-sizing: border-box;
width: 100%;
min-height: 48px;
padding: 0.8em 1em;
border: 1px solid #d1d5db;
border-radius: 8px;
background-color: #fff;
appearance: none;
-webkit-appearance: none;
transition: border-color .2s, box-shadow .2s;
}
.form-box input:focus,
.form-box select:focus,
.form-box textarea:focus {
border-color: #0ea5e9;
box-shadow: 0 0 0 3px rgba(14, 165, 233, .18);
outline: none;
}
最後に、フォームで詰まりやすい点をまとめておきます。症状から逆引きしてください。
| 症状 | 原因 | 対処 |
|---|---|---|
| 入力欄だけ書体が違う | fontが継承されない | font: inheritを指定 |
| 幅が親からはみ出す | paddingが幅に加算 | box-sizing: border-box |
| 矢印を押しても開かない | 擬似要素がクリックを奪う | pointer-events: none |
| タップで画面が拡大 | 文字が16px未満 | 入力欄を16px以上に |
| 枠が消えて操作位置が不明 | outlineを消した | :focus-visibleで代替 |
| 開いた瞬間に全部赤い | :invalidを使用 | :user-invalidに変更 |
どれも装飾ではなく土台の指定漏れが原因です。ベーススタイルを最初に入れておけば、大半は発生しません。
フォームのデザインは、ブラウザ標準スタイルを打ち消すベース作りから始めると一気に安定します。入力欄は下線・枠線・塗りつぶしの3パターンから選び、セレクトとチェックボックスはappearance: noneで消してから自作の矢印やレ点を描きます。仕上げに:focus-visibleでフォーカス表示を確保し、スマホでは16px以上とinputmodeを指定すれば、見た目と使いやすさの両方が揃ったフォームになります。
セレクトの矢印、チェックボックスやラジオボタンの標準デザイン、iOSの角丸やグラデーションなど、ブラウザやOSが独自に描いている見た目が消えます。消したあとは自分でスタイルを当てる前提なので、矢印やレ点は擬似要素で描き直してください。
input・textarea・select・buttonは親要素のフォントを継承しない仕様のためです。font: inheritを指定すると、本文と同じ書体・サイズになります。フォーム崩れの相談で最も多い原因です。
iOSのSafariは、文字サイズが16px未満の入力欄にフォーカスすると自動でズームします。入力欄のfont-sizeを16px以上にすれば止まります。viewportで拡大自体を禁止する方法は、拡大したい利用者を困らせるため推奨されません。
:invalidはページ表示直後から条件を満たさない要素すべてに当たります。:user-invalidは利用者が入力して離れたあとにだけ当たるため、開いた瞬間に必須項目が赤くなる不快な表示を避けられます。
見た目のために消すこと自体は可能ですが、代わりの表示を必ず用意してください。キーボードだけで操作する人が現在位置を見失います。:focus-visibleを使えば、マウス操作時は出さずキーボード操作時だけ枠を出せます。
CSSの実装テクニックを「レイアウト・装飾・アニメーション・基礎・トラブル解決」の目的別に探せる総まとめページを用意しています。実装で迷ったときの索引としてどうぞ。

目的に合わせて選べる「AI副業」「AI転職」「AI活用」の3コースを用意。副収入・キャリアチェンジ・日常の生産性アップまで、あなたのゴールに合わせてAIを学べます。
会員登録はカンタン30秒で完了します。まずは公式LINEから、無料でAI学習をスタートしましょう!
WithCodeでWeb制作を習得後、フリーランスエンジニアとして活動。HTML/CSS・JavaScript・WordPress案件を中心に年間20件以上の制作実績を持つ。「難しい技術をわかりやすく」をモットーに、初心者〜中級者向けの技術記事を執筆。副業・フリーランス独立を目指す方に向けた情報発信に注力している。
公式サイト より
今すぐ
無料カウンセリング
を予約!