EC-CUBE4系のフォーム周りを「Material Components for the web」で綺麗にしてみる。
date_range
- ENGINEER
先般、弊社サンデイシステムズでは、EC-CUBE4系のデザインテンプレートをリリースしました。
EC-CUBEレスポンシブWebデザインテンプレート No.SS4001(4.0.3)
こちらのテンプレートは、Googleが提供するUIコンポーネントのライブラリ「Material Components for the web(以下、MDC-Web)」を使って、マテリアルデザインにおけるいくつかの印象的なデザインパターンを実現しています。 例えば「フローティングラベル」と呼ばれる、フォーム入力時のデザインパターン。 Gmailなんかのログインフォーム入力時に、ラベルが上にスッと移動するアレです。
今回作成したデザインテンプレートでは、MDC-WebでEC-CUBEのフォーム周りをガッツリと変えてみました。 その際の知見も踏まえ、MDC-Webでのフォーム周りのデザインカスタマイズについて、少しご紹介させていただきます。
もっとも簡単なMDC-Webの使用方法
MDC-Webを試す方法でもっとも簡単なのは、CDNからコンパイル済みのCSSファイルと、バンドル済みのjavascriptファイルを読み込む方法です。 default_frame.twig、もしくは適用したいページのtwigファイルに読み込めばOK。 今回はサンプルとして新規会員登録ページに該当する「Entry/index.twig」に追記しておきます。
{% block stylesheet %}
<link href="//unpkg.com/material-components-web@latest/dist/material-components-web.min.css" rel="stylesheet">
{% endblock stylesheet %}
{% block javascript %}
<script src="//yubinbango.github.io/yubinbango/yubinbango.js" charset="UTF-8"></script>
<script src="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.js"></script>
{% endblock javascript %}
次にMDC-Web用のマークアップを行います。 新規会員登録ページの「お名前」部分を修正したいと思うので、デフォルトのtwigファイル内の下記の箇所を…
<dl>
<dt>
{{ form_label(form.name, 'お名前', { 'label_attr': { 'class': 'ec-label' }}) }}
</dt>
<dd>
<div class="ec-halfInput{{ has_errors(form.name.name01, form.name.name02) ? ' error'}}">
{{ form_widget(form.name.name01, { 'attr': { 'placeholder': '姓' }}) }}
{{ form_widget(form.name.name02, { 'attr': { 'placeholder': '名' }}) }}
{{ form_errors(form.name.name01) }}
{{ form_errors(form.name.name02) }}
</div>
</dd>
</dl>
以下のように変更。
<dl>
<dt>
{{ form_label(form.name, 'お名前', { 'label_attr': { 'class': 'ec-label' }}) }}
</dt>
<dd class="horizontal">
<div>
<div class="mdc-text-field mdc-text-field--outlined{{ has_errors(form.name.name01) ? ' mdc-text-field--invalid' }}" data-mdc-auto-init="MDCTextField">
{{ form_widget(form.name.name01, {'attr': { 'class': 'mdc-text-field__input', 'placeholder': null }}) }}
<div class="mdc-notched-outline">
<div class="mdc-notched-outline__leading"></div>
<div class="mdc-notched-outline__notch">
<label class="mdc-floating-label" for="entry_name_name01">姓</label>
</div>
<div class="mdc-notched-outline__trailing"></div>
</div>
</div>
{{ form_errors(form.name.name01, {'label_attr': {'class': 'mdc-text-field-helper-text mdc-text-field-helper-text--validation-msg'}}) }}
</div>
<div>
<div class="mdc-text-field mdc-text-field--outlined{{ has_errors(form.name.name02) ? ' mdc-text-field--invalid' }}" data-mdc-auto-init="MDCTextField">
{{ form_widget(form.name.name02, {'attr': { 'class': 'mdc-text-field__input', 'placeholder': null }}) }}
<div class="mdc-notched-outline">
<div class="mdc-notched-outline__leading"></div>
<div class="mdc-notched-outline__notch">
<label class="mdc-floating-label" for="entry_name_name02">名</label>
</div>
<div class="mdc-notched-outline__trailing"></div>
</div>
</div>
{{ form_errors(form.name.name02, {'label_attr': {'class': 'mdc-text-field-helper-text mdc-text-field-helper-text--validation-msg'}}) }}
</div>
</dd>
</dl>
autoInit() を実行。
{% block javascript %}
<script src="//yubinbango.github.io/yubinbango/yubinbango.js" charset="UTF-8"></script>
<script src="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
mdc.autoInit();
}, false);
</script>
{% endblock javascript %}
最後にデフォルトのCSSと干渉し、若干見栄えが悪くなってる箇所があるので、そちらを整えます。
{% block stylesheet %}
<link href="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.css" rel="stylesheet">
<style>
.horizontal {
display: flex;
margin: 0 -10px;
width: auto;
}
.horizontal>div {
margin: 0 10px 11px;
}
.mdc-text-field__input {
font-size: 16px;
}
.mdc-floating-label {
font-size: 16px;
line-height: 1.5;
vertical-align: top;
margin-bottom: 0;
}
.mdc-text-field--outlined .mdc-notched-outline--upgraded .mdc-floating-label--float-above {
font-size: 16px;
}
</style>
{% endblock stylesheet %}
出来上がり。
ついでにエラーメッセージもMDC-Webのスタイルを当て込んでおきます。 form_div_layout.twigの「form_errors」部分。
{%- block form_errors -%}
{%- if errors|length > 0 -%}
{%- for error in errors -%}
<div class="mdc-text-field-helper-line">
<p{% if label_attr %}{% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}{% endif %} aria-hidden="true">{{ error.message|trans({}, translation_domain) }}</p>
</div>
{%- endfor -%}
{%- endif -%}
{%- endblock form_errors -%}
こんな感じにしておくと、エラーメッセージの表示も整います。 入力が完了すると、エラーの表示が消えてくれるのがちょっと良きです。
以上で完了です。
複数の必要なコンポーネントのみ利用する場合。
MDC-Webは様々なコンポーネントが網羅されたオールインワンパッケージとして利用できますし、個別のコンポーネントとしての利用も可能です。 一つのECサイトの中で全てのMDCコンポーネントを利用する事はほぼ無いので、利用するコンポーネントのみに絞って、CSSとJSファイルを軽量化するのが適切な使い方かなと思います。 ちなみに弊社でリリースしたデザインテンプレートでは、以下のコンポーネントのみを使用。
- auto-init
- ripple
- textfield
- select
- top-app-bar
- dialog
- menu
Webpack環境下で、javascriptファイル群をプロジェクトに適した形でバンドルファイル化し、先程の簡単な例と同様に読み込んで使用します。 以下のようにMDCTextFieldモジュールをインポートして、インスタンス化すればOKです。
import { MDCTextField } from '@material/textfield/index';
const textFieldElements = [].map.call(document.querySelectorAll('.mdc-text-field'), function (el) {
return new MDCTextField(el);
});
こちらの方法の場合、マークアップ時の「data-mdc-auto-init」の記述やautoInit関数の実行等は不要になります。 auto-initコンポーネントは、Ajax等で要素を追加した際などに、また出番が回ってきます。
まとめ
ブラウザ毎に差異の無い綺麗なフォームデザインがあると、様々な案件で効率的にサイト構築ができて便利だなと思う今日この頃です。 ご興味がありましたら、実際の挙動をDEMOサイトもご確認いただければ幸いです。