La usabilidad de formularios es un tema increíblemente importante en el diseño web. Como una de las principales interfaces de entrada proporcionadas a los usuarios, la facilidad de uso de un formulario es esencial para una buena experiencia de usuario..
Hoy, vamos a construir un formulario de varias partes, completo con validación y animación. Vamos a cubrir un montón de terreno, así que abróchate el cinturón!
El diseño de la interfaz de formulario es una mina de obstáculos de usabilidad. Antes de comenzar, hablemos de algunas de las mejores prácticas..
Las formas generalmente no son el lugar para fomentar una interacción única. Las buenas formas proporcionan técnicas de navegación obvias y transparencia total. Las buenas formas están bien etiquetadas y son fáciles de navegar.
Es importante no desviarse demasiado de los comportamientos de forma predeterminados. Existen estándares que son la base de los comportamientos predeterminados de los formularios. La desviación de estos estándares puede tener efectos negativos en la accesibilidad, así que considere la posibilidad de mantener esos estilos predeterminados cuando sea posible.
El usuario de su formulario no tiene que quedarse. Eligen quedarse. Completar un formulario es una tarea, así que hazlo fácil. (Si es posible, ¡diviértase!) No confunda ni exija al usuario; en su lugar, establezca un diálogo alrededor de las preguntas que el formulario está haciendo. Ser cortés.
Las formas multiseccionales son ciertamente una buena técnica, a veces. No hay una sola respuesta para "cuántas entradas se necesitan antes de que deba dividir el formulario". En su lugar, siempre considere si dividir el formulario en secciones separadas ayudará o dificultará la usabilidad. En segundo lugar, considere si ayuda o dificulta otros aspectos del diseño de interacción.
Si tiene formularios con secciones muy distintas, puede valer la pena separarlos en varias partes. Los procesos de pago son un ejemplo común de esto. (La información personal, la información de envío, la información de pago y la confirmación son secciones muy distintas y generalmente importantes).
Vamos a crear un formulario de registro con campos arbitrarios. Necesitamos saber en qué sección estamos actualmente, por lo que necesitaremos un indicador en la parte superior del formulario. Queremos hacer una transición horizontal de nuestras secciones de formulario, deslizando de derecha a izquierda. Para lograr esto, configuraremos las diferentes secciones para que tengan una posición absoluta dentro de un elemento de "ventana" de sección. También queremos tener dos botones; Uno es el botón de envío normal. El otro es un botón de "siguiente sección"..
Aquí está nuestro formulario:
El marcado es bastante sencillo, pero hablemos de algunas piezas..
Esto es largo, prepárate ...
@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); tamaño de fondo: cubierta; altura: 100%; Familia tipográfica: 'Merriweather Sans', sans-serif; color: # 666; #signup width: 600px; altura: auto; relleno: 20px; fondo: #fff; margen: 80px auto; posición: relativa; min-height: 300px; #fieldsets position: absolute; arriba: 0px; izquierda: 0px; ancho: 100%; altura: 100%; relleno: 20px; tamaño de caja: caja de borde; desbordamiento: oculto; entrada [tipo = texto], entrada [tipo = correo electrónico], entrada [tipo = contraseña], entrada [tipo = tel], área de texto pantalla: bloque; -webkit-apariencia: ninguno; -mez-apariencia: ninguna; ancho: 100%; tamaño de caja: caja de borde; borde: 1px sólido #ddd; relleno: 8px; margen inferior: 8px; posición: relativa; &: foco esquema: ninguno; borde: 1px sólido se oscurece (# 2cbab2,10%); entrada [tipo = radio] margen: 6px; pantalla: bloque en línea; fieldset border: none; posición: absoluta; izquierda: -640px; ancho: 600px; relleno: 10px 0; transición: todos los 0.3s lineales; -webkit-transición: todos los 0.3s lineales; -moz-transición: todos los 0.3s lineales; -ms-transición: todos los 0.3s lineales; opacidad: 0; & .current izquierda: 20px; opacidad: 1; & .next left: 640px; entrada [type = submit] display: none; frontera: ninguna; # section-tabs font-size: 0.8em; altura: 50px; posición: relativa; margen superior: -50px; margen inferior: 50px; relleno: 0; font-weight: negrita; estilo de lista: ninguno; transformación de texto: mayúsculas; li color: # a7a7a7; span color: #bababa; cursor: no permitido; & .active color: # 444; cursor: puntero; borde izquierdo: 1px sólido #aaa; texto-decoración: ninguno; relleno: 0 6px; flotador izquierdo; ancho: 25%; tamaño de caja: caja de borde; text-align: center; font-weight: negrita; línea de altura: 30px; fondo: #ddd; posición: relativa; &: después de contenido: ""; bloqueo de pantalla; margen izquierdo: 0; posición: absoluta; izquierda: 0; arriba: 0; & .current opacidad: 1; fondo: #fff; índice z: 999; borde izquierdo: ninguno; &: después de border: 15px solid transparent; borde izquierdo: 15px sólido # 2cbab2; .error color: # bf2424; bloqueo de pantalla; input.error, textarea.error border-color: # bf2424; &: focus border-color: # bf2424; label.error margin-bottom: 20px; input.valid color: verde; label.valid posición: absoluta; derecha: 20px; input + .valid, textarea + .valid display: none; .valid + .valid display: inline; posición: absoluta; derecha: 10px; margen superior: -36px; color verde; .btn borde: ninguno; relleno: 8px; fondo: # 2cbab2; cursor: puntero; transición: todos los 0.3s; -webkit-transición: todos los 0.3s; -moz-transición: todos los 0,3s; &: hover background: darken (# 2cbab2, 6%); color: #fff; posición: absoluta; abajo: 20px; derecha: 20px; Familia tipográfica: 'Merriweather Sans', sans-serif;
Caminemos por la parte importante de los estilos..
El formulario en sí se establece en un ancho específico, centrado con margen: 0 auto
, luego se establece en posición: relativo
. Este posicionamiento permite posicionamiento absoluto
de elementos hijos para colocarlos absolutamente, en relación con la forma contenida. El formulario que contiene contiene tres tipos principales de elementos: las pestañas de sección y la "ventana" del conjunto de campos, así como los botones.
Las pestañas de la sección se colocan en relación con el elemento que las contiene y se "suben" con un margen superior negativo. Compensamos el efecto sobre el resto del diseño con un margen inferior igual..
La "ventana" del conjunto de campos está configurada para ser posicionada absoluta, relativa al elemento de formulario principal. El ancho y la altura están ambos configurados al 100%. El propósito de esta ventana es mantener elementos, luego ocultarlos cuando caen fuera de los bordes con desbordamiento: oculto
. No pudimos hacer esto en el formulario, porque queremos conservar las pestañas del indicador.
Finalmente, los elementos del botón (una etiqueta de anclaje y una entrada de envío) están diseñados para ser ubicados de manera absoluta en la esquina inferior derecha del formulario, compensados por 20 píxeles desde la parte inferior y derecha. También hemos agregado una transición CSS simple a los elementos del botón para oscurecer el fondo al pasar el cursor..
posición: absoluta
. Tenemos dos clases para dos estados y un estado predeterminado. El estado predeterminado saca el conjunto de campos a la izquierda del formulario; la .corriente
clase coloca el fieldset en el área visible del formulario, y finalmente el .siguiente
la clase empuja el fieldset a la derecha del formulario..error
y .válido
Las clases te ayudarán con el estilo de validación. Estamos utilizando Merriweather Sans, una fuente disponible de forma gratuita a través de Google Webfonts.Aquí está la parte que hace que toda la interacción funcione. Algunas notas antes de ver el código: este código depende de jQuery y jQuery Validate. jQuery validate es un complemento que ha existido durante mucho tiempo y, por lo tanto, ha sido probado y probado por miles de personas.
Nuestra estrategia básica: configurar algunas reglas de validación para el formulario, incluida una función personalizada para verificar un número de teléfono. Queremos que los usuarios puedan navegar hacia atrás a través de secciones previamente terminadas. Queremos que puedan usar el botón de entrada para pasar a la siguiente sección; sin embargo, no queremos permitir que los usuarios avancen a las secciones posteriores hasta que las secciones anteriores se hayan completado y sean válidas.
Si el usuario intenta hacer clic en una pestaña para una sección más allá de las que ha completado, queremos evitar navegar a esa sección.
Queremos confiar en las clases (en lugar de animaciones jQuery) para la transición entre estados.
Entonces, con estas cosas en mente, aquí está el JavaScript final. (Nota: si no estás al tanto de tu jQuery, esto puede ser un poco desalentador; sin embargo, quédate con él de todos modos, y aprenderás metiéndote en el código). un momento y explicar lo que está pasando.
$ ("# registro"). validate (success: function (label) label.addClass ("valid"). text ("✓");, error: function (e) // no hacer nada, pero registre esta función, 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"). en ("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 $ /); , "Especifique un número de teléfono válido");
Entonces, vamos pieza por pieza..
$ ("# registro"). validate (success: function (label) label.addClass ("valid"). text ("✓");, error: function (e) // no hacer nada, pero registre esta función, onsubmit: false, rules: phone: required: true, phoneUS: true);
Esta función es la función de configuración de jQuery Validate. Primero, le estamos diciendo al complemento que tome el formulario de registro y le aplique la validación. Si la validación es exitosa, agregamos una clase de válida a la etiqueta que el complemento de validación inserta después del elemento de entrada, y reemplazamos el texto con la marca de verificación utf-8 ✓
.
También estamos registrando la devolución de llamada de error, aunque en realidad no estamos haciendo nada en esta función. No registrar la función parece tener la misma devolución de llamada que la función de éxito en caso de error. Estamos configurando el enviar
gancho a falso esto se debe a que al presionar enter se envía automáticamente el formulario, que de manera predeterminada activa la validación para evitar el envío de formularios no válidos. La prevención del comportamiento predeterminado del envío de formulario no impide la validación del formulario. El resultado es que los campos en la pantalla "siguiente" ya muestran errores de validación, a pesar de que el formulario nunca se envió.
$ ("body"). on ("keyup", "form", function (e) if (e.which == 13) if ($ ("# next"). is (": visible") && $ ("fieldset.current"). find ("input, textarea"). valid ()) e.preventDefault (); nextSection (););
Esta función escucha el evento keyup, activado en el formulario. Si la clave que fue presionada fue enter (código de clave 13), entonces realizamos la siguiente verificación. Si el siguiente botón aún está visible y la sección actual es válida, evite que se presione el botón predeterminado mientras se está en un formulario, que es el envío del formulario..
Entonces llamamos Siguiente sección()
, que avanza el formulario a la siguiente sección. Si la sección actual contiene entradas no válidas, esas entradas se identifican y el formulario no avanza. Si el siguiente botón no está visible, eso significa que estamos en la sección final (que veremos en funciones posteriores) y queremos permitir que se produzca el comportamiento predeterminado (envío del formulario).
$ ("# next"). en ("click", function (e) nextSection ();); $ ("form"). on ("submit", function (e) if ($ ("# next"). is (": visible") || $ ("fieldset.current"). index () < 3) e.preventDefault(); );
Estas funciones son sencillas. Si presiona el botón con la identificación de "siguiente", queremos avanzar a la siguiente sección. Recuerda el Siguiente sección()
La función contiene todos los controles necesarios para la validación de formularios..
En el evento de envío en el formulario, queremos evitar el envío del formulario si el siguiente botón está visible o si el conjunto de campo actual no es el último.
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);
los goToSection ()
La función es el caballo de batalla detrás de la navegación de este formulario. Se necesita un solo argumento: el índice de la navegación de destino. La función toma todos los campos con un índice mayor que el que se pasa en el parámetro índice y elimina el corriente
clase, y añade un siguiente
clase. Esto empuja los elementos a la derecha de la forma..
A continuación, eliminamos la clase actual de todos los conjuntos de campos con un índice menor que el índice pasado. A continuación, elegimos el elemento de la lista igual al aprobado en el índice y agregamos una clase actual.
Posteriormente, eliminamos la clase actual de todos los demás hermanos. li
s. Establecemos un tiempo de espera, después del cual eliminamos la siguiente clase y agregamos las clases actuales y activas al conjunto de campos con un índice igual al que se pasó en el parámetro de índice.
La clase activa nos permite saber que el usuario puede navegar de nuevo a esta sección en particular. Si el parámetro de índice pasado es 3 (el último conjunto de campos), ocultamos el siguiente botón y mostramos el botón Enviar. De lo contrario, queremos asegurarnos de que el siguiente botón esté visible y el botón Enviar esté oculto. Esto nos permite ocultar el botón enviar a menos que el último campo sea visible.
function nextSection () var i = $ ("fieldset.current"). index (); si yo < 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."); );
los Siguiente sección()
La función es básicamente una envoltura alrededor de la goToSection ()
función. Cuando Siguiente sección
se llama, se realiza una comprobación simple para asegurarse de que no estamos en la última sección. Mientras no lo estemos, vamos a la sección con un índice que es igual al índice de la sección actual, más uno.
Estamos escuchando el evento clic en los elementos de la lista. Esta función verifica que el elemento de la lista tenga la clase activa, que recibe una vez que el usuario llega inicialmente a esa sección del formulario completando todas las secciones anteriores. Si el elemento de la lista tiene la clase, llamamos goToSection
y pasar en el índice de ese elemento de la lista. Si el usuario hace clic en un elemento de la lista correspondiente a una sección a la que aún no puede acceder, el navegador le avisa que debe saber que debe completar las secciones anteriores antes de avanzar..
jQuery.validator.addMethod ("phoneUS", function (phone_number, element) phone_number = phone_number.replace (/ \ s + / g, ""); devolver this.optional (element) || phone_number.length> 9 && phone_number. coincidencia (/ ^ (1 -?)? (\ ([2-9] \ d 2 \) | [2-9] \ d 2) -? [2-9] \ d 2 - ? \ d 4 $ /);, "Especifique un número de teléfono válido");
Finalmente, estamos agregando un método especificado por el complemento jQuery Validate que verifica manualmente una entrada. No dedicaremos mucho tiempo a esto, porque esta funcionalidad exacta se puede encontrar en la documentación de Validación..
Básicamente, verificamos que el texto que el usuario coloca en el campo del teléfono coincida con la expresión regular (la larga cadena de números y símbolos). Si lo hace, entonces la entrada es válida. Si no es así, el mensaje "Especifique un número de teléfono válido" se agrega después de la entrada. Podría usar esta misma funcionalidad para verificar cualquier tipo de entrada (no tiene que usar una expresión regular).
Nota: No utilice esto como un método de autenticación de contraseña. Es muy inseguro y cualquiera puede ver la fuente para ver la contraseña.
Hemos utilizado HTML semántico y LESS simple combinados con un mínimo de JavaScript para crear una interacción de formulario robusta. Los métodos utilizados para crear este formulario, especialmente el uso de nombres de clase para identificar el estado y definir funcionalidades y animaciones, se pueden utilizar en casi cualquier proyecto interactivo. La misma funcionalidad podría usarse para demostraciones paso a paso, juegos y cualquier otra cosa que dependa de interacciones simples basadas en estado.
¿Qué más le harías a este formulario? ¿Qué tipos de interacciones ha encontrado para ayudar a los usuarios a fluir de forma más natural a través de un proceso tedioso, como completar un formulario largo de varios pasos? Compártelos en los comentarios.!