■完成イメージ
ブラウザ標準のフォームUI(チェックボックスやセレクトボックス)のデザインは、標準ゆえに「フォーム」だと分かりやすいデザインですが、どうしてもサイトカラーに合わずに野暮ったい印象になるときがあります。そういった場合にデザインを自由に変更できるといいのですが、フォームUIへのスタイル適用は制限があり、自由に変更できません。
そういったときに、実際のフォームUIを隠し独自のフォームUIを表示し、それに対して行ったアクションを隠してあるフォームUIに反映させる手法があります(ここでは擬似フォームUIと呼びます)。
本コラムでは主にスマートフォン向けにCSS3とJavaScript(jQuery)を使い、画像を使わない擬似フォームUIの作り方を4回に分けて紹介していきます。
※PCではGoogle Chromeのみ動作確認をしています。
第01回目の今回はCSS3を使った装飾と後ほどjQueryで扱いやすくするためのマークアップを行なっていきます。
STEP01 フォーム要素を配置する
この時点でのサンプルを表示する
まずは何はともあれフォーム要素が必要ですので、チェックボックス・ラジオボタン・セレクトボックスを配置した次のようなHTMLを用意します。
001 | <form action= "" method= "post" > |
002 | <div class= "inputBox" > |
003 | <label for = "fName" >お名前</label> |
004 | <input type= "text" name= "" value= "" id= "fName" > |
006 | <div class= "inputBox" > |
007 | <div class= "label" >チェックボックス(複数)</div> |
009 | <li><label><input type= "checkbox" name= "cb1" value= "" >国内</label></li> |
010 | <li><label><input type= "checkbox" name= "cb2" value= "" >国際</label></li> |
011 | <li><label><input type= "checkbox" name= "cb3" value= "" >経済</label></li> |
012 | <li><label><input type= "checkbox" name= "cb4" value= "" >エンタメ</label></li> |
013 | <li><label><input type= "checkbox" name= "cb5" value= "" >スポーツ</label></li> |
014 | <li><label><input type= "checkbox" name= "cb6" value= "" >IT</label></li> |
017 | <div class= "inputBox" > |
018 | <div class= "label" >チェックボックス</div> |
020 | <li><label><input type= "checkbox" name= "cbs" value= "" >指定しない</label></li> |
024 | <div class= "inputBox" > |
025 | <div class= "label" >ラジオボタン(複数)</div> |
027 | <li><label><input type= "radio" name= "rb" value= "" >指定しない</label></li> |
028 | <li><label><input type= "radio" name= "rb" value= "" >午前</label></li> |
029 | <li><label><input type= "radio" name= "rb" value= "" >午後</label></li> |
030 | <li><label><input type= "radio" name= "rb" value= "" >10~11時</label></li> |
031 | <li><label><input type= "radio" name= "rb" value= "" >11~12時</label></li> |
032 | <li><label><input type= "radio" name= "rb" value= "" >12~13時</label></li> |
035 | <div class= "inputBox" > |
036 | <div class= "label" >ラジオボタン</div> |
038 | <li><label><input type= "radio" name= "rbs" value= "" >指定しない</label></li> |
042 | <div class= "inputBox" > |
043 | <label for = "fPref" >セレクト</label> |
044 | <select name= "都道府県" id= "fPref" > |
045 | <option value= "" >都道府県をお選びください。</option> |
046 | <optgroup label= "北海道・東北" > |
047 | <option value= "北海道" >北海道</option> |
048 | <option value= "青森県" >青森県</option> |
049 | <option value= "秋田県" >秋田県</option> |
050 | <option value= "岩手県" >岩手県</option> |
051 | <option value= "山形県" >山形県</option> |
052 | <option value= "宮城県" >宮城県</option> |
053 | <option value= "福島県" >福島県</option> |
055 | <optgroup label= "甲信越・北陸" > |
056 | <option value= "山梨県" >山梨県</option> |
057 | <option value= "長野県" >長野県</option> |
058 | <option value= "新潟県" >新潟県</option> |
059 | <option value= "富山県" >富山県</option> |
060 | <option value= "石川県" >石川県</option> |
061 | <option value= "福井県" >福井県</option> |
063 | <optgroup label= "関東" > |
064 | <option value= "茨城県" >茨城県</option> |
065 | <option value= "栃木県" >栃木県</option> |
066 | <option value= "群馬県" >群馬県</option> |
067 | <option value= "埼玉県" >埼玉県</option> |
068 | <option value= "千葉県" >千葉県</option> |
069 | <option value= "東京都" >東京都</option> |
070 | <option value= "神奈川県" >神奈川県</option> |
072 | <optgroup label= "東海" > |
073 | <option value= "愛知県" >愛知県</option> |
074 | <option value= "静岡県" >静岡県</option> |
075 | <option value= "岐阜県" >岐阜県</option> |
076 | <option value= "三重県" >三重県</option> |
078 | <optgroup label= "関西" > |
079 | <option value= "大阪府" >大阪府</option> |
080 | <option value= "兵庫県" >兵庫県</option> |
081 | <option value= "京都府" >京都府</option> |
082 | <option value= "滋賀県" >滋賀県</option> |
083 | <option value= "奈良県" >奈良県</option> |
084 | <option value= "和歌山県" >和歌山県</option> |
086 | <optgroup label= "中国" > |
087 | <option value= "岡山県" >岡山県</option> |
088 | <option value= "広島県" >広島県</option> |
089 | <option value= "鳥取県" >鳥取県</option> |
090 | <option value= "島根県" >島根県</option> |
091 | <option value= "山口県" >山口県</option> |
093 | <optgroup label= "四国" > |
094 | <option value= "徳島県" >徳島県</option> |
095 | <option value= "香川県" >香川県</option> |
096 | <option value= "愛媛県" >愛媛県</option> |
097 | <option value= "高知県" >高知県</option> |
099 | <optgroup label= "九州・沖縄" > |
100 | <option value= "福岡県" >福岡県</option> |
101 | <option value= "佐賀県" >佐賀県</option> |
102 | <option value= "長崎県" >長崎県</option> |
103 | <option value= "熊本県" >熊本県</option> |
104 | <option value= "大分県" >大分県</option> |
105 | <option value= "宮崎県" >宮崎県</option> |
106 | <option value= "鹿児島県" >鹿児島県</option> |
107 | <option value= "沖縄県" >沖縄県</option> |
112 | <div class= "cancel" ><button type= "button" >キャンセル</button></div> |
113 | <div class= "send" ><button type= "submit" >送信</button></div> |
STEP02 レイアウトの調整を行なう
この時点でのサンプルを表示する
万が一、偽装フォームUIのCSSが効かなくなった場合のために最低限のレイアウト調整を行なっておきます。
02 | padding: 10px 10px 15px; |
03 | border-top: 1px solid rgba(0, 0, 0, 0.2); |
04 | border-bottom: 1px solid rgba(255, 255, 255, 0.7); |
07 | .inputBox:first-child { |
19 | -webkit-box-sizing: border-box; |
20 | box-sizing: border-box; |
STEP03 チェックボックスとラジオボタンの偽装フォームUIを作成する
この時点でのサンプルを表示する
フォーム動作のための最低限の準備が整ったら偽装フォームUIを作成していきます。まずは、チェックボックスとラジオボタンを作成したいと思います。
このとき、単にスタイルを作るだけではなく今後のことを考えHTML構造も扱いやすいように調整していきます。
01 | <form action= "" method= "post" class= "pseudoForm" > |
02 | <div class= "inputBox" > |
03 | <div class= "label" >チェックボックス(複数)</div> |
04 | <div class= "pseudoUI-cb" > |
06 | <li><label><input type= "checkbox" name= "cb1" value= "" >国内</label></li> |
07 | <li><label><input type= "checkbox" name= "cb2" value= "" >国際</label></li> |
08 | <li><label><input type= "checkbox" name= "cb3" value= "" >経済</label></li> |
09 | <li><label><input type= "checkbox" name= "cb4" value= "" >エンタメ</label></li> |
10 | <li><label><input type= "checkbox" name= "cb5" value= "" >スポーツ</label></li> |
11 | <li><label><input type= "checkbox" name= "cb6" value= "" >IT</label></li> |
15 | <div class= "inputBox" > |
16 | <div class= "label" >チェックボックス</div> |
17 | <div class= "pseudoUI-cb" > |
19 | <li><label><input type= "checkbox" name= "cbs" value= "" >指定しない</label></li> |
24 | <div class= "inputBox" > |
25 | <div class= "label" >ラジオボタン(複数)</div> |
26 | <div class= "pseudoUI-rb" > |
28 | <li><label><input type= "radio" name= "rb" value= "" >指定しない</label></li> |
29 | <li><label><input type= "radio" name= "rb" value= "" >午前</label></li> |
30 | <li><label><input type= "radio" name= "rb" value= "" >午後</label></li> |
31 | <li><label><input type= "radio" name= "rb" value= "" >10~11時</label></li> |
32 | <li><label><input type= "radio" name= "rb" value= "" >11~12時</label></li> |
33 | <li><label><input type= "radio" name= "rb" value= "" >12~13時</label></li> |
37 | <div class= "inputBox" > |
38 | <div class= "label" >ラジオボタン</div> |
39 | <div class= "pseudoUI-rb" > |
41 | <li><label><input type= "radio" name= "rbs" value= "" >指定しない</label></li> |
まずHTMLですが、擬似フォームUIを実装するフォームとそうでないフォームとを分けられるようにしたいため、form要素には「.pseudoForm」というクラスを追加し、チェックボックスとラジオボタンはそれぞれ、div要素で囲い「.pseudoUI-cb」と「.pseudoUI-rb」というクラスを追加しています。「pseudoUI」が「擬似UI」という意味で、続く「cb」と「rb」はチェックボックスとラジオボタンという意味でクラス名をつけています。
このように特別なクラスを用意しておくことで、これらのクラス名がつけられたもののみ擬似フォームUIにすることができるため汎用性が高くなります。また、後ほどJavaScriptでDOM操作をする際にもこのクラス名を対象にすることとなります。
10 | padding: 17px 10px 15px 38px; |
11 | background-image: -webkit-gradient(linear, left top, left bottom, |
12 | from( #fff), to(#ECECEC)); |
13 | background-image: linear-gradient( #fff, #ECECEC); |
14 | border: 1px solid #ccc; |
19 | .pseudoUI-cb li:first-child, |
20 | .pseudoUI-rb li:first-child { |
21 | border-top: 1px solid #ccc; |
22 | -webkit-border-radius: 5px 5px 0 0; |
25 | .pseudoUI-cb li:last-child, |
26 | .pseudoUI-rb li:last-child { |
27 | -webkit-border-radius: 0 0 5px 5px; |
28 | border-radius: 0 0 5px 5px; |
31 | .pseudoUI-cb li:only-child, |
32 | .pseudoUI-rb li:only-child { |
33 | border: 1px solid #ccc; |
34 | -webkit-border-radius: 5px; |
38 | .pseudoUI-cb li:before, |
39 | .pseudoUI-rb li:before { |
43 | border: 1px solid #ccc; |
44 | -webkit-border-radius: 5px; |
46 | background-image: -webkit-gradient(linear, left top, left bottom, |
47 | from( #eee), to(#ddd)); |
48 | background-image: linear-gradient( #eee, #ddd); |
49 | -webkit-box-shadow: inset 0 0 1px rgba(0, 0, 0, 0.2); |
50 | box-shadow: inset 0 0 1px rgba(0, 0, 0, 0.2); |
55 | -webkit-box-sizing: border-box; |
56 | box-sizing: border-box; |
59 | .pseudoUI-cb li:after { |
63 | background-color: #9c3; |
64 | box-shadow: 0 0 1px rgba(0, 0, 0, 0.5); |
72 | .pseudoUI-rb li:before { |
73 | -webkit-border-radius: 10px; |
77 | .pseudoUI-rb li:after { |
82 | background-color: #9c3; |
83 | -webkit-box-shadow: 0 0 1px rgba(0, 0, 0, 0.5); |
84 | box-shadow: 0 0 1px rgba(0, 0, 0, 0.5); |
85 | -webkitborder-radius: 6px; |
94 | .pseudoUI-cb input[type= "checkbox" ], |
95 | .pseudoUI-rb input[type= "radio" ] { |
次にCSSですが、擬似要素やCSS3のグラデーション・ドロップシャドウなどを使い、div要素や画像を使わずに装飾を行なっていきます。
グラデーションや角丸はCSS3から追加されたbackground-image: linear-gradientとborder-radiusを使うことで画像を使わずに実装することができます。
※古いバージョンのブラウザに対応するためにベンダープレフィックス(-webkit-○○)が必要です。
角丸はli要素の最初と最後に必要となりますので、:first-child/:last-child擬似クラスを使います。
01 | .pseudoUI-cb li:first-child, |
02 | .pseudoUI-rb li:first-child { |
03 | border-top: 1px solid #ccc; |
04 | -webkit-border-radius: 5px 5px 0 0; |
05 | border-radius: 5px 5px 0 0; |
08 | .pseudoUI-cb li:last-child, |
09 | .pseudoUI-rb li:last-child { |
10 | -webkit-border-radius: 0 0 5px 5px; |
11 | border-radius: 0 0 5px 5px; |
ちなみに・・・
:first-childはCSS3で追加された:last-childと似ているためCSS3で追加されたものと思ってしまいますが、CSS2で既にサポートされている擬似クラスです。クロスブラウザの問題からPCサイトで使われることはあまりありませんが、スマートフォンサイトでは問題なく使うことができます。
更にli要素が1つしかない場合のことも考え、:only-child擬似クラスを使い兄弟要素がない場合には4つの角が角丸になるようにしておきます。
1 | .pseudoUI-cb li:only-child, |
2 | .pseudoUI-rb li:only-child { |
3 | border: 1px solid #ccc; |
4 | -webkit-border-radius: 5px; |
最後にチェックボックスの□の部分(ラジオボタンなら○の部分)を作成していきます。この部分は装飾用の空divを作る方法もありますが、無駄なHTMLが増えないよう:before擬似要素を使います。
01 | .pseudoUI-cb li:before, |
02 | .pseudoUI-rb li:before { |
06 | border: 1px solid #ccc; |
07 | -webkit-border-radius: 5px; |
09 | background-image: -webkit-gradient(linear, left top, left bottom, |
10 | from( #eee), to(#ddd)); |
11 | background-image: linear-gradient( #eee, #ddd); |
12 | -webkit-box-shadow: inset 0 0 1px rgba(0, 0, 0, 0.2); |
13 | box-shadow: inset 0 0 1px rgba(0, 0, 0, 0.2); |
18 | -webkit-box-sizing: border-box; |
19 | box-sizing: border-box; |
22 | .pseudoUI-rb li:before { |
23 | -webkit-border-radius: 10px; |
擬似要素はそのままでは領域を持たないため、内容は空でいいのでcontentプロパティとdisplayプロパティで領域を作成する必要があります(今回はpositionプロパティを使っているのでdisplayプロパティは必要ありません)。また、擬似要素は指定した要素の内側にできるため、要素にposition: relativeを指定しておくことで、position: absoluteで自由に配置することができます。
ちなみに・・・
:before/:after擬似要素はCSS3ではコロンを2つ書く(ダブルコロン)書式に変更されましたが、Internet Explorer8では認識されないため、現状ではシングルコロンで統一した方が無難で間違いも起こりません。
装飾は角丸・グラデーション・ドロップシャドウ(box-shadow: inset 0 0 1px rgba(0, 0, 0, 0.2);)を使い質感を出します。
CSSを見るとbox-sizingというCSSプロパティがありますが、これはCSS3で追加されたもので、ボックスサイズの大きさの計算式を変更することができます。ボックスサイズは通常の場合、「width + padding + border」という計算式によって確定されますが、box-sizing: border-boxと指定することで、widthの値がそのままボックスサイズになり、paddingとborder分の領域はwidthの中に含まれることになります。こちらの方がボックスサイズの把握がしやすいため扱いやすくなります。
その他、大きさや位置の調整と標準のフォームUIを隠すなどの調整を細々と行なって完成ですが、選択された際のマークが作られていません。これは後ほどJavaScriptと一緒に作成します。
STEP04 セレクトボックスの偽装フォームUIを作成する
この時点でのサンプルを表示する
引き続き、セレクトボックスの擬似フォームUIを作成していきます。
01 | <div class= "inputBox fPref" > |
02 | <label for = "fPref" >セレクト</label> |
03 | <div class= "pseudoUI-select" > |
04 | <select name= "都道府県" id= "fPref" > |
05 | <option value= "" >都道府県をお選びください。</option> |
06 | <optgroup label= "北海道・東北" > |
07 | <option value= "北海道" >北海道</option> |
08 | <option value= "青森県" >青森県</option> |
09 | <option value= "秋田県" >秋田県</option> |
10 | <option value= "岩手県" >岩手県</option> |
11 | <option value= "山形県" >山形県</option> |
12 | <option value= "宮城県" >宮城県</option> |
13 | <option value= "福島県" >福島県</option> |
15 | <optgroup label= "甲信越・北陸" > |
16 | <option value= "山梨県" >山梨県</option> |
17 | <option value= "長野県" >長野県</option> |
18 | <option value= "新潟県" >新潟県</option> |
19 | <option value= "富山県" >富山県</option> |
20 | <option value= "石川県" >石川県</option> |
21 | <option value= "福井県" >福井県</option> |
24 | <option value= "茨城県" >茨城県</option> |
25 | <option value= "栃木県" >栃木県</option> |
26 | <option value= "群馬県" >群馬県</option> |
27 | <option value= "埼玉県" >埼玉県</option> |
28 | <option value= "千葉県" >千葉県</option> |
29 | <option value= "東京都" >東京都</option> |
30 | <option value= "神奈川県" >神奈川県</option> |
33 | <option value= "愛知県" >愛知県</option> |
34 | <option value= "静岡県" >静岡県</option> |
35 | <option value= "岐阜県" >岐阜県</option> |
36 | <option value= "三重県" >三重県</option> |
39 | <option value= "大阪府" >大阪府</option> |
40 | <option value= "兵庫県" >兵庫県</option> |
41 | <option value= "京都府" >京都府</option> |
42 | <option value= "滋賀県" >滋賀県</option> |
43 | <option value= "奈良県" >奈良県</option> |
44 | <option value= "和歌山県" >和歌山県</option> |
47 | <option value= "岡山県" >岡山県</option> |
48 | <option value= "広島県" >広島県</option> |
49 | <option value= "鳥取県" >鳥取県</option> |
50 | <option value= "島根県" >島根県</option> |
51 | <option value= "山口県" >山口県</option> |
54 | <option value= "徳島県" >徳島県</option> |
55 | <option value= "香川県" >香川県</option> |
56 | <option value= "愛媛県" >愛媛県</option> |
57 | <option value= "高知県" >高知県</option> |
59 | <optgroup label= "九州・沖縄" > |
60 | <option value= "福岡県" >福岡県</option> |
61 | <option value= "佐賀県" >佐賀県</option> |
62 | <option value= "長崎県" >長崎県</option> |
63 | <option value= "熊本県" >熊本県</option> |
64 | <option value= "大分県" >大分県</option> |
65 | <option value= "宮崎県" >宮崎県</option> |
66 | <option value= "鹿児島県" >鹿児島県</option> |
67 | <option value= "沖縄県" >沖縄県</option> |
02 | padding: 17px 35px 15px 10px; |
04 | background-image: -webkit-gradient(linear, left top, left bottom, |
05 | from( #fff), to(#DBDBDB)); |
06 | background-image: linear-gradient( #fff, #DBDBDB); |
07 | border: 1px solid #ccc; |
09 | display: inline-block; |
12 | vertical-align: middle; |
13 | -webkit-box-sizing: border-box; |
14 | box-sizing: border-box; |
17 | .pseudoUI-select:before { |
21 | border: 1px solid #ccc; |
22 | -webkit-border-radius: 10px; |
24 | background-image: -webkit-gradient(linear, left top, left bottom, |
25 | from( #ddd), to(#aaa)); |
26 | background-image: linear-gradient( #ddd, #aaa); |
27 | -webkit-box-shadow: inset 0 0 1px rgba(0, 0, 0, 0.2); |
28 | box-shadow: inset 0 0 1px rgba(0, 0, 0, 0.2); |
33 | -webkit-box-sizing: border-box; |
34 | box-sizing: border-box; |
37 | .pseudoUI-select:after { |
41 | border: 5px solid transparent; |
42 | border-top-color: #fff; |
49 | .pseudoUI-select select { |
HTMLの変更やCSSによる装飾はチェックボックスと同じなため、特別難しいことはありませんが、▼の部分にちょっとしたテクニックが必要です。これに関しては文章で説明するよりも図の方がわかりやすいと思いますので次の図解をご覧ください。
また、セレクトボックスの場合は標準のフォームUIをdisplay: noneで非表示にしないことがポイントです。
チェックボックスやラジオボタンはJavaScriptでchecked属性を与えることで選択・非選択状態の操作をすることができますが、セレクトボックスはJavaScriptで開くことができません。そのため、セレクトボックスはopacityプロパティを使い、実際はあるけど見えない状態にします。また、大きさを擬似フォームUIと同じにしなければタップしてもプルダウンが開かない領域ができてしまうため、width/heightを100%にしてフィットするようにします。
実際にブラウザで開きタップしてプルダウンが開かれることを確認できたら完成です。また、この時点ではセレクトボックスで選んだ内容が表示されないため、JavaScriptで調整を行います。
以上でCSS3を使った擬似フォームUIの装飾が完成しました、次回は一番の肝となるJavaScript(jQuery)による擬似フォームUIと標準フォームUIの同期操作を行います。
画像を使わずに作る擬似フォームUIの作り方
- 第01回 「CSS3を使った装飾」
- 第02回 「jQueryを使った擬似フォームUIの操作」
- 第03回 「タップ時のレスポンスの向上」
- 第04回 「仕上げ」