Responsive FAQ: de tabs a en línea 19.4.15
Una estructura de "preguntas frecuentes y sus respuestas" (FAQ) que cambia su forma de presentarse en función del tamaño (anchura o altura): de un sistema de tabs adyacentes a intercaladas.
Responsive FAQ: de tabs a en línea
Este fin de semana, en uno de los paseos por Codepen, me topé con la realización "Vertical Tabs: Smart & Responsive". Una navegación por pestañas o tabs que muestran su contenido a su lado y al alcanzar cierto tamaño mínimo del viewport pasan a ocupar toda su línea y el contenido asociado se muestra debajo de cada una.
Me llamaron la atención dos detalles:
- Su marcado Html.
- El uso de jQuery para su funcionamiento.
Uso de la librería javascript que el mismo autor lamenta haber recurrido a ella:
Didn't want to use jQuery but i'm pressed for time
Me picó la curiosidad de intentar "recrear su funcionamiento" en base a puro Css simplificando al máximo tanto el marcado Html como las declaraciones Css.
Lograr el comportamiento de la info supone renunciar a la vía del :checked
y sus labels asociadas para minimizar las reglas Css necesarias y que no dependan del número de pestañas.
Para ello la vía elegida es el uso de :target
. La técnica para evitar los "saltos asociados" ya es una vieja conocida del blog.
A su vez, necesitamos un contenedor extra para lograr que la info oculta en unos caso se muestre intercalada entre las "tabs" (en viewports "pequeños") y en otros (viewports grandes) se visualice a su lado sin producir desplazamiento en ellas.
El marcado Html para cumplir con estas premisas sería algo como lo siguiente:
<section>
<div>
<span id='uno'></span>
<a class='ref' href='#uno'>1ª Pestaña</a>
<article>
<!-- contenido oculto 1ª tab-->
</article>
<span id='dos'></span>
<a class='ref' href='#dos'>2ª Pestaña</a>
<article>
<!-- contenido oculto 2ª tab-->
</article>
...
</div>
</section>
Para añadir pestañas y su contenido asociado sólo es necesario modificar el id
de cada span
y que este valor sea el mismo en el href
del enlace que le sigue.
El Css asociado
Lo primero es preparar el terreno declarando el Css necesario tanto al section
como al div
hijo que contiene toda la info. Los estilos básicos son:
section {
overflow: hidden;
}
section > div {
position: static;
width: 25%;
transition: .4s;
}
La posición static
hará que no sea referente para la ubicación de su contenido.
.ref {
background-color: #52545a;
color: #000;
text-decoration: none;
font-size: 1.3rem;
display: block;
padding: .5rem;
border-bottom: 1px solid rgba(0,0,0,.3);
}
article {
position: absolute;
margin-left: 26%;
top: 0;
height: 0%;
max-height: 0;
overflow: hidden;
transition: .5s;
}
Ya tenemos las "pestañas" colocadas una sobre otra en el eje Y y todos los articles
ocultos y colocados sin que se sobrepongan (eje Z) con ellas.
Aplicando un poco de la magia del :target
para distinguir las pestañas según su estado y mostrar el contenido según la que pinchemos:
span[id] {display: none;}
:target + a,
.ref:hover,
.ref:focus {
background-color: #333;
color: #fff;
}
:target + a + article {
height: 100%;
max-height: 100vh;
overflow: auto;
}
Tras esto y unos reglas más sólo a efectos estéticos y para el resto de elementos contenidos en cada article
que no afectan al funcionamiento de la demo, sólo resta cambiar un poco el comportamiento en pantallas pequeñas.
Medias Queries
O lo que es lo mismo, añadir una pizca de Css para que esta demo pueda lucir la escarapela de responsive
.
Para ello y por la naturaleza de la demos hemos de definir dos puntos de ruptura (valores aleatorioss): para viewports menores a cierta altura y también para aquellos que tengan menos de la anchura deseada. Ambos puntos o condición los indicamos en la misma regla @media
separados por una coma:
@media all and (max-width:800px),
all and (max-height:400px) {
section > div {
position: relative;
width: 100%;
}
article {
position: relative;
margin-left: 0;
top: auto;
width: 100%;
height: 0%;
max-height: 0;
overflow: hidden;
}
:target + a + article {
height: auto;
max-height: 1000vh;
overflow: hidden;
padding-bottom: 1rem;
}
}
El resultado de poner todo junto y en funcionamiento lo puedes ver en el siguiente pen:
See the Pen Responsive f&q from tabs to lines by Kseso (@Kseso) on CodePen.
Como siempre, en los casos en que es necesario modificar el tamaño del viewport donde se muestra la demo (te recuerdo que es un iframe y que estos elementos crean su propio viewport), lo mejor es verlo sin estar incrustado aquí en el blog:
Kseso
the obCSServer ᛯ Ramajero Argonauta, Enredique Amanuense de CSS.#impoCSSible inside
Dicen que, en español, EsCss es el mejor blog de CSS. Posíblemente exageren.
@Kseso EsCss Kseso
Buenos días, gracias y felicitaciones por tu blog Kseso, es una fuente inagotable y se agradece. Si clicas en un elemento, éste se abre en modo elástico hacia abajo. Pero si ese elemento vuelves a clicarlo no se cierra... qué debería cambiarse para corregir esto? muchas gracias
ResponderEliminarHola Daniel
EliminarLos "estados" :checked :target son permanentes. Esto es, los estilos asociados a ellos se mantienen aplicados hasta que es otro elemento el que lo recibe.
Por eso una vez que tienes #uno:target + ... no ocurre nada por mucho que se repita la selección de #uno, esto es, en la demo una vez comenzada la apertura de información siempre habrá una "faq" visible.
Esto en la demo incrustada en Codepen pasa desapercibido. Pero si copias los códigos a un archivo html y lo ejecutas directamente en tu navegador verías cambiar la ruta en la barra de navegación.
Si quieres poder pasar a un estado donde se cierren todas necesitas crear un elemento para el cierre (como en muchas demos del blog con :checked) así el :target pasará a un elemento distinto a los que controlan las "pestañas":
[code]
<span id='cierre'></span>
<a href='#cierre'>Cerrar</a>
[/code]
Un saludo