入力フォームの重要性
商品購入やイベントへの参加申し込みなど、Webページ上でユーザーが最終アクション(CV:コンバージョン)を完了させる接点となるのが「入力フォーム」です。
入力フォームをただ設置すれば問い合わせが増えるわけではありません。
せっかくユーザーが入力画面まで到達しても、フォームの入力を完了させずにページを離脱してしまうことは多々あります。
ユーザーが入力を進めやすいフォームでなければ、フォーム画面を見た途端にページを離れてしまったり、入力作業にストレスを感じて途中離脱してしまったりCVを逃すことになり、ユーザー獲得の機会が失われます。
WebサイトやECサイトのコンテンツをどんなに充実させても、最終的にユーザーが入力を完了させなければ結果に結びつきません。そのため、ユーザーライクなフォームのデザインは非常に重要です。
フォームデザインのポイント
- フォーム要素は縦一列配置にする
- ラベルは入力データの上に配置する
- ラベルと入力データはグループ化する
- 選択肢が少ない場合はセレクトボックスを避ける
- ラジオボタンやチェックボックスは縦に配列する
- 入力フォームの幅を適切に設定する
- エラー表示はインラインで表示する
- 「*」ではなく「必須」と表示する
作成したデモページ
https://isystk.github.io/google-form-sample/
入力項目毎にラベルとフォーム要素をsctionでグループ化しています。また入力エラーがある場合は、フォーム要素の下に表示して何処の入力値に問題があるかを判りやすくしています。
また入力補助として「フォーカスのある入力フォームの下線を太くするアニメーション」「次の入力フォームにフォーカスを移動する機能」「テキストボックスの入力文字数を表示する機能」を用意しました。
入力補助として追加した機能の紹介
フォーカスのある入力フォームの下線を太くするアニメーション
css
.form-section .test-wrap.active .form-bottom{
border-bottom-color: #487cff;
border-bottom-width: 2px;
animation: centerToSide .3s ease 0s 1 forwards;
}
@keyframes centerToSide {
0% {
transform: scaleY(1) scaleX(.1);
}
100% {
transform: scaleY(1) scaleX(1);
}
}
javascript
$(function() {
var wrap = $('.form-section');
var form = wrap.find('input,select,textarea');
form.each(function() {
var self = $(this);
// フォーカスイン
self.focus(function() {
self.closest('div').addClass('active');
});
// フォーカスアウト
self.blur(function(){
wrap.find('div').removeClass('active');
});
});
});
次の入力フォームにフォーカスを移動する機能
入力中の項目からフォーカスが外れたタイミングで自動的に次の入力項目へフォーカスを移動させることで操作性を良くしユーザービリティを向上させています。
$(function() {
// 入力完了時に次のフォームへフォーカスを当てる
$.autoFocus();
});
(function($){
// デフォルト値
var options = {
wrapselector : document,
textselector : 'input,select,textarea'
};
$.autoFocus = function(opts) {
// 引数に値が存在する場合、デフォルト値を上書きする
$.extend(options, opts);
var inputObj = $(options.wrapselector).find(options.textselector);
$(options.wrapselector).delegate(options.textselector, 'change', function(event) {
var self = $(this);
// ラジオボタンとチェックボックスは対象外
if (self.attr('type') === 'radio' || self.attr('type') === 'checkbox') {
return;
}
inputObj = $(options.wrapselector).find(options.textselector);
// 配列をループ処理
$.each(inputObj, function(i, val) {
if (i === inputObj.length-1) {
return;
}
var target = $(inputObj[i]);
var next = findNextObj(i);
if (self.attr('name') === target.attr('name')) {
next.focus();
}
});
// 次の入力フォームを見つける。
function findNextObj(idx) {
if (inputObj.length <= idx) {
return;
}
var target = $(inputObj[idx]);
var targetName = target.attr('name');
var next = $(inputObj[idx+1]);
var nextName = next.attr('name');
// 同じnameのフォームは飛ばす。
if (targetName === nextName) {
return findNextObj(++idx);
} else {
return next;
}
}
});
// 初期表示時にエラーが有る場合は該当項目にフォーカスを当てる
inputObj.each(function() {
var target = $(this);
if (target.hasClass('error')) {
target.focus();
return false;
}
});
}
})(jQuery);
テキストエリアの入力文字数を表示する機能
テキストエリアはmaxlengthによる入力上限の制御が効かないので、入力可能な残りの文字数を右下に表示させるようにしました。
$(function() {
// テキストエリア文字数カウント
$('.js-textCounter').each(function() {
var self = $(this),
maxCount = self.text(),
textarea = self.closest('.textarea-wrap').find('textarea');
$.textCounter([
{textSelector: textarea, labelSelector: self, count: maxCount}
]);
});
});
(function($){
$.textCounter = function(selectors) {
var s = selectors;
for (var i = 0, len = s.length; i < len; i++) {
var obj = s[i],
elem = $(obj.textSelector),
label = $(obj.labelSelector);
// カウント数
label.html(obj.count - getCount(elem.val()));
// デフォルト色
label.data('defaultcolor', label.css('color'));
elem.bind('keyup', function(val) {
var count = obj.count - getCount(elem.val());
label.html(count);
if (count <= 0) {
label.css('color', '#FF0000');
} else {
label.css('color', label.data('defaultcolor'));
}
});
}
};
function getCount(val) {
if (val) {
var str = val.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, " ");
return str.replace(/\n/g, "\r\n").length;
}
return 0;
}
})(jQuery);