soy Kseso y esto EsCSS

Sistema de pestañas (tabs) Css con :target sin salto y RWD

Doble contenido del post: cómo hacer unas RWD pestañas (tabs) en puro css sin el salto intrínseco al uso de :target forma sencilla y comprensible. Estilos explicados paso a paso para quien empieza.

Sistema de pestañas (tabs) Css con :target sin salto y RWD

·Por Kseso ✎ 55

target cssEl uso de pestañas o tabs para mostrar contenido bajo demanda es un recurso de sobra conocido y utilizado en el diseño de páginas.

Igual de conocido es que para su construcción puedes elegir entre varias técnicas para lograrlo. Y si conoces un poco este blog y de qué va, no te extrañará que veamos un ejemplo basado en puro Css para realizar tabs con tres premisas:

  1. En primer lugar realizar unas pestañas basadas en puro Css con la ayuda de :target.
  2. En segundo y quizás como más novedoso, evitar el salto que lleva aparejado dicho pseudoelemento.
  3. Y como es casi de obligado cumplimiento en los tiempos que nos han tocado, añadirle un toque RWD.

ACTUALIZADO: 03/2014:
Si estás interesado en este tipo de realizaciones te invito a ver este artículo con una recopilación de casi una veintena de Slaiders, galerías y pestañas o tabs en puro Css. Todas ellas de realización propia, basadas en distintas técnicas con disposiciones y efectos de lo más variado.

La pseudoclase :target en xhtml y css

Pero primero, un poco de teoría para los nuevos.

"Target" se podría traducir como el destino, el blanco o el seleccionado.
En html, el destino de una dirección o enlace, por lo general, suele ser una página. Pero habrás visto que, en ciertas ocasiones, termina con algo parecido a ".html#texto". Significa que apunta a un elemento en concreto dentro del documento. Y ese #texto fuerza al navegador al cargar la página a ir a su posición y mostrarlo en la parte superior de la ventana.

Y sí, es lo que en ciertos momentos se llaman "anclas", "anchors" o similares. Por otra parte, ya habrás observado que el símbolo # (almohadilla) es el mismo que el utilizado en CSS para los id (identificadores únicos).

Así que ahí tenemos un pseudoelemento en el html. Aquel objeto que en un momento dado seleccionamos o convertimos en el destino de una acción.

Y para actuar sobre él (sobre el objeto de nuestra selección), CSS define la pseudoclase :target
Una de las diferencias principales con las demás pseudoclases como | :visited | :hover | :active | :focus | etc, es que estan últimas no son persistentes. Su efecto desaparece al retirar el curso, pinchar en una zona en blanco... etc. Cosa que no ocurre con :target que permanece... hasta seleccionar otro :target.

Esa persistencia mencionada es una característica que se utiliza para ciertas realizaciones como son la navegación por pestañas (tabs), desplegables, etc, donde se requiere que no se oculte la información al retirar el puntero, como ocurre con :hover.

:target y sus saltos

El principal inconveniente, por molesto, que tiene el uso de :target nace de sus propias características: el salto que conlleva. Al seleccionar un elemento el navegador desplaza los contenidos para colocar al target en la parte superior de la ventana.

A estas alturas ya hay otras soluciones. Algunas tan radicales como emplear ::checked en vez de :target y otras que lo mantienen pero a costa de enmarañar los códigos (Css y Html).

Anulando el salto con elegancia

El método es sencillo. Basta con fijar al elemento destino de :target y ocultarlo. Así:

.diana { position: fixed; display: none; }

Y antes que empiecen los peros y objeciones, no te preocupes, que con el etiquetado y correcto y el selector de adyacente + solventamos las dos declaraciones anteriores.

Etiquetado de las tabs

El marcado que vamos a utilizar para hacer nuestras tabs es el siguiente:

<div class="contenedor-tabs"> <!-- El primer bloque de pestaña+contenido asociado --> <span class="diana" id="una"></span> <div class="tab"> <a class="tab-e" href="#una">UNA</a> <div class="panel"> <!-- Contenido a mostrar/ocultar --> </div> </div> <!-- Fin del primer bloque --> <!-- Segundo bloque --> <span class="diana" id="dos"></span> <div class="tab"> <a class="tab-e" href="#dos">DOS</a> <div class="panel"> <!-- Contenido a mostrar/ocultar --> </div> </div> <!-- Fin segundo bloque --> <!-- Resto de bloques --> </div>

Desmenuzando el html y su Css asociado:

Todas nuestras pestañas y el contenido asociado está contenido en el div "contenedor-tabs". Lo primero es fijar unas medidas, según se necesiten, con un ancho máximo y opto por la variante del modelo de caja box-sizing

* { margin: 0; padding: 0; box-sizing: border-box; } .contenedor-tabs { width: 100%; max-width: 600px; margin: 50px auto 0; position: relative; }

La función del <span class="diana" id="una"></span>: es el elemento al que haremos :target. Cada uno tiene su #id diferenciador para que :target funcione. El id de cada uno de estos span coincide con el destino del enlace (href) de la pestaña asociada (a class="tab-e). Su Css el que te mostré antes.

<div class="tab"> es el módulo base de cada grupo. En él están los contenidos a mostrar u ocultar y la "pestaña" para acceder a ellos. No hay estilos asociados, ya que en la demo no son necesarios.

<a class="tab-e" href="#una">UNA</a> Este enlace es el que constituye la solapa o "pestaña" que se mantiene siempre visible y accesible.
Como ves el valor de su atributo href, el destino del enlace, es el span oculto que le precede en el html.
Sus estilos no tienen mayores secretos: flotados para que las cuatro pestañas se coloque adyacentes, con una anchura definida (apoyada por el min-width), y el resto de propiedades para lograr una apariencia.

Fíjate en su margen negativo superior. Ese valor junto al top del div que le sigue hace que no queden ocultas las pestañas por el contenido que muestran/ocultan.

.tab .tab-e { background: #d5d5d5; float: left; width: 20%; min-width: 85px; margin-top: -1rem; margin-right: 3px; padding: 5px; text-decoration: none; font-family: nunito, sans-serif; font-size: 1.3rem; color: #dfdfdf; text-align: center; position: relative; border-radius: 5px 5px 0 0; transition: all 1s ease; }

<div class="panel">
Advertencia: a este div le he asignado una clase sólo a efectos de identificarlo mejor al referirme a él. Realmente no se necesita esa clase, como veremos después y ya te adelanté antes al mencionar el selector de hermano adyacente.

Lo reseñable de su css es que está posicionado a 1em de la parte superior de su contenedor para hacer sitio a las pestañas y ocultos mediante la propiedad opacity: 0;

.tab div { background: #fff; width: 100%; position: absolute; top: 1rem; left: 0; padding: 1rem; font-size: 1.2rem; font-family: carme, sans-serif; color: #fff; line-height: 1.2; z-index: 5; opacity:0; border-radius: 0 5px 5px; transition: all 1s ease; }

Si integras el ejemplo en una página con más contenidos después de la demo, deberías optar por otro tipo de posicionamiento ≠ absoluto en esta caja o darle altura suficiente al contenedor general para evitar que se coloque un contenido sobre otro.

El resultado después de todo lo anterior es el que ves en la imagen:

navegación por tabs Css

Fíjate que ya llevamos dos metros de artículo y ni aparece el contenido de los paneles ni hemos usado :target
Pero como ya te adelantaba antes, es lo más sencillo y corto. Vamos con ello.

Aplicando :target

Vamos primero con la pestaña que estará activa o seleccionada. El enlace que hemos marcado con la clase "tab-e". Para ello construimos el selector necesario en la regla Css:
.diana:target + .tab .tab-e :
Este selector dice que se aplique los estilos a la clase "tab-e" (nuestro enlace y pestaña) contenida en "tab" cuando el hermano adyacente con clase "diana" (nuestro span oculto) sea seleccionado con :target (hermano adyacente: que le precede en el html sin nada por medio). Si tienes dificultades para interpretar los selectores puedes ampliar el cómo se leen.

Aquí quizás alguno aún no tenga claro cómo conseguimos marcar con :target a nuestro span oculto. Lo repasamos: al clicar en el enlace "tab-e" nos lleva a su destino (su href="#algo) y este destino es el id del span que le precede. Por eso damos un id diferente a cada span oculto que coincide con el href de cada pestaña,

Ahora sí, aclarado lo anterior los estilos de la pestaña seleccionada. Nada reseñable, sólo cambiamos unos valores por otros para resaltarla, Y el z-index para colocarla sobre (eje z) las otras pestañas y por debajo (eje z) de su panel:

.diana:target + .tab .tab-e { background: #8AA9B8; color: #f5f5f5; box-shadow: 0 0 5px rgba(0, 0, 0, 0.2); z-index: 2; }

Y a continuación sólo nos queda hacer visible el panel de contenidos asociado a cada pestaña.
.diana:target + .tab div :
La lectura del selector es como antes, sólo cambia que apuntamos al div dentro de "tab" que contiene los elementos ocultos. Como sólo hay un div (además del enlace que actúa como pestaña) no es necesario ni asignarle una clase ni utilizar selector de hijo directo (>) como mencionaba antes.

La aparición la realiza el cambio de opacidad inicial de cero a 1

.diana:target + .tab div { opacity: 1; background: #8AA9B8; color: #fff; } css tabs

Y esto es todo lo necesario para lograr un sistema de pestañas o tabs realizado en puro Css sin que el uso de :target ocasione saltos.
Ahora sólo nos queda una pizca de @media queries para poder decir que son "responsive".

Responsive design en tabs

A modo de ejemplo y como es una demo sólo vamos a declara una @media querie y de forma general: para las ventanas menores a 370px.
Para ello actuamos (cambiamos algunos valores) de los tres elementos principales: el contenedor general de clase ".contenedor-tabs", el div panel y el enlace que forma cada pestaña:

@media screen and (max-width:370px) { .contenedor-tabs { width: 100%; min-width: 370px; margin: 2.5rem 0; } .tab div { font-size: 1rem; line-height: 1.1; padding: 1rem 5px; width: 100%; } .tab .tab-e { font-size: 1rem; padding: .5rem 0; text-align: center; line-height: 1.5rem; width: 25%; margin-right: 0; } }

Resultado final de target en las pestañas

Y ahora ya podemos dar por terminado y ver nuestro sistema de pestañas "responsive" con target y sin (sobre)saltos.
Aquí el pen resultante

Si se te hizo corto, más

No recuerdo dónde vi la técnica del elemento oculto para evitar el salto. Mis disculpas. Si alguien sabe su autor que lo comente para otorgar crédito.
Puedes profundizar en :target y algunas realizaciones en base a él:

  1. Diferencias entre :hover :focus :target :checked
  2. :Target ¿Algún problema?
  3. Guerra de pseudoelementos en Css. :target vs :checked
  4. Cambio de hoja de estilos con puro Css

Este post fue escrito allá por 2012. Mucho tiempo ha. Desde entonces son muchas las demos de tabs o pestañas publicadas.
Para modificarlo se necesitan ciertos conocimientos mínimos de Css. Si aún no los tienes mi consejo es que busques alguna de esas otras demos para adaptarla a tus necesidades. Algunas las tienes ya enlazadas en el artículo y otras en los comentarios. En especial esta recopilación de tabs y galerías.

avatar del Editor del blog

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