Formulario

Mario González - Blog sobre desarrollo web

Elementos de formulario opcionales con transiciones CSS

| ,

En este minitutorial vamos a crear un formulario HTML en el que algunos elementos estarán ocultos y se mostrarán al rellenar o marcar otros elementos del formulario. Utilizaremos jQuery y transiciones CSS3 para mostrar y ocultar los elementos.


Ver resultado final

El HTML

El formulario que vamos a crear es bastante simple, pero nos servirá para partir de él y crear formularios más complejos. La idea de este tutorial es aprender a usar las transiciones de CSS3 para mostrar y ocultar elementos al estilo de slideUp y slideDown de jQuery. Los archivos del tutorial están disponibles para descargar.

Para empezar, decidamos qué datos serán fijos y cuáles dependerán de otros:

Datos fijos:
1. Nombre
2. Apellidos
3. He desarrollado alguna web

Datos dependientes:
Si se ha marcado el dato 3, aparecen:
4. Ya desarrollo con HTML5
5. Utilizo algún preprocesador para CSS
Si se ha marcado el dato 5, aparece:
6. Preprocesador: LESS, SASS, Stylus (esto será un desplegable)

Comenzaremos incluyendo todos los datos, y luego veremos cómo ocultar los dependientes. Éste será el código HTML de nuestro formulario:


<h1>Formulario para desarrolladores</h1>
<form action="#">
    <ul>
        <li><label for="nombre">Nombre</label> <input id="nombre" name="nombre" type="text" /></li>
        <li><label for="apellidos">Apellidos</label> <input id="apellidos" name="apellidos" type="text" /></li>
        <li><label for="pregunta_desarrollo">He desarrollado alguna web</label> <input id="pregunta_desarrollo" name="pregunta_desarrollo" type="checkbox" /></li>
        <li><label for="pregunta_html5">Ya desarrollo con HTML5</label> <input id="pregunta_html5" type="checkbox" /></li>
        <li><label for="pregunta_preprocesadores">Utilizo algún preprocesador para CSS</label> <input id="pregunta_preprocesadores" name="pregunta_preprocesadores" type="checkbox" /></li>
        <li><label for="preprocesador">Preprocesador</label><select id="preprocesador" name="preprocesador">
            <option value="less">LESS</option>
            <option value="sass">SASS</option>
            <option value="sass_compass">SASS / COMPASS</option>
            <option value="stylus">STYLUS</option>
        </select></li>
    </ul>

    <button type="submit">enviar</button>

</form>

Es un marcado bastante estándar. Hemos optado por maquetar un formulario en columna, presentando un dato por línea, con las etiquetas en línea con los inputs. Aquí podemos ver el resultado de nuestro HTML.

El CSS

Vamos a darle unos estilos básicos a nuestro formulario:


h1, form {
    font-family:Arial, sans-serif;
}
h1 {
    font-size:1.4em;
    font-weight:bold;
    margin:10px 0;
}
form {
    margin-top:20px;
}
form li {
    height:30px;
    line-height:30px;
}
form label {
    width:270px;
    display:block;
    float:left;
    text-align:right;
    margin-right:10px;
}
form button {
    margin-top:20px;
    margin-left:260px;
}

Contando con que hemos incluido algún reset CSS, nuestro formulario debería verse más o menos así. No le hemos dado estilo a los elementos de formulario (input, select, submit), así que se verán diferentes según el navegador y el sistema operativo.

Ahora estamos viendo todos los datos, sin embargo, algunos de ellos son opcionales y no deberían verse al principio. Lo que haremos será, en el HTML, asignarles una clase llamada oculto. Se la asignaremos a los li, porque queremos que se muestre/oculte toda la fila.


<ul>
    <li><label for="nombre">Nombre</label>
        <input id="nombre" name="nombre" type="text" /></li>
    <li><label for="apellidos">Apellidos</label>
        <input id="apellidos" name="apellidos" type="text" /></li>
    <li><label for="pregunta_desarrollo">He desarrollado alguna web</label>
        <input id="pregunta_desarrollo" name="pregunta_desarrollo" type="checkbox" /></li>
    <li class="oculto"><label for="pregunta_html5">Ya desarrollo con HTML5</label>
        <input id="pregunta_html5" type="checkbox" /></li>
    <li class="oculto"><label for="pregunta_preprocesadores">Utilizo algún preprocesador para CSS</label>
        <input id="pregunta_preprocesadores" name="pregunta_preprocesadores" type="checkbox" /></li>
    <li class="oculto"><label for="preprocesador">Preprocesador</label><select id="preprocesador" name="preprocesador">
        <option value="less">LESS</option>
        <option value="sass">SASS</option>
        <option value="sass_compass">SASS / COMPASS</option>
        <option value="stylus">STYLUS</option>
    </select></li>
</ul>

El siguiente paso será darle estilo a los elementos con clase oculto. Lo primero que a uno se le ocurre es usar display:none. Sin embargo, nosotros queremos mostrar los elementos con un efecto similar al slideDown de jQuery. La transición que buscamos no es pasar de invisible a visible, sino pasar de tener altura 0px a tener altura 30px (la altura que tienen los li visibles). Para ello, la clase oculto tendrá el siguiente código CSS:


.oculto {
    height:0;
}

Si hacemos esto probablemente no notemos ningún cambio. En realidad sí hay un cambio: el li realmente tiene una altura de 0 píxeles, pero su contenido, que es texto, se sale del elemento y se ve, porque el overflow está por defecto a visible. Cambiemos entonces esta propiedad en los li:


form li {
    height:30px;
    line-height:30px;
    overflow:hidden;
}

Ahora sí que habrán desaparecido los elementos con clase oculto. Con esta simple clase podremos mostrar y ocultar los elementos desde el jQuery. Aquí podemos ver el formulario con los campos ocultos.

El jQuery

Vamos a ver cómo asignarle al checkbox del dato 3 un evento click, que comprobará si está marcado o no y mostrará u ocultará los datos que nos interesan:


$(document).ready(function() {

    $("#pregunta_desarrollo").on("click", function() {
	if ($(this).is(":checked")) {
	    $("#pregunta_html5, #pregunta_preprocesadores").closest("li.oculto").removeClass("oculto");
	} else {
	    $("#pregunta_html5, #pregunta_preprocesadores, #preprocesador").closest("li").addClass("oculto");
	}
    });

});

Expliquemos brevemente el código:


$("#pregunta_desarrollo").on("click", function() {

Primero le asignamos un evento click a la pregunta que nos interesa («He desarrollado alguna web»), identificándola mediante su id pregunta_desarrollo. El evento lanzará la siguiente función cuando se haga clic en el checkbox, que consiste primero en comprobar si éste se ha marcado o desmarcado:


if ($(this).is(":checked")) {
    ...
} else {
    ...
}

En caso de haberse marcado el checkbox, la primera línea que se ejecuta es:


$("#pregunta_html5, #pregunta_preprocesadores").closest("li.oculto").removeClass("oculto");

Primero usamos un selector que engloba las dos preguntas que queremos mostrar. El elemento que está realmente oculto no es la pregunta, sino el li que la contiene, por eso al selector le añadimos .closest("li.oculto"). Y luego nos limitamos a quitarle la clase oculto, con lo que la pregunta aparecerá.

Las siguientes líneas de código son para el select de los preprocesadores. Éste debe aparecer siempre que esté marcado el checkbox anterior:


if ($("#pregunta_preprocesadores").is(":checked")) {
    $("#preprocesador").closest("li.oculto").removeClass("oculto");
}

Por último, la línea de código para cuando se ha desmarcado el primer checkbox (que va en el else de la condición inicial):


$("#pregunta_html5, #pregunta_preprocesadores, #preprocesador").closest("li").addClass("oculto");

Hacemos lo contrario a lo que hicimos antes: al li que contiene las preguntas opcionales le añadimos la clase oculto, para que desaparezca.

Lo último que nos queda es hacer que cuando se marque la pregunta de si se usan preprocesadores CSS, aparezca el desplegable con los preprocesadores:


$("#pregunta_preprocesadores").on("click", function() {
    if ($(this).is(":checked")) {
	$("#preprocesador").closest("li.oculto").removeClass("oculto");
    } else {
	$("#preprocesador").closest("li").addClass("oculto");
    }
});

Si probamos ahora el formulario, veremos que aún falta una cosa. Si marcamos «He desarrollado alguna web», luego marcamos «Utilizo algún preprocesador para CSS», y luego desmarcamos «He desarrollado alguna web», todo parece estar bien. Pero si ahora volvemos a marcar «He desarrollado alguna web», vemos que falta algo. Aparece marcado «Utilizo algún preprocesador para CSS» (esto es correcto, lo marcamos antes), pero no aparece el desplegable de preprocesadores CSS. Esto es porque, en nuestro código, hacer clic sobre la primera pregunta sólo hace aparecer la segunda, pero no influye en las demás. Para que funcione correctamente, añadiremos estas líneas a la primera condición:


if ($("#pregunta_preprocesadores").is(":checked")) {
    $("#preprocesador").closest("li.oculto").removeClass("oculto");
}

Con lo que el código final nos queda así:


$("#pregunta_desarrollo").on("click", function() {
    if ($(this).is(":checked")) {
	$("#pregunta_html5, #pregunta_preprocesadores").closest("li.oculto").removeClass("oculto");
	if ($("#pregunta_preprocesadores").is(":checked")) {
	    $("#preprocesador").closest("li.oculto").removeClass("oculto");
	}
    } else {
	$("#pregunta_html5, #pregunta_preprocesadores, #preprocesador").closest("li").addClass("oculto");
    }
});
$("#pregunta_preprocesadores").on("click", function() {
    if ($(this).is(":checked")) {
	$("#preprocesador").closest("li.oculto").removeClass("oculto");
    } else {
	$("#preprocesador").closest("li").addClass("oculto");
    }
});

Podemos comprobar el formulario funcionando correctamente.

Las transiciones

Ahora mismo nuestro formulario es funcional, pero queremos añadirle unas transiciones a las preguntas que aparecen y desaparecen. Habíamos establecido que los elementos ocultos tenían una altura de 0 píxeles, y los que se muestran tenían una altura de 30 píxeles. Lo único que tenemos que hacer es añadir mediante CSS una transición en la propiedad height.

En el momento de publicar este artículo, las transiciones CSS aún no están estandarizadas, así que hay que usar prefijos para navegadores:


form li {
    height:30px;
    line-height:30px;
    -moz-transition:height 200ms ease;
    -webkit-transition:height 200ms ease;
    -o-transition:height 200ms ease;
    transition:height 200ms ease;
}    

Con este código hemos establecido una transición en la propiedad height, que durará 200 milisegundos. Si probamos ahora el formulario final, veremos cómo las preguntas aparecen y desaparecen con el efecto persiana que estábamos buscando.

Conclusiones

Si queremos convertir este ejemplo en un caso real, probablemente aún nos quede trabajo por hacer. Lo mejor sería encapsular el jQuery en un plugin y hacerlo más general, para que sirva para cualquier elemento de un formulario, y también habría que tener en cuenta si el formulario puede aparecer ya relleno con datos desde el principio (mediante algún lenguaje del lado del servidor). Pero eso queda más allá de la intención de este tutorial, que es la de explicar una base que pueda servir para hacer algo más atractivos nuestros formularios.

¿Qué opinas?

Tu dirección de correo electrónico no será publicada. * Campos obligatorios