Filtrar datos con Css y emular consultas a bases de datos :checked ~ :not

Demo en puro CSS para mostrar resultados filtrados por categoría, simulando consultas a una base de datos. Con opciones para mostrar todo el contenido o resetear y ocultarlo.

Filtrar datos con Css y emular consultas a bases de datos :checked ~ :not

Por Kseso ✎ 18

Galería de imágenes: pseudo consulta a base de datos en puro CssUna demo para mostrar resultados filtrados por categoría, simulando una consulta a una base de datos. Con opciones para mostrar todo el contenido o resetear y ocultar todo.

Normalmente este tipo de realizaciones se ayudan de javascript o algún otro lenguaje para realizar las consultas oportunas y seleccionar unos datos u otros. U ordenar la información en el html añadiendo etiquetado extra. Pero también es posible prescindir de todos ellos y realizarlo en puro Css.

Como es lógico, Css no permite realizar consultas, por eso en el título hablo de "pseudo consulta". Pero el filtrado sí. Todo es cuestión de elegir los selectores apropiados, en este caso, speudoclases.

Antes de pasar a ver el ejemplo y sus códigos, unos apuntes:

.- Si el contenido es numeroso y muy pesado, habrá una demora en la carga y por lo tanto un retraso para tenerlo accesible al inicio.
.- Pero una vez cargado por primera vez, los cambios serán instantáneos, sin esperas o saltos.
.- Tampoco es necesario separar ni ordenar la información en el html, no es obligado agruparla ni ordenarla.

Ver Demo

Marcado Html

Vamos a aprovechar que html5 permite utilizar elementos de formulario sin necesidad del tag form, así que la demo se basa en el método input type="radio" precediendo a las imágenes que están contenidas en un elemento figure. Como es lógico, sería igual una lista o cualquier otro elemento.

Básicamente el etiquetado es:

<article id="galeria"> <input type="radio" name="filtro" id="nature"> <label for="nature">Naturaleza</label> <input type="radio" name="filtro" id="sport"> <label for="sport">Deportes</label> <!-- resto de inputs--> <figure id="filtro"> <img src="ruta/img.ext" alt="" class="nature"> <img src="ruta/pit.ext" alt="" class="sport"> <img src="ruta/pic.ext" alt="" class="moda"> <!-- resto de imágenes--> </figure> </article>

Para esta demo declaro una clase en cada imagen, que será la usada para filtrar los resultados asignando la misma clase a las imágenes afines y así crear los diferentes grupos. Se podrían sustituir estas clases por cualquier atributo data-. No se emplean para aplicar estilos.

El Css necesario, con mucho estilo

Como suele ocurrir en casi todas las realizaciones, lo primero son unos estilos básicos para contener la info y presentarla. Creo que no se necesitan explicaciones, pero si me equivoco, tienes los comentarios:

Estilos base

#galeria { background: #fff ; display: inline-block; max-width: 900px; margin: 1rem auto; padding: 0 10px; box-shadow: 0 0 5px rgba(0, 0, 0, 0.2), 0 15px 15px -12px rgba(0, 0, 0, 0.35); text-align: center; border-radius: 3px; } figure#filtro { margin: 0 0 15px; padding: 0; text-align: center; letter-spacing: 10px; } figure#filtro img { width: 0px; /*no queremos mostrarlas de entrada*/ margin: 10px 0 0 0; border-radius: 5px; box-shadow: 0 0 4px rgba(0, 0, 0, 0.2), 0 15px 15px -12px rgba(0, 0, 0, 0.55); border-top: 1px solid #e0e0e0; transition: 1s; } input[type=radio] {display: none;} /*No interesa mostrarlos, sólo que funcionen*/

Filtros Css de consulta

Filtrar resultados con Css para emular consultas a bases de datos

Para filtrar qué imágenes mostramos nos apoyamos en la pseudoclase :checked aplicada al radio input y en la clase asignada a cada grupo de ellas. Unidas por el selector de hermano:

input#nature:checked ~ figure img.nature { width: 250px;}

Y a continuación ocultamos el resto de imágenes que no tengan dicha clase. Para seleccionarlas usamos en el selector la pseudoclase de "exclusión" o negación :not(.clase)

input#nature:checked ~ figure img:not(.nature) { opacity: 0; position: absolute; top: 0; left: 50%; }

Estas dos declaraciones hay que repetirlas, cambiando el id y la clase, por cada grupo que creemos, coincidiendo con las etiquetas de selección que encabeza la demo

Mostrando todas las imágenes

Con lo anterior ya tenemos prácticamente todo el trabajo hecho, sólo nos queda ofrecer la posibilidad de ver mostrar todo el contenido. Así que creamos el input y su etiqueta y las declaraciones asociadas:

Filtrar resultados con Css para emular consultas a bases de datos <input type="radio" name="filtro" id="todo"> <label for="todo">Todo</label> /* Css */ input#todo:checked ~ figure img { width: 160px; display: inline-block; /*resto de declaraciones*/ }

Reseteando la consulta

Para borrar la consulta y ocultar todas las imágenes volvemos a crear su input y el css asociado para las miniaturas. Y ya de paso, damos una apariencia diferencial a esta opción:

Filtrar resultados con Css para emular consultas a bases de datos <input type="radio" name="filtro" id="x"> <label for="x">×</label> /* Css */ input#x:checked ~ figure img { width:0; opacity:0; transition: .5s; } input#x + label { padding:5px; border-radius: 50%; background: #eee; color: #999; font-size: 1.5rem; box-shadow: 0 0 2px rgba(0, 0, 0, 0.5), 0 5px 8px -4px rgba(0, 0, 0, 0.45) inset; }

Y con esto ya tenemos todo listo para filtrar la información mostrada en función de lo que seleccione el usuario, sin tener que recurrir a otros lenguajes que no sea Css y sin tener que ordenar los elementos en el html. Sólo quedarían unos estilos más para que luzcan los "labels" y que cambien según estén seleccionados o al recibir el :hover.

Todo junto funcionando

Y todo lo anterior junto y en funcionamiento da como resultado:

Check out this Pen!

Por alguna razón, las animaciones no acaban de ir finas si lo ves en Chrome. No se si será algún conflicto con codepen o qué. Al no ser una parte complementaria en la demo no me he parado a ver las causas.

Epílogo

Como te decía en al inicio, esta forma de filtrar datos no sería recomendable en situaciones de una gran cantidad de ellos, especialmente si conllevan mucho peso (decenas de imágenes, por ejemplo).
Pero en otras situaciones, como una pequeña galería con pocas imágenes o datos de sólo texto tiene la ventaja que ahorras recursos, peticiones y demoras. Claro está, siempre que tus visitantes usen navegadores actuales.

Pero como ya debes saber, este blog habla de Css y sus posibilidades. Sólo son experimentos, propuestas o artículos de divulgación. Debes ser tú quien evalúe la idoneidad de aplicarlo a una producción en función de las circunstancias propias de cada caso.
Quien se limita a hacer un copy&paste en el pecado lleva la penitencia.

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 Don Kseso Kseso

Comentarios: 18

  1. Uff esto esta genial prefiero sinceramente trucos con CSS que con javascrit o JQuary creo que son menos pesados para la pagina ya que solo se cargarían en las entradas individuales y forman parte de la plantilla, a menos que tu CSS sea una barbaridad y debas guardarlo fuera de la misma pero creo que la mejor opción es la plantilla, Fantastico el truco gracias por compartir.

    Sin sitios como este seria muy tedioso encontrar trucos demorariamos 1 hora en busqueda mientras que aca en 20min tienes varias animaciones con CSS en un solo lugar :P

    ResponderEliminar
  2. Genial, sólo pondría una única pega. Quitaría el display: none; de la regla input[type="radio"] por

    position: absolute;
    clip: rect(1px,1px,1px,1px);

    Por eso de la accesibilidad. El resto genial.

    ResponderEliminar
  3. Gracias por el apunte, Emilio.

    Y un placer verte por aquí.
    Un saludo

    ResponderEliminar
  4. keep posted my friend...
    your content so unique ;)

    Beben Koben si Bloglang anu ganteng kalem tea \m/

    ResponderEliminar
  5. Beben Koben Thank you so much.

    ResponderEliminar
  6. Otra consulta, como hago si quiero poner un video en vez de una imagen?

    ResponderEliminar
  7. No acabo de entender bien tu pregunta.
    O mejor dicho, es tan obvio y hay tanta documentación sobre cómo incluir un vídeo en el html que creo que no es eso lo que quieres preguntar.

    Un ejemplo

    Un saludo

    ResponderEliminar
  8. Puedes reducir el css para todos los elementos que quieras que contengan las mismas propiedades y valores, así al momento de modificar el código te evitas editar una a una las propiedades y /o valores de cada elemento

    Es mas sencillo tener esto:
    input#nature:checked ~ figure img.nature,
    input#sport:checked ~ figure img.sport,
    input#cats:checked ~ figure img.cats,
    input#moda:checked ~ figure img.moda { width: 250px; }

    input#nature:checked ~ figure img:not(.nature),
    input#sport:checked ~ figure img:not(.sport),
    input#cats:checked ~ figure img:not(.cats),
    input#moda:checked ~ figure img:not(.moda) { opacity: 0; position: absolute; top: 0; left: 50%; }

    A tener esto:
    input#nature:checked ~ figure img.nature { width: 250px;}
    input#nature:checked ~ figure img:not(.nature) { opacity: 0; position: absolute; top: 0; left: 50%;}
    input#sport:checked ~ figure img.sport { width: 250px;}
    input#sport:checked ~ figure img:not(.sport) { opacity: 0; position: absolute; top: 0; left: 50%;}
    input#cats:checked ~ figure img.cats { width: 250px;}
    input#cats:checked ~ figure img:not(.cats) { opacity: 0; position: absolute; top: 0; left: 50%;}
    input#moda:checked ~ figure img.moda { width: 250px; }
    input#moda:checked ~ figure img:not(.moda) { opacity: 0; position: absolute; top: 0; left: 50%;}


    Y ambos códigos funciona igual, sólo que uno es más reducido y practico que el otro, saludos!

    ResponderEliminar
    Respuestas
    1. Por cierto... No habrá alguna forma de hacer que el id del input dependa de el nombre con el que se identifica la clase de la categoría o imagen a la que se está llamando?

      Acá un ejemplo de lo que trato de decir (probablemente mal estructurado)
      input([id]label):checked ~ figure img ([class] = input([id]label):checked){ width: 250px; }
      input([id]label):checked ~ figure img:not ([class] = input([id]label):checked) { opacity: 0; position: absolute; top: 0; left: 50%; }

      Eliminar
    2. Pregunte eso porque ayudaría a reducir el código aún más, y sería aún más practico, sería genial si existe alguna forma de hacerlo evitando el JS (no tengo problema con el JS, pero creo que sí puedo limitarme a usarlo es mucho mejor para el sitio, ya que corre con mayor fluidez)

      Eliminar
    3. Omite esto: "Por cierto... No habrá alguna forma de hacer que el id del input dependa de el nombre con el que se identifica la clase de la categoría o imagen a la que se está llamando?

      Acá un ejemplo de lo que trato de decir (probablemente mal estructurado)
      input([id]label):checked ~ figure img ([class] = input([id]label):checked){ width: 250px; }
      input([id]label):checked ~ figure img:not ([class] = input([id]label):checked) { opacity: 0; position: absolute; top: 0; left: 50%; }"

      Está mal :l revolví todo el código... Iré a organizar mis ideas xD pero sí de algún modo comprendiste lo que traté de decir y sabes como hacerlo, podrías decirlo? gracias

      Saludos

      Eliminar
    4. /************** 1 **************/
      Si estuviésemos en un entorno de producción real no cabría ninguna duda.

      Dicho lo cual, Jesús, quiero llamar tu atención sobre dos detalles:
      1º: fecha del artículo y de la demo.
      2º: carácter del blog

      Ambos creo que son relevantes, pues es una página principalmente divulgativa y fue publicado hace 2 años (inicios de 2013). momento en que este tipo de desarrollo era más bien escaso y desconocido. Así que posíblemente primé otros aspectos frente al que mencionas.

      /************** 2 **************/

      Busca información sobre la propuesta intermitente del combinador de referencia /for/

      Eliminar
  9. Muchas gracias por el gran aporte, una pregunta como incluir a la imagen un lightbox para ver la imagen en su tamaño original? espero que haya una solución... Gracias.

    ResponderEliminar
    Respuestas
    1. Si lo que buscas es realizarlo en puro Css quizás quieras intentar combinar esta demo con la del artículo "Esto es todo, amigos. Lightbox puro Css o la del post "De icono a pantalla completa. Estudio para una landing page"

      Ya nos contarás.

      Un saludo

      Eliminar
    2. Saludos especiales, gracias por compartir.. que buena programación, ordenada, corta y efectiva.

      Eliminar
    3. Amigos quisiera que de primer plano me muestre todas las imágenes y se ahi realizar la selección por filtro.
      Gracias, quedo atendo. correo: arlington.vargas4@gmail.com.

      Eliminar
    4. Nota del Editor:
      Este blog ni ha ofrecido ni da ayuda "a la carta" por otros medios que no sean los propios comentarios del blog.
      Eso podría ser considerado trabajos de consultoría y asesoría.
      Actividad totalmente distinta a la divulgación pública y gratuita que se hace desde el blog.


      /*++++++++~~~~~~++++++++*/

      Dicho lo cuál, Arlington como su consulta cae más dentro de lo que es Html que Css le voy a orientar en la "búsqueda del tesoro":
      El atributo checked y los valores admitidos por él.

      Un saludo

      Eliminar

EsCss RSS del Blog RSSS Comentarios Humans.txt ᛯ Diseno por Kseso SiteMap