arrow一覧に戻る

2021.10.02

CSSが効かないUIコンポーネントのデザイン適用のテクニック

フロントエンドエンジニアの悩みごと

デザイナーから画面デザインを渡されたときに、「うわぁ、このデザインどう実装しよう……」と思った経験がまったくないというフロントエンドエンジニアはまずいないでしょう。
デザイナーのこだわりは理解するし、できる限りデザインは再現してあげたいけど、現実的に難しくないか……という、理想と現実、デザインと技術の板挟みで苦労するのがフロントエンドエンジニアだったりします。

フォーム部品のカスタムデザインは面倒

とくに面倒なのがフォーム部品です。
チェックボックス、ラジオボタン、セレクトボックスなどのフォーム部品はブラウザ側でUIを描画するため、ブラウザの種類によって見た目が異なります。

デザイナーとしてはブラウザ間の見た目の違いをなくしたい。
そもそも、ブラウザ標準のフォーム部品の見た目がダサい。
などの理由で、フォーム部品のデザインをカスタマイズしたいという欲求があるのはよくわかります。
エンジニアの私からしても、デフォルトのフォーム部品はダサいと思いますし。

ただ、実装する上で問題があります。

フォーム部品への CSS 適用は設定できないところが多い

そうなんです、CSS が効かないんです。

MDN のドキュメントにもこんな記載があります。

なぜ CSS によるフォームウィジェットへのスタイル設定は困難であるか?

CSS を伴ってもすべてのウィジェットが同等に作成されるわけではありません

いまだに、フォームで CSS を使用する際に困ることが存在します。この問題は、3 つのカテゴリーに分けられます。

良好
いくつかの要素はプラットフォーム間の問題があるとしても、ほとんど問題なくスタイルを設定できます。これらは以下の構造的な要素が含まれます:
(中略)

不良
一部の要素はほとんどスタイル設定ができず、時に CSS3 の高度な知識やトリックが必要になるかもしれません。
・チェックボックスとラジオボタン
・<input type=”search” />

劣悪
一部の要素は、CSS でスタイルを設定できません。たとえば次のもの:
<input type=”color” />
<input type=”datetime-local” /> のような日付関連コントロール
<input type=”range” />
<input type=”file” />
ドロップダウンウィジェットの作成に含まれる要素、<select/>,
<option>, </option>
<optgroup>, </optgroup>
</select>

<datalist>を含む。
<progress> と <meter></meter></progress></datalist></blockquote>

「良好」にカテゴライズされるフォーム部品は大丈夫です。
ほとんどデザイナーの要望通りに CSS でカスタマイズできるでしょう。

「劣悪」にカテゴライズされるものについては、HTML 要素を使うのをやめて、同等の機能のあるライブラリを使うか、独自で実装するか、デザインをカスタマイズするのを諦めるかという選択になることが多いです。
カレンダーやカラーピッカー、プルダウンリストなどはその代表例です。

「不良」にカテゴライズされるものは頑張ればなんとかなります。
CSS のテクニックを駆使すれば、かなりの部分でデザイナーの要望に応えられるはずです。

「不良」フォーム部品へのデザイン適用の方法

ここからは実装例のコードとともに、実装のポイントやテクニックについて解説していこうと思います。
今回はチェックボックス、ラジオボタンと、応用例としてトグルスイッチの実装方法を紹介します。

対応環境は各ブラウザの最新バージョンとします。(IE11 ? いったん忘れましょう……)

チェックボックス

CSS のスタイルが効かないブラウザ標準の UI をどうやってカスタマイズするか、その実装方法を見ていきましょう。
今回実装するのは、こんなデザインのチェックボックスです。

HTML

<label class="checkbox">
    <input type="checkbox" class="checkbox__input" />
    <span class="checkbox__text">チェックボックス</span>
</label>

HTML の実装ポイントは  input タグを label タグで囲んでいるところです。
この構造にすることによって、label と input を for と id で関連づけなくて済み、コーディングの手間が省けます。

CSS

.checkbox {
    position: relative;
    display: inline-block;
    cursor: pointer;
    margin: 0;
}

.checkbox__input {
    appearance: none;    /* ① */
    -webkit-appearance: none;
    -moz-appearance: none;
    display: block;
    width: 18px;    /* ② ここから */
    height: 18px;
    border: 1px solid #9eacc7;
    border-radius: 2px;
    background-color: #fff;    /* ② ここまで */
    position: absolute;
    left: 0;
    top: 50%;  /* ③ */
    transform: translateY(-50%);    /* ③ */
    cursor: pointer;
    margin: 0;
}

.checkbox__input:checked {    /* ④ */
    border-color: #1ea7fd;
    background-color: #1ea7fd;
}

.checkbox__input:checked::after {    /* ⑤ */
    content: "";
    display: block;
    position: absolute;
    left: 2px;
    top: 2px;
    width: 10px;    /* ⑥ ここから */
    height: 6px;
    border-left: 2px solid #fff;
    border-bottom: 2px solid #fff;
    transform: rotate(-45deg);    /* ⑥ ここまで */
}

.checkbox__text {
    padding-left: 25px;
    display: inline-block;
    color: #333;
}

CSS の実装ポイントとテクニックについて上から見ていきます。

① ブラウザの標準 UI を非表示にする
ブラウザの標準 UI の見た目は CSS で変更できません。
ですので、appearance プロパティを none に設定して消してしまいます。
その上で CSS で新しいデザインを描き直します。

appearance プロパティは Safari、FireFox ではベンダープレフィックスが必要ですので、合わせて設定しましょう。

② inputタグでチェックボックスの四角を描画する
ブラウザの標準 UI を非表示にすると、チェックボックスの input タグのサイズや背景、角丸などが設定できるようになります。
これを使って、チェックボックスの枠の四角を描画します。

③ 縦中央揃えのテクニック
position: absolute で絶対配置にした場合、top: 50% を指定すると、要素の上部が 50% の位置に配置されるため、中央より下に配置されて期待通りの縦中央揃えになりません。
これを期待通りの配置にするために、transform: translateY(-50%) で要素の高さの 50% だけ上にずらします。
これできれいに縦中央揃えを実現することができます。

④ チェックが入ったときのスタイル設定(四角)
チェックボックスに checked になったときに、チェックボックスの四角を青色に変更します。

⑤ チェックが入ったときのスタイル設定(チェック)
チェックボックスに checked になったときの、✓ は after 疑似要素を使って描画します。

⑥ ✓ の形の描画テクニック
左と下の border をつけて −45 度回転することで ✓ の形を描画しています。
width と height の長さを調整して長方形にすることで、✓ にしていますが、width と height を同じ長さにして正方形にすることで下矢印にすることもできます。
また、回転角度を変えることで上下左右の矢印が作れるのでテクニックとして覚えておくと良いと思います。

このように、CSS でスタイルを変更できない部分を非表示にした上で、before と after の疑似要素を組み合わせることで、変更が難しく、一見複雑に見えるデザインも CSS だけで実装することができます。

ラジオボタン

ラジオボタンも四角と ✓ を丸で描画するところが違いますが、基本的に同じ方法で実装できますので試してみてください。

トグルスイッチ

デザイナーから渡された画面デザインに、こんな UI が置かれていることがありませんか?

何気ない顔をして画面上にいますが、HTML 標準にはこんなコンポーネントはありません!
……と言いたいところですが、フロントエンドエンジニアの腕の見せ所として、こいつも実装してやりましょう。

HTML

<input type="checkbox" class="toggle" />

HTML は拍子抜けするくらいシンプルにできます。
チェックボックスの input タグだけです。

CSS

.toggle {
    display: inline-block;
    appearance: none;    /* ① */
    -webkit-appearance: none;
    -moz-appearance: none;
    width: 60px;    /* ② */
    height: 30px;
    border-radius: 15px;
    background-color: #ccc;
    border: 1px solid #ccc;
    cursor: pointer;
    position: relative;
}

.toggle::after {    /* ③ */
    content: '';
    display: block;
    width: 26px;    /* ④ */
    height: 26px;
    background-color: white;
    border-radius: 13px;
    cursor: pointer;
    transition: left 0.3s;    /* ⑤ */
    position: absolute;
    top: 1px;
    left: 31px;
}

.toggle::before {    /* ⑥ */
    content: 'OFF';
    position: absolute;
    font-size: 12px;
    line-height: 1;
    top: 50%;
    transform: translateY(-50%);
    left: 4px;
    color: #fff;
}

.toggle:checked {    /* ⑦ */
    background-color: #1ea7fd;
    border: 1px solid #1ea7fd;
}

.toggle:checked::after {    /* ⑦ */
    left: 1px;
}

.toggle:checked::before {    /* ⑦ */
    content: 'ON';
    left: 32px;
}

CSS の実装ポイントとテクニックについて上から見ていきます。

① ブラウザの標準 UI を非表示にする
appearance: none でブラウザの標準 UI を非表示にします。

② input タグの形と背景を設定する
ブラウザの標準 UI を非表示にすると、チェックボックスの input タグのサイズや背景、角丸などが設定できるようになります。
これを使って、トグルスイッチの外形を作ります。

③ after 疑似要素でスライドスイッチを作る
左右にスライドする丸いスイッチ部分は after 疑似要素を使って作ります。

④ 円を描画する
width と height を同じ値にして正方形にし、border-radius: 50% で円を描画することができます。

⑤ スライドのアニメーションを付ける
スイッチが左右にスライドする動きにアニメーションを付けると操作感が良くなります。
left の位置が変化したら、0.3s の時間でアニメーションします。
たった一行でこのアニメーションを付けることができます。

⑥ before 疑似要素で ON/OFF の文字を表示する
ON/OFF の文字は before 疑似要素で表示しています。

⑦ トグルが ON の場合の表示
トグルが ON の場合は、チェックボックスが checked になっているときですので、checked のときのスタイルをそれぞれ指定します。

複雑そうに見えますが、チェックボックスのカスタマイズでやっていることと、ほとんど同じテクニックでトグルスイッチも実装できます。

IE11 のこと

IE11 は忘れようと最初に言いましたが、忘れたくても忘れられないプロジェクトもあります。

IE11 は残念なことに、今回のテクニックのキモである appearance プロパティが実装されていません。
この場合はどうすればいいかというと、appearance: none の代わりに、opacity: 0 を指定して、inputタグごと透明にして消してしまいます。
そうすると、before、after の疑似要素も見えなくなってしまうので、input タグに直接 before、after を適用するのではなく、span などの代替のタグを用意してそちらに before、after を適用して表示します。

デザインを描画するためだけの span タグが増えてしまうので、あまりスマートでないですがこの方法で IE11 もチェックボックスのデザインのカスタマイズが可能です。

まとめ

いかがでしたか?

CSS が適用できないフォーム部品でも工夫すれば、意外と簡単にデザインをカスタマイズすることができます。
デザインされたフォーム部品を使うために、Bootstrap などの UI ライブラリを導入して、UI ライブラリのデザインをカスタマイズするということをしていた経験も多いかもしれません。
既存の UI ライブラリのカスタマイズも正確にデザイン反映するのが難しかったり、UI ライブラリの CSS 実装を調べなければならなかったり、意外と面倒です。
それなら自分で CSS を実装してしまったほうが楽ということもよくあります。

Fixel ではデザインシステムを構築するプロジェクトを多く手掛けており、デザインシステムに登録する UI コンポーネントの実装についても、多くの知見と経験があります。
きれいにデザインされて使いやすい UI コンポーネントの実装やデザインシステムについての悩みがありましたら、どうぞご相談ください。

この記事を書いた人

宮崎 聡史 フルスタックエンジニア

工業大学機械工学科卒。FA通信機器のサービスエンジニアを経験後、Web業界へ。Webサイトの作成から始まり、デザインとUXにこだわったアプリケーション開発も多数行う。 ハードウェアの背景を持ちながら、デザインからフロントエンド、バックエンドまでの幅広い領域をカバーする。 Fixelでは、デザインされたUI/UXのアプリへの実装、およびUXHubの実装を担当。

Contact

どのようなお悩みでも
まずはお気軽に
ご相談ください

arrow

Careers

柔軟で先進的な思考を持った
デザイナーやエンジニア、
コンサルタントを募集しています

arrow

Copyright© Fixel Inc. All rights reserved.