【コピペOK】HTML・CSSでフォームをカスタマイズする方法

コーディングをしていて意外と面倒なのがフォームの見た目のカスタマイズです。

フォームの各部品は、ブラウザによって見た目がまちまちで、サイトのデザインとマッチしないことも多々あります。ただ、デフォルトのスタイルをリセットしてカスタマイズしようとしても、他のHTML要素と違って色々と面倒な点もあります。

また、カスタマイズする際はアクセシビリティにも考慮しなければいけません。

フォームのデザインは、オシャレにする必要はありません。サイト全体のトンマナに合わせ、ユーザにとってわかりやすいものにすることがベストです。

この記事では、最低限のアクセシビリティを意識した、フォームのカスタマイズを紹介します。

フォーム作成に関する、知っておくおくべき知識・スキルを学べる、超マニアックなUdemyの講座を作りました。下記のリンクから飛べば、セール価格で購入できます。

gakuのアイコン

👇 メンターやってます 👇

模写修行やこのメディアを作ったメンバー中心に、Web制作業界を目指す方のための学習支援サービス 『Hello Mentor』 を運営しています。

基礎学習後に迷子になっていませんか?脱初心者したいなら、私たちにお任せください!

模写武者くんのアイコン

特にこんな方におすすめ!

  • 基礎学習後にやるべきことがわからない...
  • スクール卒だけど実力不足だと感じている...
  • 自分のコードが正しい書き方かわからない...
  • 未経験から1人で転職できる気がしない...
  • 独立するためのノウハウがない...

まずは、下記リンクから個別ガイダンスへお越しください。

受け入れ人数制限あり

詳しく見る

サブスクで入会金・解約金・最低契約期間もなし

👆 メンターやってます 👆

この記事の目次

フォームをカスタマイズする際に気をつけること

カスタマイズする際に1番見落としがちなことが、アクセシビリティへの考慮です。

  • 何らかの理由でキーボードのみで操作している方
  • 視覚に障がいがあり音声読み上げ機能を使っている方

例えば、webサイトはこのような方も使うことを考慮して、誰でもなるべく便利に使えるように作るべきです。

ここではアクセシビリティ対応を含め、最低限気を付けないといけないことを紹介します。

outlineを消さない

下記の理由より、outline: none;outline: 0;を使っているケースがありますが、これはNGです。

  • デフォルトのスタイルをリセットする
  • フォーカスリングの見栄えが悪い

キーボードのみで操作している方は、tabキーでフォーム内を移動します。outline: none;outline: 0;を使ってしまうとフォーカスが当たらず、現在どこにいるのかわからなくなってしまいます。

それでもやっぱりoutlineを消したい場合、:focus-visibleを使えば、『キーボード操作以外でフォーカスリングを消す』ことができます。

display: none;にしない

詳しくは後述しますが、ラジオボタンやチェックボックスをカスタマイズする際は、デフォルトの input タグを見た目上消します。

その際にdisplay: none;を使ってしまうと、tabキーでのフォーカスや選択が出来なくなります。

inputを見た目上消したい場合は、display: none;ではなく、opacity: 0;positionで画面外に飛ばして消しましょう。

フォントサイズは16px以上にする

iOSではフォントサイズが16pxより小さいとフォーム入力時に画面がズームされます。このズームは結構煩わしさを感じます。

16px以上にすることが無難ではありますが、どうしても16pxより小さくしたい場合は、transform: scale();でスケーリングすれば、ズームされずに小さく出来ます。

基礎学習後...迷子になっていませんか?

Web制作業界を目指す方の多くが、基礎学習後にやるべきことがわからず、迷子状態になっています。あなたも下記のように感じていませんか?

  • 基礎学習後にやるべきことがわからない...
  • スクール卒だけど実力不足だと感じている...
  • 自分のコードが正しい書き方かわからない...
  • 未経験から1人で転職できる気がしない...
  • 独立するためのノウハウがない...

そんな悩みを解決するために、模写修行やこのメディアを作ったエンジニア・デザイナー中心に、学習支援サービス 『Hello Mentor』 を運営しています。

転職成功者や副業・フリーランスデビューした方も出ています。

受け入れ人数制限あり

詳しく見る

サブスクで入会金・解約金・最低契約期間もなし

HTML・CSSでフォームをカスタマイズする方法

制作したデモページとコードは、下記から確認できます。

フォームで使う要素は他にもありますが、この記事ではよく使う下記の6つに絞って解説します。

見た目のカスタマイズやその他の知識に関して、さらに詳しく知りたい方は、下記のUdemy教材を購入してみてください。

テキスト / テキストエリア編

<!-- テキスト -->
<div class="form-item">
    <label for="name" class="form-label">テキスト</label>
    <input type="text" name="name" id="name" placeholder="山田 太郎" class="form-text" />
</div>

<!-- テキストエリア -->
<div class="form-item">
    <label for="contact" class="form-label">テキストエリア</label>
    <textarea name="contact" id="contact" placeholder="お問い合わせ内容を記入してください。" class="form-text form-text--textarea"></textarea>
</div>
.form-text {
    padding: 12px;
    border-radius: 8px;
    width: 100%;
    border: 1px solid var(--color-border);
    outline: none;
}

/* プレースホルダー */
.form-text::placeholder {
    font-weight: bold;
    color: var(--color-placeholder);
}

/* フォーカス時 */
.form-text:focus {
    outline: 1px solid var(--color-focus-border);
}

/* テキストエリア固有(高さ・自動リサイズ) */
.form-text--textarea {
    min-height: 150px;
    field-sizing: content;
}

ポイント

  • inputtype="text"textareaはほぼ同じなので、まとめて書いています。
  • リセットCSSにappearance: none;があるので、ほとんどのデフォルトのスタイルをいくつか取り除くことができます。
  • placeholderのスタイルは、::placeholderを使います。
  • outlineはデフォルトでnoneにしつつ、:focusでフォーカス時のスタイルを付けています。
  • textareaには、field-sizing: content;を入れると、文字数に応じて自動でtextareaがリサイズされます。

ラジオボタン / チェックボックス編

<!-- ラジオボタン -->
<fieldset class="form-item">
    <legend class="form-label">ラジオボタン</legend>
    <div class="form-option-wrap">
        <input type="radio" name="Radio01" value="Radio01" class="form-option form-option--radio visually-hidden" id="Radio01" />
        <label class="form-option-label form-option-label--radio" for="Radio01">
            <span>Radio01</span>
        </label>

        <input type="radio" name="Radio01" value="Radio02" class="form-option form-option--radio visually-hidden" id="Radio02" />
        <label class="form-option-label form-option-label--radio" for="Radio02">
            <span>Radio02</span>
        </label>
    </div>
</fieldset>

<!-- チェックボックス -->
<fieldset class="form-item">
    <legend class="form-label">チェックボックス</legend>
    <div class="form-option-wrap">
        <input type="checkbox" name="CheckBox01" value="CheckBox01" class="form-option form-option--checkbox visually-hidden" id="CheckBox01" />
        <label class="form-option-label form-option-label--checkbox" for="CheckBox01">
            <span>CheckBox01</span>
        </label>

        <input type="checkbox" name="CheckBox02" value="CheckBox02" class="form-option form-option--checkbox visually-hidden" id="CheckBox02" />
        <label class="form-option-label form-option-label--checkbox" for="CheckBox02">
            <span>CheckBox02</span>
        </label>
    </div>
</fieldset>
.form-option-wrap {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
}

.form-option-label {
    --radio-checkbox-size: 24px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-weight: bold;
    position: relative;
    cursor: pointer;
}

/* ラベルテキスト(透明のborderでフォーカス時のレイアウトシフトを防止) */
.form-option-label span {
    --form-option-underline-width: 2px;
    opacity: 0.7;
    border-top: var(--form-option-underline-width) solid transparent;
    border-bottom: var(--form-option-underline-width) solid transparent;
}

/* ラジオ/チェックボックスの枠(::beforeで描画) */
.form-option-label::before {
    content: "";
    display: inline-block;
    width: var(--radio-checkbox-size);
    height: var(--radio-checkbox-size);
    border: 1px solid var(--color-border);
    flex-shrink: 0;
}

/* ラジオ用・丸形 */
.form-option-label--radio::before {
    border-radius: 50%;
}

/* チェックボックス用・角丸四角 */
.form-option-label--checkbox::before {
    border-radius: 4px;
}

/* チェック時のラベルテキスト */
.form-option:checked + .form-option-label span {
    color: var(--color-primary);
    opacity: 1;
}

/* チェック時の枠(背景色をprimaryに) */
.form-option:checked + .form-option-label::before {
    background-color: var(--color-primary);
    border-color: var(--color-primary);
}

/* チェック時のアイコン(::after + mask-imageで白い図形を表示) */
.form-option:checked + .form-option-label::after {
    content: "";
    position: absolute;
    left: 0;
    top: 50%;
    width: var(--radio-checkbox-size);
    height: var(--radio-checkbox-size);
    transform: translateY(-50%);
    background-color: var(--color-white);
    mask-size: contain;
    mask-position: center;
    mask-repeat: no-repeat;
}

/* ラジオ用・丸アイコン */
.form-option--radio:checked + .form-option-label--radio::after {
    mask-image: url(../img/icon-radio.svg);
}

/* チェックボックス用・チェックマークアイコン */
.form-option--checkbox:checked + .form-option-label--checkbox::after {
    mask-image: url(../img/icon-check.svg);
}

/* フォーカス時のラベル(下線で表示) */
.form-option:focus-visible + .form-option-label span {
    opacity: 1;
    border-bottom: var(--form-option-underline-width) solid var(--color-focus-border);
}

ポイント

  • ラジオボタンとチェックボックスはほぼ同じなので、まとめて書いています。
  • fieldsetlegendを使って、ラジオボタンとチェックボックスをグループ化しています。
  • inputを画面から消すために、display: none;を使ってはいけません。visually-hiddenで見た目上消しています。
  • 擬似要素を使って、ラジオボタン / チェックボックスのマークを作っています。できる限りコードを共通化したかったので、マークは画像で作りました。
  • 選択された時のスタイルは、隣接セレクタを使って付けています。

セレクトボックス編

<!-- セレクトボックス -->
<div class="form-item">
    <label for="select" class="form-label">セレクトボックス</label>
    <div class="form-select-wrap">
        <select name="select" id="select" class="form-select">
            <option value="option01">option01</option>
            <option value="option02">option02</option>
            <option value="option03">option03</option>
        </select>
    </div>
</div>
.form-select-wrap {
    position: relative;
}

/* プルダウン矢印(borderで三角形を描画して45度回転) */
.form-select-wrap::after {
    content: "";
    display: inline-block;
    width: 10px;
    height: 10px;
    position: absolute;
    right: 18px;
    top: 50%;
    translate: 0 -50%;
    border-right: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    rotate: 45deg;
    pointer-events: none;
}

.form-select {
    padding: 12px;
    border-radius: 8px;
    width: 100%;
    outline: none;
    border: 1px solid var(--color-border);
}

/* セレクトのフォーカス時 */
.form-select:focus {
    outline: 1px solid var(--color-focus-border);
}

ポイント

  • 矢印を擬似要素で作ることで、どんなブラウザでも同じ見た目にできます。
  • 矢印にpointer-events: none;を入れて、クリックイベントを無効化しています。これがないと、矢印部分をクリックしても、プルダウンが開きません。

サブミットボタン編

<!-- 送信ボタン -->
<div class="form-item">
    <button class="form-button">送信する</button>
</div>
.form-button {
    background-color: var(--color-black);
    color: var(--color-white);
    display: block;
    padding: 14px 24px;
    font-weight: bold;
    border-radius: 100vh;
    outline: none;
    border: 3px solid var(--color-black);
    transition:
        background-color 0.3s,
        border 0.3s;
}

@media (any-hover: hover) {
    .form-button:hover {
        background-color: var(--color-black-hover);
        border: 3px solid var(--color-black-hover);
    }
}

.form-button:focus {
    background-color: var(--color-black-focus);
    border: 3px solid var(--color-focus-border);
}

ポイント

  • ボタンにはhover時のスタイルも付けます。

Udemyではさらに詳しく学べる

Udemyでは、フォームのカスタマイズだけでなく、下記のような内容も学べます。

  • フォームに使うHTMLタグ全般
  • バリデーション
  • 郵便番号からの住所自動入力
  • 隠しフィールドの使い方
  • スパム対策
  • ヘッドレスフォームを使ったフォーム作成
  • WordPressのプラグインを使ったフォーム作成

これらはコーダーとして知っておくべき知識・スキルです。不安な点が多い方は、下記のUdemy教材を購入してみてください。

基礎学習後...迷子になっていませんか?

模写修行やこのメディアを作ったメンバー中心に、Web制作業界を目指す方のための学習支援サービス 『Hello Mentor』 を運営しています。

下記のような、基礎学習後にやるべきことがわからず、迷子状態になっている方に特におすすめです

  • 基礎学習後にやるべきことがわからない...
  • スクール卒だけど実力不足だと感じている...
  • 自分のコードが正しい書き方かわからない...
  • 未経験から1人で転職できる気がしない...
  • 独立するためのノウハウがない...

メンターは、全員が現役のプロです。駆け出しの方やメンターだけをやっている方はいません。

少数精鋭で運営しているため、受け入れ人数に限りがあります。本気でWeb制作業界を目指している方は、ぜひご検討ください。

受け入れ人数制限あり

詳しく見る

サブスクで入会金・解約金・最低契約期間もなし

この記事を書いた人

Gakuのアイコン

Gaku /

フリーランス8年を経て法人化(4期目)。コンテンツ制作、ライティング、マーケティング、デザイン、コーディング、プログラミングなど、幅広くやってます!

Web制作会社が運営する学習支援サービス👉

詳しく見る
模写修行のトップページのスクリーンショット

完全無料のコーディング練習サイト