コーディングをしていて意外と面倒なのがフォームのカスタマイズです。
ブラウザによって見た目がまちまちで、サイトのデザインとマッチしないことも多々あります。ただ、デフォルトのスタイルをリセットしてカスタマイズしようとしても、他のHTML要素と違って色々と面倒な点もあります。
また、カスタマイズする際はアクセシビリティにも考慮しなければいけません。
フォームのデザインは、オシャレにする必要はありません。ユーザにとってわかりやすいものにすることがベストです。
この記事では、最低限のアクセシビリティを意識した、フォームのカスタマイズを紹介します。
👇 メンターやってます 👇
模写修行やこのメディアを作ったエンジニア中心に、メンタリングサービスHello Mentorを運営しています。
- 独学に限界を感じている...
- 何をどこまで勉強すれば良いかわからない...
- 自分の書き方が正しいかわからない...
- 検索しても解決しない問題が多い...
- 転職や副業のアドバイスが欲しい...
このような方は、ぜひ下記のリンクからサービス詳細をご覧ください。個別説明会もお気軽にお申し込みください。
👆 メンターやってます 👆
この記事の目次
フォームをカスタマイズする際に気をつけること
カスタマイズする際に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();
でスケーリングすれば、ズームされずに小さく出来ます。
【駆け出しの方へ】独学に限界を感じてませんか?
プログラミングやデザインは独学可能ですが、ほとんんどの方が苦戦します。
↓このように感じていませんか?
- 何をどこまで勉強すれば良いかわからない...
- 自分の書き方が正しいかわからない...
- 検索しても解決しない問題が多い...
- 転職や副業するまでの道が見えない...
そんな問題を解決するために、模写修行やこのメディアを作ったエンジニア/デザイナー中心に、メンタリングサービスHello Mentorを始めました。
スクールのような大金は必要ありません。高額な費用は払いたくないけど、プロのサポートが欲しい方は、ぜひ下記のリンクからサービス詳細をご覧ください。
👆 メンターは全員現役エンジニア 👆
HTML・CSSでフォームをカスタマイズする方法
まずは制作したデモページをご覧ください。シンプルなデザインになっています。
- テキスト
- ラジオボタン
- チェックボックス
- セレクトボックス
- テキストエリア
- 送信ボタン
フォームで使う要素は他にもありますが、この記事ではよく使うこれら6つに絞って解説します。
リセットCSSはハード系を使えばほぼ見た目は同じになるはずです。
html {
color: #000;
background: #fff;
}
body,
div,
dl,
dt,
dd,
ul,
ol,
li,
h1,
h2,
h3,
h4,
h5,
h6,
pre,
code,
form,
fieldset,
legend,
input,
textarea,
p,
blockquote,
th,
td {
margin: 0;
padding: 0;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
fieldset,
img {
border: 0;
}
address,
caption,
cite,
code,
dfn,
em,
strong,
th,
var {
font-style: normal;
font-weight: normal;
}
ol,
ul {
list-style: none;
}
caption,
th {
text-align: left;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-size: 100%;
font-weight: normal;
}
q:before,
q:after {
content: "";
}
abbr,
acronym {
border: 0;
font-variant: normal;
}
sup {
vertical-align: text-top;
}
sub {
vertical-align: text-bottom;
}
input,
textarea,
select,
button {
font-family: inherit;
font-size: inherit;
font-weight: inherit;
line-height: inherit;
*font-size: 100%;
}
legend {
color: #000;
}
*::before,
*::after {
box-sizing: border-box;
}
/* base */
/* ---------------- */
* {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-family: "Helvetica Neue", Arial, "Hiragino Kaku Gothic ProN", "Hiragino Sans", Meiryo, sans-serif;
box-sizing: border-box;
}
body {
line-height: 1.8;
line-height: 2;
font-size: 18px;
}
a {
text-decoration: none;
color: inherit;
}
img {
width: 100%;
height: auto;
vertical-align: bottom;
}
全く同じように作りたい方は、上のリセットCSSをコピーして使ってみてください。
OS | ブラウザ |
---|---|
Mac | Safari / Chrome / Firefox |
Windows | Chrome / Firefox / Edge |
iOS | Safari / Chrome |
Android | Chrome |
ブラウザ対応はこの通りです。全て最新版でチェックしました。
テキスト編
<input type="text" name="" value="" class="c-form-text" />
.c-form-text {
height: 2.4em;
width: 100%;
padding: 0 16px;
border-radius: 4px;
border: none;
box-shadow: 0 0 0 1px #ccc inset;
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
}
.c-form-text:focus {
outline: 0;
box-shadow: 0 0 0 2px rgb(33, 150, 243) inset;
}
appearance: none;
を入れることでデフォルトのスタイルをいくつか取り除くことができます。
- 通常時はボーダーを1px
- フォーカス時はボーダーを2px
フォーカス時はボーダーを目立たせるために2pxにしています。これをborder
でやるとフォーカス時にがたつくので、ボーダーはbox-shadow
で付けています。box-shadow
でフォーカスがわかるようにしているので、outline: 0;
しても大丈夫です。
ラジオボタン編
<div class="c-form-radio">
<label>
<input type="radio" name="radio" value="1" />
<span class="c-form-radio-name">
<span class="c-form-radio-text">ラジオボタン1</span>
</span>
</label>
<label>
<input type="radio" name="radio" value="2" />
<span class="c-form-radio-name">
<span class="c-form-radio-text">ラジオボタン2</span>
</span>
</label>
</div>
.c-form-radio{
display: flex;
flex-direction: column;
align-items: flex-start;
}
.c-form-radio input {
position: absolute;
white-space: nowrap;
width: 1px;
height: 1px;
overflow: hidden;
border: 0;
padding: 0;
clip: rect(0 0 0 0);
clip-path: inset(50%);
margin: -1px;
}
.c-form-radio-name {
cursor: pointer;
display: inline-flex;
align-items: center;
color: #666;
}
.c-form-radio-name:before {
content: "";
display: inline-block;
width: 1.2em;
height: 1.2em;
border: 1px solid #ccc;
border-radius: 50%;
margin-right: 6px;
flex-shrink: 0;
}
.c-form-radio input:checked + .c-form-radio-name {
color: rgb(33, 150, 243);
}
.c-form-radio input:checked + .c-form-radio-name:before {
border: 0.35em solid rgb(33, 150, 243);
}
.c-form-radio input:focus-visible + .c-form-radio-name .c-form-radio-text {
background: linear-gradient(transparent 90%, rgba(33, 150, 243, 0.3) 90%);
}
まずはinput
を消しています。前述した通り、ここでdisplay: none;
を使ってはいけません。
あとは擬似要素のbeforeを使って、ラジオボタンを作っているだけです。
選択された時のスタイルは隣接セレクタを上手く使えばOKです。
.m-form-radio input.focus-visible + .m-form-radio-name .m-form-radio-text {
background: linear-gradient(transparent 90%, rgba(33, 150, 243, 0.3) 90%);
}
上のコードで『tabキーで操作してフォーカスした際はテキストに下線を引く』ようにしています。マウスやトラックパットでの操作でもこのスタイルを付けてしまうと、フォーカスが外れたときに、選択も外れてしまったように見えてしまうので、tabキーでの操作に限定しています。
チェックボックス編
<div class="c-form-checkbox">
<label>
<input type="checkbox" name="checkbox" value="checkform-item1" />
<span class="c-form-checkbox-name">
<span class="c-form-checkbox-text">チェックボックス1</span>
</span>
</label>
...
<label>
<input type="checkbox" name="checkbox" value="checkform-item4" />
<span class="c-form-checkbox-name">
<span class="c-form-checkbox-text">チェックボックス4</span>
</span>
</label>
</div>
.c-form-checkbox{
display: flex;
flex-direction: column;
align-items: flex-start;
}
.c-form-checkbox input {
position: absolute;
white-space: nowrap;
width: 1px;
height: 1px;
overflow: hidden;
border: 0;
padding: 0;
clip: rect(0 0 0 0);
clip-path: inset(50%);
margin: -1px;
}
.c-form-checkbox-name {
cursor: pointer;
display: inline-flex;
align-items: center;
color: #666;
position: relative;
}
.c-form-checkbox-name:before {
content: "";
display: inline-block;
width: 1.2em;
height: 1.2em;
border: 1px solid #ccc;
border-radius: 3px;
margin-right: 6px;
flex-shrink: 0;
}
.c-form-checkbox input:checked + .c-form-checkbox-name {
color: rgb(33, 150, 243);
}
.c-form-checkbox input:checked + .c-form-checkbox-name:before {
border: 1px solid rgb(33, 150, 243);
background-color: rgb(33, 150, 243);
}
.c-form-checkbox input:checked + .c-form-checkbox-name:after {
content: "";
position: absolute;
border: solid #fff;
border-width: 0 2px 2px 0;
left: 0.4em;
top: 0;
bottom: 0;
margin: auto;
width: 0.4em;
height: 0.65em;
transform: translateY(-1px) rotate(45deg);
}
.c-form-checkbox input:focus-visible + .c-form-checkbox-name .c-form-checkbox-text {
background: linear-gradient(transparent 90%, rgba(33, 150, 243, 0.3) 90%);
}
ラジオボタンとほぼ同じなので説明は割愛します。
セレクトボックス編
<div class="c-form-select">
<select>
<option value="select1">セレクト1</option>
<option value="select2">セレクト2</option>
<option value="select3">セレクト3</option>
<option value="select4">セレクト4</option>
<option value="select5">セレクト5</option>
<option value="select6">セレクト6</option>
</select>
</div>
.c-form-select {
position: relative;
}
.c-form-select:before {
content: "";
position: absolute;
top: 0;
bottom: 0;
margin: auto;
right: 12px;
width: 8px;
height: 8px;
border-top: 2px solid #333;
border-right: 2px solid #333;
transform: rotate(135deg);
pointer-events: none;
}
.c-form-select select {
height: 2.4em;
width: 100%;
padding: 0 8px;
border-radius: 4px;
border: none;
box-shadow: 0 0 0 1px #ccc inset;
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
cursor: pointer;
}
.c-form-select select::-ms-expand {
display: none;
}
.c-form-select select:focus {
outline: 0;
box-shadow: 0 0 0 2px rgb(33, 150, 243) inset;
}
appearance: none;
を入れるとデフォルトの矢印を消せます。矢印を擬似要素で作ることで、どんなブラウザでも同じ見た目にできます。
テキストエリア編
<textarea name="name" class="c-form-textarea"></textarea>
.c-form-textarea {
display: block;
width: 100%;
height: 100%;
padding: 4px 16px;
border-radius: 4px;
border: none;
box-shadow: 0 0 0 1px #ccc inset;
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
resize: vertical;
}
.c-form-textarea:focus {
outline: 0;
box-shadow: 0 0 0 2px rgb(33, 150, 243) inset;
}
テキストとほぼ同じです。
textarea
はほとんどのブラウザで、ユーザーがリサイズできるようになっています。resize: vertical;
を入れておくと横方向のリサイズを、無効にできます。
使えるブラウザは少ないですが、field-sizing: content;
を入れると、文字数に応じて自動でtextarea
のサイズを変更することもできます。
サブミットボタン編
<!-- inputタグを使う場合 -->
<input type="submit" name="" value="送信" class="c-form-submit-button" />
<!-- buttonタグを使う場合 -->
<button type="submit" class="c-form-submit-button">送信</button>
.c-form-submit-button {
display: inline-block;
width: 100%;
padding: 8px;
border: none;
border-radius: 4px;
background-color: #333;
color: #fff;
font-weight: bold;
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
cursor: pointer;
border: 2px solid transparent;
}
.c-form-submit-button:hover {
background-color: #000;
}
.c-form-submit-button:focus {
outline: 0;
background-color: #000;
border: 2px solid rgb(33, 150, 243);
}
特別難しいことはしていません。デフォルトのスタイルを消して、独自にスタイリングしているだけです。
Netlifyを使えばサーバーサイドの知識0でフォームを実装することも可能!
サイトを制作する際にフォームを設置する機会は多くあります。
NetlifyのForms機能を使うと、サーバーサイドの知識0でも簡単にオリジナルのデザインでフォームの実装が可能です。興味がある方は、ぜひ下記の記事も覗いてみてください。
NetlifyのForms機能でフォームを作る方法!サーバーサイドの知識0で実装可能!独学に限界を感じていませんか?
模写修行やこのメディアを作ったエンジニア中心に、メンタリングサービスHello Mentorを運営しています。
👇 こんな方のためのサービスです。
- 独学に限界を感じている...
- 何をどこまで勉強すれば良いかわからない...
- 自分の書き方が正しいかわからない...
- 検索しても解決しない問題が多い...
- 転職や副業のアドバイスが欲しい...
メンターを務めるのは、今も現役でコードを書いているエンジニアのみです。駆け出しの方やメンターだけをやっている方はいません。
高額な料金はかかりません。サブスク&入会金・解約料なしなので、リスクなく始められます。
少しでも興味がある方は、ぜひ下記のリンクからサービスサイトをご覧ください。個別説明会もお気軽にお越しください。(無理な営業等一切ございません!)
当メディア運営メンバーでメンターやってます!👉
詳しく見る
0からweb制作やプログラミングの勉強を始める方はもちろん、12ヶ月以上独学している方や既にお仕事をしている方にもご利用いただいています!