Contenedores de pestañas sólo con CSS

En este capítulo expongo dos contenedores con pestañas y usando exclusivamente CSS-2.1 para mostrar y ocultar los contenidos de cada pestaña. En principio parecería más sencillo que usando Javascript. Pero las diferencias en la forma que los navegadores tratan algunos aspectos del CSS dicen lo contrario.

Tal como vimos en los ejemplos con Javascript, necesitamos un elemento que haga de título, de tal forma que al activarlo haciendo click se produzca un evento CSS y desde éste elemento podamos referenciar con CSS el cuerpo del contenido para que se haga visible. Esto podría ser porque se modifica dinámicamente la propiedad de estilo {display} dándole un valor distinto del inicial none. O bien usando cualquier otra propiedad como {z-index} que estructura los elementos en capas. Por lo tanto hay dos aspectos a considerar:

  • Eventos CSS
  • Referenciar con CSS desde un elemento a otro

A continuación hay dos ejemplos de contenedores de pestañas sólo con CSS, pero si quiere ver con más detalle como funcionan debería también consultar el siguiente capítulo sobre referencias y eventos en CSS.

Contenedor de pestañas CSS y elementos vínculo

En este primer ejemplo usamos elementos <a> que van a recibir el foco y generar un evento CSS creando la pseudoclase dinámica a:focus. El contenedor con pestañas en acción es este:

La estructura HTML es la siguiente:

<form class="zpestanya">
    <!--  primer tab con tabindex="100" -->
    <span class="zhueco">&nbsp;</span><a class="zvinculo" 
    tabindex="100" href="javascript:"><span 
    class="ztitulo">Primera</span><span class="zinterior">
        Contenido ...
    </span></a>
    <!--  segundo tab con tabindex="101"-->
    <!--  tercer tab con tabindex="102" -->
    <!-- insertar más tabs aquí -->
    <!--  tab de fondo -->
    <span class="zhueco">&nbsp;</span><a class="zvinculo" 
    tabindex="199" href="javascript:" 
    style="border: 0"><span class="zinterior" style="">
        Contenido de fondo ...
    </span></a>
    <span class="zhueco">&nbsp;</span><div 
    class="zcontenedor"> </div>
</form>

Pseudo-protocolo javascript: en atributos href de un vínculo

No es bueno aplicar JavaScript en el atributo href de un elemento <a>. Inicialmente lo hacía así pero ahora ya he visto algunas recomendaciones que aconsejan hacerlo de esta manera:
    <a href="/res/srv/accion-javascript.html" onclick="return false;" ...>...
        
Esto ya está modificado en el ejemplo. La página accion-javascript.html es una de ayuda al usuario que se mostrará en caso de por cualquier razón el script de onclick tenga un error. O bien si se ha desactivado JavaScript en el navegador. En el ejemplo no hay ningún script que ejecutar. Si hubiera alguno como hacer alert("hola") entonces pondríamos alert("hola"); return false;. El caso es que si esto devuelve false NO se ejecutará el vínculo tras ejecutar el script. Cualquier otra cosa como true, undefined, null o un valor dará lugar a que se ejecute el vínculo. Vea que si una función no devuelve nada explícitamente realmente está devolviendo el valor undefined. Por eso siempre es mejor poner false al final para asegurar que si se ejecuta el script no se ejecute el vínculo.

Hemos obviado algunas cosas, como los contenidos interiores en la estructura de la segunda y tercera pestaña por ser iguales. Vea que en ningún caso usamos identificadores id para manejar estilos, lo que nos permite introducir indefinido número de pestañas simplemente copiando la estructura de cualquier otra. Y lo que es más importante, sin tener que modificar nada en el CSS (a excepción del tema del ancho del contenedor).

Incluimos el atributo tabindex="N" siendo "N" una serie que, por ejemplo, se inicia en 100 de tal forma que la pestaña de fondo sería la 199. El atributo href="javascript:" para el vínculo nos sirve para que este elemento no haga nada con ese enlace. Si ponemos "#" resulta que la página se desplaza al inicio. Dentro del vínculo hay dos elementos. El estilo CSS es el siguiente:

form.zpestanya{
    font-size: 0.8em;
    width: 23em;
    position: relative;
    }
span.zhueco {
    background-color: transparent;
    border: 0;
    border-bottom: gray solid 1px;
    }    
a.zvinculo {
    background-color: gray;
    color: white;
    border: gray solid 1px;
    font-weight: normal;
    text-decoration: none;
    outline: none;
    }
span.ztitulo {
    padding-left: 1em;
    padding-right: 1em;
    }
a.zvinculo span.zinterior {
    display: block;
    position: absolute;
    z-index: -1;
    background-color: rgb(235, 235, 225);
    color: black;
    margin: 0.2em;            
    height: 10em;
    overflow: auto; 
    border: 0;
    font-weight: normal;
    text-decoration: none;
    }
a.zvinculo:focus {
    background-color: rgb(235, 235, 225);
    border-bottom-color: rgb(235, 235, 225);
    color: blue;
    }    
a.zvinculo:focus span.zinterior {
    z-index: 1;
    }
div.zcontenedor {
    padding: 0.2em;
    height: 11em;
    background-color: rgb(235, 235, 225);
    border: gray solid 1px; 
    } 

El contenedor <form class="zpestanya"> envuelve toda la estructura. El ancho es uno de los valores que habrá que modificar en el caso de que incrementemos el número de pestañas y, por tanto, la longitud de todos los títulos sea mayor que ese ancho. También hay que ajustar el ancho y alto del contenedor <span class="zinterior"> donde van los contenidos de cada pestaña. Y por otro lado el alto del contenedor de fondo <div class="zcontenedor">, cuyo cometido es sólo para remarcar el borde que cierra el contenido. Estas medidas sólo se ajustan la primera vez y ya no será necesario cambiarlas si agregamos más pestañas, a excepción del reajuste de ancho de títulos mencionado. Estos reajustes son una de las desventajas frente a las pestañas que usábamos con tablas en el tema anterior.

Finalmente cuando el vínculo obtiene el foco cambiamos el color de fondo de la pestaña, el borde inferior y el color de la letra. Luego accedemos a su hijo <span class="zinterior"> y lo traemos al frente con z-index: 1.

Contenedor de pestañas CSS y elementos de cuadro de texto

Este contenedor de pestañas usa elementos <input type="text"> en lugar de elementos vínculo <a> del ejemplo anterior. En principio tiene más desventajas como se expone con más detalle en el tema siguiente.

Ejemplo:

 
Contenido de la Primera pestaña.

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec sollicitudin libero id elit. Sed euismod nonummy neque. Nam dignissim urna vel urna. Nunc aliquet. Nunc vel dui mattis magna varius condimentum. Etiam lacus enim, aliquam ultricies, luctus ut, placerat id, lectus. Vestibulum laoreet commodo tortor. Nunc eget urna. Suspendisse ac orci. Vivamus quis tortor facilisis velit interdum blandit.

 
Otro contenido para la PESTAÑA 2ª. Ahora sí es posible incluir un elemento vínculo como www.wextensible.com.
 
El último contenido de la Pestaña 3
Tab de fondo

El código HTML:

<form class="xpestanya">
    <!--  Primer tab -->
    <span class="xhueco">&nbsp;</span><input type="text" 
    class="xcuadro" value="Primera" tabindex="200"
    readonly="readonly" /><div class="xinterior">
        Contenido...
    </div>
    <!--  Segundo tab -->        
    <!--  Tercer tab -->        
    <!--  Insertar aquí otro tab con siguiente tabindex -->
    <div class="xfondo"><div>Tab de fondo</div></div>
</form>

La principal diferencia es que el contenedor interior <div class="xinterior"> es hermano de la pestaña <input type="text"> y no hijo como en el primer ejemplo. Aquí también usamos los atributos tabindex cuya finalidad se comenta en el tema siguiente. También hay un contenedor <div class="xfondo"> para dar el fondo y dar borde al conjunto.

form.xpestanya {
    font: 1em Palatino Linotype;
    position: relative;
    height: 12em;
    width: 20em;
    }
span.xhueco {
    background-color: transparent;
    border-bottom: gray solid 1px;
    }               
input.xcuadro {
    width: 4em;        
    margin: 0;
    padding-left: 1em;
    padding-right: 1em;  
    background-color: gray;
    color: white;
    border: gray solid 1px;
    outline: none;                          
    text-align: center;
    font-family: Palatino Linotype;
    cursor: pointer;
    }
div.xinterior {
    position: absolute;
    z-index: -1;
    background-color: rgb(235, 235, 225);
    left: 0;
    margin: 0.5em;
    color: black;
    height: 9em; 
    overflow: auto; 
    }
input.xcuadro:focus {
    border-bottom-color: rgb(235, 235, 225);
    background-color: rgb(235, 235, 225);
    color: blue;
    }
input.xcuadro:focus + div.xinterior {
    z-index: 1;
    }
div.xfondo {
    z-index: 0;
    background-color: rgb(235, 235, 225);          
    border: gray solid 1px;
    margin-top: -1px;
    height: 10em;
    width: 100%;
    }
 div.xfondo > div {
    margin: 0.5em;
    }

Aunque los detalles se comentan en el siguiente tema, podemos finalizar diciendo que tendremos que modificar las medidas si el número de pestañas supera el ancho disponible del elemento <form> que lo contiene todo.