本記事では、HTML フォームでカスタマイズが難しい一部のウィジェットで CSS を使用する方法を見ていきます。前の記事で見たように、テキストフィールドやボタンでの CSS 使用はまったく問題がありません。ここからは、HTML フォームへのスタイル設定の影の部分を見ていきます。
始める前に、2 種類の HTML フォームウィジェットについておさらいしましょう:
- 不良
- スタイルの設定が難しく複雑なトリックが必要であり、時に CSS3 の高度な知識が必要である要素。
- 劣悪
- これらの要素では、CSS によるスタイル設定はあきらめましょう。あなたが可能なことはせいぜいわずかなものですが、それを各ブラウザに対してあてにすることはできません。また、それら要素の外見を完全にコントロールすることもできません。
CSS の表現力
テキストフィールドやボタン以外のフォームウィジェットに存在する大きな問題は多くの場合、CSS には複雑なウィジェットへ適切にスタイルを設定できるほど十分な表現力がないことです。
最近の HTML および CSS の進化により、CSS の表現力が拡張されてきました:
- CSS 2.1 の表現力は限られていましたが、疑似クラスが 3 つだけありました:
- CSS Selector Level 3 で、HTML フォームに関係する疑似クラスがいくつか追加されました:
- CSS Basic UI Level 3 でも、ウィジェットの状態を示す疑似クラスがいくつか追加されました:
- 現在も策定中で活発な議論が続く CSS Selector Level 4 では、フォーム関連の向上計画はあまりありません:
:invalid
疑似クラスの改良に過ぎない:user-error
これらすべては幸先がよいのですが、問題が 2 つあります: 第一に、必ずしも CSS 2.1 を超える機能を実装しているわけではないブラウザが存在します。第二にこれらは、例えば日付選択のような複雑なウィジェットのスタイル設定には十分ではありません。
フォームについて、CSS の表現力を拡張するためのブラウザベンダーによる実験的な機能がいくつかあり、場合によってはそれらができることを知っておくとよいでしょう。
警告: これらの実験的な機能に興味を持ったとしても、標準化されたものではないのであてにはできません。これらを使用する場合 (おそらく頻繁に使用するべきではありません) は、自己責任で行ってください。また、非標準のプロパティを使用することにより Web に対してよくないであろう行為を行っていることになります。
フォーム要素の外見を制御する
WebKit (Chrome、Safari) ベースおよび Gecko (Firefox) ベースのブラウザは、HTML ウィジェットについて高水準のカスタマイズ機能を提供します。これらはクロスプラットフォームで使用可能ですから、ネイティブのルックアンドフィールのウィジェットからユーザによるスタイル設定が可能なウィジェットへ切り替える仕組みが必要になります。
そのために、これらは独自のプロパティを使用します: -webkit-appearance
または -moz-appearance
です。これらのプロパティは非標準であり、使用するべきではありません。実際は、このプロパティの動作は WebKit と Gecko で異なります。しかし、知っておくとよい値が 1 つあります: none
です。この値によって、ウィジェットのスタイルを (ほぼ完全に) コントロールできるようになります。
よって要素へのスタイル適用で問題を抱えている場合は、この独自プロパティを使用してみましょう。これからいくつか例を見ていきますが、このプロパティのもっとも知られている使い方は、WebKit ブラウザにおける検索フィールドのスタイル設定です:
<form> <input type="search"> </form>
<style> input[type=search] { border: 1px dotted #999; border-radius: 0; -webkit-appearance: none; } </style>
注意: Web 技術について語る際に将来を予測するのは困難ですが、CSS の表現力を拡張するのは難しく、また将来の展望を示す Shadow DOM といった他の仕様の調査が行われています。十分なスタイル設定を可能にするための探求はまだ終わりません。
例
チェックボックスとラジオボタン
チェックボックスやラジオボタンに、単独でスタイルを設定するのはやや面倒です。例えばチェックボックスやラジオボタンのサイズは変更できないということであり、それを試みてもブラウザはまったく異なる動作をするでしょう。
シンプルなテストケース
以下のテストケースについて考えてみましょう:
<span><input type="checkbox"></span>
span { display: inline-block; background: red; } input[type=checkbox] { width : 100px; height: 100px; }
さまざまなブラウザでの処理方法は以下のとおりです:
ブラウザ | レンダリング |
---|---|
Firefox 16 (Mac OSX) | |
Chrome 22 (Mac OSX) | |
Opera 12.01 (Mac OSX) | |
Internet Explorer 9 (Windows 7) | |
Internet Explorer 7 (Windows XP) |
より複雑な例
Opera や Internet Explorer は -webkit-appearance
や -moz-appearance
といった機能をサポートしていませんので、それらを使用するのは不適切です。幸い、CSS には解決策を見いだせる表現力があります。一般的なサンプルを見てみましょう:
<form> <fieldset> <p> <input type="checkbox" id="first" name="fruit-1" value="cherry"> <label for="first">I like cherry</label> </p> <p> <input type="checkbox" id="second" name="fruit-2" value="banana" disabled> <label for="second">I can't like banana</label> </p> <p> <input type="checkbox" id="third" name="fruit-3" value="strawberry"> <label for="third">I like strawberry</label> </p> </fieldset> </form>
基本的なスタイル設定を伴います:
body { font: 1em sans-serif; } form { display: inline-block; padding: 0; margin : 0; } fieldset { border : 1px solid #CCC; border-radius: 5px; margin : 0; padding: 1em; } label { cursor : pointer; } p { margin : 0; } p+p { margin : .5em 0 0; }
ここで、独自のチェックボックスを持つようにスタイルを設定してみましょう。
方針として、ネイティブのチェックボックスを独自の画像で置き換えます。始めに、チェックボックスで必要とされる全状態の画像を用意しなければなりません。その状態は以下のとおりです: 未チェック、チェック済、未チェックで無効、チェック済みで無効。この画像は、CSS スプライトとして使用します:
元のチェックボックスを隠すことから始めましょう。チェックボックスを、ページのビューポートの外側に移します。ここで注意点が 2 つあります:
- 後ほど見るようにユーザがチェックボックスを使用できるようにしなければなりませんので、チェックボックスを隠すために
display:none
を使用してはいけません。display:none
を使用するとユーザはチェックボックスにアクセスできなくなり、チェックを入れたり外したりできなくなります。 - スタイルを設定するために、CSS3 のセレクタをいくつか使用します。古いブラウザをサポートするため、すべてのセレクタの前に
:root
疑似クラス付加してもかまいません。現在の実装状況では、私たちが必要とするものをサポートしている全ブラウザが:root
疑似クラスもサポートしており、その一方で他のブラウザはサポートしていません。これは、古い Internet Explorer をフィルタするのに便利な方法の例です。そのようなブラウザは通常のチェックボックスを、新しいブラウザは独自のチェックボックスを表示します。
:root input[type=checkbox] { /* 元のチェックボックスをビューポートの外側に押し出す */ position: absolute; left: -1000em; }
ネイティブのチェックボックスを除去しましたので、独自のチェックボックスを追加しましょう。そのために、元のチェックボックスの後にある <label>
要素の :before
疑似要素を使用します。よって以下のセレクタでは、チェックボックスを示すため属性セレクタを使用します。そして、元のチェックボックスの後に続く label
要素を示すために隣接セレクタを使用します。最後に :before
疑似要素へアクセスして、独自の未チェックのチェックボックス表示するスタイルを設定します。
:root input[type=checkbox] + label:before { content: ""; display: inline-block; width : 16px; height : 16px; margin : 0 .5em 0 0; background: url("https://developer.mozilla.org/files/4173/checkbox-sprite.png") no-repeat 0 0; /* 以下は、チェックボックスの位置をテキストの ベースラインに合わせるために使用します */ vertical-align: bottom; position: relative; bottom: 2px; }
状況に応じて独自のチェックボックスの状態を変更するため、元のチェックボックスで :checked
疑似クラスと :disabled
疑似クラスを使用します。CSS スプライトを用いるため、背景の位置を変更することが必要です。
:root input[type=checkbox]:checked + label:before { background-position: 0 -16px; } :root input[type=checkbox]:disabled + label:before { background-position: 0 -32px; } :root input[type=checkbox]:checked:disabled + label:before { background-position: 0 -48px; }
最後に (しかしとても重要なこと): ユーザがウィジェットを渡り歩くのにキーボードを使用するとき、各ウィジェットは視覚的にフォーカスが当たるべきです。ネイティブのチェックボックスを隠すため、ユーザがフォーム内でどこにいるかをわかるようにするには、自身でこの機能を実装しなければなりません。以下の CSS で、独自のチェックボックスのフォーカスを実装します。
:root input[type=checkbox]:focus + label:before { outline: 1px dotted black; }
結果を実際にご覧いただけます:
select の悪夢に対処する
<select>
要素はクロスプラットフォームでスタイル設定が不可能であるため、"劣悪な" ウィジェットとされています。ただし、いくつかできることがあります。長い説明はやめて、サンプルを見てみましょう:
<select> <option>Cherry</option> <option>Banana</option> <option>Strawberry</option> </select>
select { width : 80px; padding : 10px; } option { padding : 5px; color : red; }
以下の表で、さまざまなブラウザがどのように処理するかを 2 つのケースで示します。始めの 2 列は、サンプルそのものです。後の 2 列はウィジェットの外見をよりコントロールするために、以下のカスタム CSS を使用したものです:
select, option { -webkit-appearance : none; /* WebKit で外見をコントロールするため */ -moz-appearance : none; /* Gecko で外見をコントロールするため */ /* Presto (Opera) および Trident (IE) で外見をコントロールするため これは Gecko でも動作し、また WebKit でも部分的に作用することに注意 */ background : none; }
ブラウザ | 通常のレンダリング | 調整したレンダリング | ||
---|---|---|---|---|
閉じた状態 | 開いた状態 | 閉じた状態 | 開いた状態 | |
Firefox 16 (Mac OSX) | ||||
Firefox 16 (Windows 7) | ||||
Chrome 22 (Mac OSX) | ||||
Chrome 22 (Windows 7) | ||||
Opera 12.01 (Mac OSX) | ||||
Internet Explorer 9 (Windows 7) | N/A | N/A | ||
Internet Explorer 7 (Windows XP) | N/A | N/A |
ご覧いただけるように、-*-appearance
プロパティの力を借りても問題が残ります:
padding
プロパティの扱いは、オペレーティングシステムやブラウザ間で一貫性がありません。- 古い Internet Explorer ではスムーズなスタイル設定ができません。
- Firefox はドロップダウンの矢印にスタイルを設定できません。
- ドロップダウンリスト内の
<option>
要素にスタイルを設定したい場合、Chrome や Opera の動作はシステムにより大きく異なります。
またこのサンプルでは、3 つの CSS プロパティにのみ言及しています。さらに多くの CSS プロパティについて考えると混乱すると考えてください。ご覧いただけるように、CSS はこれらのウィジェットのルックアンドフィールを一貫性があるように変更するのに向いていませんが、ブラウザやオペレーティングシステムによる違いがあってもかまわないのであれば、ある程度の調整は可能です。
私たちはこちらのページで、どのプロパティが適しているかの説明を試みています: フォームウィジェット向けプロパティ実装状況一覧
よりよいフォームへの道: 役に立つライブラリとポリフィル
CSS はチェックボックスやラジオボタンには十分な表現力がありますが、より高度なウィジェットについては不十分です。<select>
要素ではいくらか可能なこともありますが、ファイルウィジェットで可能なことはまったくありません。日付選択などでも同様です。
フォームウィジェットを完全にコントロールしたいのでしたら、JavaScript に頼る以外の選択肢はありません。カスタムウィジェットの作成方法の記事にて自身でそれを行う方法を見ていきますが、あなたを助けるとても有用なライブラリがあります:
- Uni-form は、フォームのマークアップや CSS によるスタイル設定を標準化するフレームワークです。jQuery と共同で使用する際の追加機能も提供しますが、こちらの利用は任意です。
- Formalize はフォームのノーマライズやカスタマイズを支援する、一般的な JavaScript フレームワーク (jQuery、Dojo、YUI など) の拡張機能です。
- Niceforms は Web フォームの完全なカスタマイズ機能を提供する、スタンドアロンの JavaScript メソッドです。いくつかの内蔵テーマや独自のカスタムテーマを使用できます。
以下のライブラリはフォームにだけのものではありませんが、HTML フォームを扱う場合にとても興味深い機能を備えています:
- jQuery UI は日付選択 (アクセシビリティに特別な配慮をしています) などの、とても興味深く高度かつカスタマイズ可能なウィジェットを提供します。
- Twitter Bootstrap は、フォームをノーマライズしたい場合にとても役に立つでしょう。
- WebShim はブラウザの HTML5 サポートへの対処に役立つ大規模ツールです。Web フォームの部分が実に役立つでしょう。
CSS と JavaScript を一体化すると副作用が発生する可能性があると覚えておいてください。よってこれらのライブラリのいずれかを採用したら、スクリプトが失敗した場合にフォールバックするスタイルシートを用意するべきです。スクリプトが失敗する理由は特にモバイル環境でたくさんありますが、このような場合でも可能な限り最善の対処を行うよう Web サイトやアプリを設計しなければなりません。
おわりに
HTML フォームでの CSS 使用には影の部分がいまだにありますが、多くの場合は回避法があります。それらはきれいではありませんが一般的です。ただし、新しいブラウザは新たな可能性を提供します。今のところ最善の解決策は、HTML フォームウィジェットに適用された CSS について、さまざまなブラウザのサポート状況を詳しく知ることです。
本ガイドの次の記事では、さまざまな HTML フォームウィジェットが重要な CSS プロパティをどれだけサポートしているかを探っていきます: フォームウィジェット向けプロパティ実装状況一覧。