layui多步骤表单
表单可用性是Web设计中一个非常重要的主题。 作为提供给用户的主要输入界面之一,表单的可用性对于良好的用户体验至关重要。
今天,我们将构建一个包含验证和动画功能的多部分表单。 我们会覆盖很多地面,所以要系好安全带!
形成高级最佳实践
表单界面设计是可用性障碍的一部分。 在开始之前,让我们先讨论一些表单最佳实践。
不要让您的用户想得太硬
形式通常不是鼓励独特互动的地方。 好的表格提供了明显的导航技术和完全的透明度。 好的表格标签明确,易于浏览。
不要太花哨
重要的是不要偏离默认的表单行为。 有一些标准是表单默认行为的基础。 违反这些标准可能会对可访问性产生负面影响,因此请考虑尽可能保留这些默认样式。
请记住,用户不必停留
您表单的用户不必停留。 他们选择留下。 填写表格比较麻烦,因此请放轻松。 (如果可能,请使其有趣!)请勿混淆或要求用户; 而是围绕表单提出的问题建立对话。 要有礼貌。
何时使用多节技术
有时,多节形式肯定是个好技术。 对于“我应该分解表格之前需要多少输入”,没有一个唯一的答案。 取而代之的是,始终考虑将表格分为几个部分是有助于还是阻碍可用性。 其次,考虑它是否有助于或阻碍交互设计的其他方面。
如果您的表单具有截然不同的部分,则可能值得将其分为多个部分。 结帐流程是这种情况的常见示例。 (个人信息,运输信息,付款信息和确认信息非常不同,通常都是实质性的部分。)
计划互动
我们将创建一个包含任意字段的注册表单。 我们需要知道当前正在哪个部分,因此我们需要在表单顶部添加一个指示器。 我们要水平转换表单部分,从右向左滑动。 为此,我们将不同的部分设置为在“窗口”元素中具有绝对位置。 我们还希望有两个按钮; 一个是普通的提交按钮。 另一个是“下一部分”按钮。
标记
这是我们的表格:
<form id="signup" action="somewhere" method="POST">
<ul id="section-tabs">
<li class="current active"><span>1.</span> Creds</li>
<li><span>2.</span> Deets</li>
<li><span>3.</span> Settings</li>
<li><span>4.</span> Last Words</li>
</ul>
<div id="fieldsets">
<fieldset class="current">
<label for="email">Email:</label>
<input name="email" type="email" class="required email" />
<label name="password" for="password">Password:</label>
<input type="password" minlength="10" class="required">
</fieldset>
<fieldset class="next">
<label for="username">Username:</label>
<input name="username" type="text">
<label for="bio">Short Bio:</label>
<textarea name="bio" class="required"></textarea>
</fieldset>
<fieldset class="next">
<label for="interests">Basic Interests:</label>
<textarea name="bio"></textarea>
<p>Receive newsletter?<br>
<input type="radio" name="newsletter" value="yes"><label for="newsletter">yes</label>
<input type="radio" name="newsletter" value="no"><label for="newsletter">no</label>
</p>
</fieldset>
<fieldset class="next">
<label for="referrer">Referred by:</label>
<input type="text" name="referrer">
<label for="phone">Daytime Phone:</label>
<input type="tel" name="phone">
</fieldset>
<a class="btn" id="next">Next Section ▷</a>
<input type="submit" class="btn">
</div>
</form>
标记非常简单,但让我们谈谈其中的一些内容。
- 字段集:字段集是用于对输入进行分组的语义元素; 这非常适合我们的情况。
- 类名: jQuery Validate使用类来定义内置类型。 我们将在一分钟内看到其工作原理。
- 字段是任意的。 我们将单选输入包装在一个段落标签中,以简化格式设置。
- 提交和下一个按钮:带有一类按钮的锚标记将用于转到下一部分。 提交输入将在适当时通过JavaScript显示。
样式(无味)
这很长,准备好..
@import url(http://fonts.googleapis.com/css?family=Merriweather+Sans:300);
@import url(http://fonts.googleapis.com/css?family=Merriweather+Sans:700);
body {
background: url(http://farm5.staticflickr.com/4139/4825532997\_7a7cd3d640\_b.jpg);
background-size: cover;
height: 100%;
font-family: 'Merriweather Sans', sans-serif;
color: #666;
}
#signup {
width: 600px;
height: auto;
padding: 20px;
background: #fff;
margin: 80px auto;
position: relative;
min-height: 300px;
}
#fieldsets {
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
padding: 20px;
box-sizing: border-box;
overflow: hidden;
}
input[type=text],
input[type=email],
input[type=password],
input[type=tel],
textarea {
display: block;
-webkit-appearance: none;
-moz-appearance: none;
width: 100%;
box-sizing: border-box;
border: 1px solid #ddd;
padding: 8px;
margin-bottom: 8px;
position: relative;
&:focus {
outline: none;
border: 1px solid darken(#2cbab2,10%);
}
}
input[type=radio]{
margin: 6px;
display: inline-block;
}
fieldset {
border: none;
position: absolute;
left: -640px;
width: 600px;
padding: 10px 0;
transition: all 0.3s linear;
-webkit-transition: all 0.3s linear;
-moz-transition: all 0.3s linear;
-ms-transition: all 0.3s linear;
opacity: 0;
&.current {
left: 20px;
opacity: 1;
}
&.next {
left: 640px;
}
}
input[type=submit] {
display: none;
border: none;
}
#section-tabs {
font-size: 0.8em;
height: 50px;
position: relative;
margin-top: -50px;
margin-bottom: 50px;
padding: 0;
font-weight: bold;
list-style: none;
text-transform: uppercase;
li {
color: #a7a7a7;
span {
color: #bababa;
}
cursor: not-allowed;
&.active {
color: #444;
cursor: pointer;
}
border-left: 1px solid #aaa;
text-decoration: none;
padding: 0 6px;
float: left;
width: 25%;
box-sizing: border-box;
text-align: center;
font-weight: bold;
line-height: 30px;
background: #ddd;
position: relative;
&:after {
content: "";
display: block;
margin-left: 0;
position: absolute;
left: 0;
top: 0;
}
&.current {
opacity: 1;
background: #fff;
z-index: 999;
border-left: none;
&:after {
border: 15px solid transparent;
border-left: 15px solid #2cbab2;
}
}
}
}
.error {
color: #bf2424;
display: block;
}
input.error, textarea.error {
border-color: #bf2424;
&:focus {
border-color: #bf2424;
}
}
label.error {
margin-bottom: 20px;
}
input.valid {
color: green;
}
label.valid {
position: absolute;
right: 20px;
}
input+.valid, textarea+.valid {
display: none;
}
.valid+.valid {
display: inline;
position: absolute;
right: 10px;
margin-top: -36px;
color: green;
}
.btn {
border: none;
padding: 8px;
background: #2cbab2;
cursor: pointer;
transition: all 0.3s;
-webkit-transition: all 0.3s;
-moz-transition: all 0.3s;
&:hover {
background: darken(#2cbab2, 6%);
}
color: #fff;
position: absolute;
bottom: 20px;
right: 20px;
font-family: 'Merriweather Sans', sans-serif;
}
让我们来看一下样式的重要部分。
总览
表单本身设置为特定宽度,以margin: 0 auto为中心,然后设置为position:relative 。 这种定位允许子元素的absolute positioning ,以相对于包含形式绝对地放置它们。 包含表单包含三种主要类型的元素:区域选项卡和字段集“窗口”以及按钮。
区域选项卡相对于包含元素放置,并以负的上边距“拉起”。 我们用相等的边距底部补偿对布局其余部分的影响。
字段集“窗口”设置为相对于父表单元素绝对定位。 宽度和高度都设置为100%。 此窗口的目的是保存元素,然后在元素落入带有overflow: hidden的边缘时隐藏它们overflow: hidden 。 我们无法在表单上执行此操作,因为我们要保留指标标签。
最后,将按钮元素(锚标记和提交输入)的样式设置为绝对位于表单的右下角,从底部和右侧偏移20个像素。 我们还向按钮元素添加了一个简单CSS过渡,以使悬停时的背景变暗。
更多注意事项
- 字段集设置为
position: absolute。 我们有两个用于两个状态的类,一个是默认状态。 默认状态将字段集拉到窗体的左侧。.current类将.current放在表单的可见区域中,最后.next类将.current推到表单的右侧。 - 当前类的不透明度为1; 默认状态(自然是.next)的不透明度为0。
- 我们使用简单CSS过渡为这些类之间的字段集设置动画。
-
.error和.valid类将有助于验证样式。 我们正在使用Merriweather Sans ,一种可通过Google Webfonts免费使用的字体。
JavaScript
这是使所有交互起作用的部分。 在查看代码之前,请注意以下几点:该代码取决于jQuery和jQuery Validate 。 jQuery validate是一个已经存在很长时间的插件,因此已经被成千上万的人测试和证明。
我们的基本策略:为表单设置一些验证规则,包括用于检查电话号码的自定义功能。 我们希望用户能够浏览先前完成的部分。 我们希望他们能够使用Enter键转到下一部分; 但是,我们不希望用户在完成之前的部分并有效之前先进入后续的部分。
如果用户尝试单击其已完成部分之外的部分的选项卡,则我们希望避免导航至该部分。
我们希望依靠类(而不是jQuery动画)在状态之间进行转换。
因此,牢记这些,这是最终JavaScript。 (注意:如果您不使用jQuery,这可能会有些令人生畏;但是,无论如何都要坚持使用它,您将通过深入研究代码来学习。)完整脚本之后,我们将在其中一段时间,解释发生了什么。
$("#signup").validate({
success : function(label){
label.addClass("valid").text("✓");
},
error : function(e){
// do nothing, but register this function
},
onsubmit:false,
rules: {
phone: {
required: true,
phoneUS: true
}
}
});
$("body").on("keyup", "form", function(e){
if (e.which == 13){
if ($("#next").is(":visible") && $("fieldset.current").find("input, textarea").valid() ){
e.preventDefault();
nextSection();
return false;
}
}
});
$("#next").on("click", function(e){
console.log(e.target);
nextSection();
});
$("form").on("submit", function(e){
if ($("#next").is(":visible") || $("fieldset.current").index() < 3){
e.preventDefault();
}
});
function goToSection(i){
$("fieldset:gt("+i+")").removeClass("current").addClass("next");
$("fieldset:lt("+i+")").removeClass("current");
$("li").eq(i).addClass("current").siblings().removeClass("current");
setTimeout(function(){
$("fieldset").eq(i).removeClass("next").addClass("current active");
if ($("fieldset.current").index() == 3){
$("#next").hide();
$("input[type=submit]").show();
} else {
$("#next").show();
$("input[type=submit]").hide();
}
}, 80);
}
function nextSection(){
var i = $("fieldset.current").index();
if (i < 3){
$("li").eq(i+1).addClass("active");
goToSection(i+1);
}
}
$("li").on("click", function(e){
var i = $(this).index();
if ($(this).hasClass("active")){
goToSection(i);
} else {
alert("Please complete previous sections first.");
}
});
jQuery.validator.addMethod("phoneUS", function(phone_number, element) {
phone_number = phone_number.replace(/\s+/g, "");
return this.optional(element) || phone_number.length > 9 &&
phone_number.match(/^(1-?)?(\([2-9]\d{2}\)|[2-9]\d{2})-?[2-9]\d{2}-?\d{4}$/);
}, "Please specify a valid phone number");
所以,让我们一步一步走。
$("#signup").validate({
success : function(label){
label.addClass("valid").text("✓");
},
error : function(e){
// do nothing, but register this function
},
onsubmit:false,
rules: {
phone: {
required: true,
phoneUS: true
}
}
});
此功能是jQuery Validate的设置功能。 首先,我们告诉插件采用注册表单并对其进行验证。 如果验证成功,则向验证插件在输入元素后插入的标签添加有效类,然后将文本替换为utf-8复选标记✓ 。
尽管我们实际上并未在此函数中执行任何操作,但我们还在注册错误回调。 不注册该函数似乎与成功函数在错误时具有相同的回调。 我们将onsubmit钩子设置为false; 这是因为按Enter键会自动提交表单,默认情况下会触发验证以防止表单无效提交。 阻止表单提交的默认行为不会阻止表单验证。 结果是,尽管从未提交表单,但“下一步”屏幕上的字段已经显示了验证错误。
$("body").on("keyup", "form", function(e){
if (e.which == 13){
if ($("#next").is(":visible") && $("fieldset.current").find("input, textarea").valid() ){
e.preventDefault();
nextSection();
}
}
});
此函数侦听在窗体上触发的keyup事件。 如果输入了被击中的键(键代码13),我们将执行以下检查。 如果下一个按钮仍然可见并且当前部分有效,请防止在表单(即表单提交)上按下Enter键的默认行为。
然后,我们调用nextSection() ,它将表格前进到下一部分。 如果当前部分包含任何无效输入,那么将识别这些输入,并且表单不会前进。 如果下一个按钮不可见,则意味着我们位于最后一节(我们将在后续功能中看到),并且希望允许发生默认行为(表单提交)。
$("#next").on("click", function(e){
nextSection();
});
$("form").on("submit", function(e){
if ($("#next").is(":visible") || $("fieldset.current").index() < 3){
e.preventDefault();
}
});
这些功能很简单。 如果您按下ID为“ next”的按钮,我们将进入下一部分。 记住nextSection()函数包含所有必要的表单验证检查。
关于表单上的Submit事件,如果下一个按钮可见,或者当前字段集不是最后一个,则我们希望避免表单提交。
function goToSection(i){
$("fieldset:gt("+i+")").removeClass("current").addClass("next");
$("fieldset:lt("+i+")").removeClass("current");
$("li").eq(i).addClass("current").siblings().removeClass("current");
setTimeout(function(){
$("fieldset").eq(i).removeClass("next").addClass("current active");
if ($("fieldset.current").index() == 3){
$("#next").hide();
$("input[type=submit]").show();
} else {
$("#next").show();
$("input[type=submit]").hide();
}
}, 80);
}
goToSection()函数是此表单导航背后的主力军。 它只有一个参数-目标导航的索引。 该函数采用索引大于传递的index参数的所有字段集,并删除current类,并添加next类。 这会将元素推到表单的右侧。
接下来,我们从索引小于传递的索引的所有字段集中删除当前类。 接下来,我们选择与传入索引相等的列表项,并添加一个当前类。
随后,我们从所有其他的兄弟姐妹删除当前的类li秒。 我们设置一个超时,然后删除下一个类,然后将当前类和活动类添加到具有等于传入索引参数的索引的字段集中。
活动类使我们知道用户可以再次导航到该特定部分。 如果传入的索引参数为3(最后一个字段集),我们将隐藏下一个按钮并显示“提交”按钮。 否则,我们要确保下一个按钮可见,而提交按钮被隐藏。 这使我们可以隐藏“提交”按钮,除非最后一个字段集可见。
function nextSection(){
var i = $("fieldset.current").index();
if (i < 3){
$("li").eq(i+1).addClass("active");
goToSection(i+1);
}
}
$("li").on("click", function(e){
var i = $(this).index();
if ($(this).hasClass("active")){
goToSection(i);
} else {
alert("Please complete previous sections first.");
}
});
该nextSection()函数基本上是围绕着一个包装goToSection()函数。 调用nextSection ,将进行简单检查以确保我们不在最后一节中。 只要不是,我们就进入索引等于当前部分索引加1的部分。
我们正在侦听列表项上的click事件。 此函数检查以确保列表项具有活动类,一旦用户最初通过完成所有前面的部分到达表单的该部分,它将收到该活动类。 如果列表项确实具有该类,我们将调用goToSection并传入该列表项的索引。 如果用户单击与他们尚无法访问的部分相对应的列表项,浏览器将警告他们,让他们知道他们必须先完成之前的部分。
jQuery.validator.addMethod("phoneUS", function(phone_number, element) {
phone_number = phone_number.replace(/\s+/g, "");
return this.optional(element) || phone_number.length > 9 &&
phone_number.match(/^(1-?)?(\([2-9]\d{2}\)|[2-9]\d{2})-?[2-9]\d{2}-?\d{4}$/);
}, "Please specify a valid phone number");
最后,我们添加了一个由jQuery Validate插件指定的方法,该方法可以手动检查输入。 我们不会花很多时间,因为可以在Validate文档中找到此确切功能。
本质上,我们检查以确保用户输入到电话字段中的文本与正则表达式(数字和符号的长字符串)匹配。 如果是,则输入有效。 如果不是,则在输入之后添加消息“请指定一个有效的电话号码”。 您可以使用相同的功能来检查任何类型的输入(不必使用正则表达式)。
注意:请勿将其用作密码验证方法。 这是非常不安全的,任何人都可以查看源以查看密码。
结论
我们使用了语义HTML和简单的LESS,并结合了一些最小JavaScript,以构建可靠的表单交互。 用于构建此表单的方法,尤其是使用类名来标识状态以及定义功能和动画的方法,几乎可以在任何交互式项目中使用。 相同的功能可用于演示逐步介绍,游戏以及依赖于基于状态的简单交互的任何其他功能。
您还要对此表格做些什么? 您发现了哪些类型的互动可以帮助用户更自然地完成繁琐的流程(例如填写冗长的多步骤表单)? 在评论中分享他们!
翻译自: https://webdesign.tutsplus.com/articles/build-a-multi-step-form-interface--webdesign-11715
layui多步骤表单
本文介绍了如何使用layui创建包含验证和动画效果的多步骤表单,强调了表单设计的最佳实践,如保持简单、避免用户思考,并讨论了何时适合使用多节技术。通过计划互动、设置标记和样式,以及利用JavaScript实现表单验证和导航,最终构建了一个用户友好的多步骤注册表单。
2762

被折叠的 条评论
为什么被折叠?



