Pseudoclases y Combinadores CSS
Pseudoclases y Combinadores CSS
Selector hijo > #page > div { } Se aplican estilos a elementos hijos directos.
Selector hermano + div + div { } Se aplican estilos a elementos que siguen a otros.
adyacente
Selector hermano general ~ div ~ div { } Se aplican estilos a elementos al mismo nivel.
En los siguientes apartados, veremos varios ejemplos gráficos sobre un supuesto ejemplo de documento
HTML, dibujado en forma de árbol esquemático. Así sabremos que elementos están dentro de otros y
nos será más fácil entender cada uno de los combinadores CSS.
Agrupación de selectores
En muchas ocasiones nos ocurrirá que tenemos varios bloques CSS con selectores diferentes pero con
los mismos estilos exactamente, algo que generalmente no es apropiado. Si esto ocurre a menudo, el
tamaño del documento CSS ocupará más y tardará más en descargarse:
.container-logo {
border-color: red;
background: white;
}
.container-alert {
border-color: red;
background: white;
.container-warning {
border-color: red;
background: white;
Una buena práctica es ahorrar texto y simplificar nuestro documento CSS lo máximo posible, por lo
que podemos hacer uso de la agrupación CSS utilizando la , (coma).
De esta forma, podemos pasar de tener el ejemplo anterior, a tener el siguiente ejemplo (que es
totalmente equivalente), donde hemos utilizado la agrupación para decirle al navegador que aplique
dichos estilos las diferentes clases:
.container-logo, .container-alert, .container-warning {
border-color: white;
background: red;
Al margen de esto, dos buenas prácticas que podríamos aplicar en esta situación serían las siguientes:
■ Legibilidad por delante: CSS por si sólo puede ser difícil de leer y mantener. Aunque a priori
puede parecer que es mejor poner la lista de selectores uno detrás de otro, la experiencia nos
dicta que deberíamos separarlos en una línea diferente cada selector. Esto lo hace
tremendamente más legible a la hora de revisar código CSS.
.container-logo,
.container-warning {
border-color: white;
background: red;
}
Consejo: Esto puede parecer poco importante a priori, pero a medida que avanzamos con nuestro
diseño, los documentos CSS se hacen tremendamente grandes y difíciles de mantener, por lo que cuanto
más sencillos sean, mejor.
Selector descendiente
En CSS podemos utilizar lo que se llama el selector descendiente, que no es más que una forma de
seleccionar ciertos elementos que están dentro de otros elementos. Esto
puede parecer sencillo, pero cuidado, ya que puede ser una fuente de problemas si no se entiende bien.
Su sintaxis se basa en colocar los elementos uno a continuación de otro, separado por un espacio:
div#pagina div {
background-color: blue;
En el ejemplo anterior, aplicamos los estilos CSS (color azul de fondo) a todos los elementos <div> que
estén dentro de un <div> con ID pagina. De esta forma, si existe un elemento <div> fuera del <div>
con id pagina, no se aplicarán los estilos indicados:
■ Se están seleccionando todos los elementos <div> que están dentro de <div> con ID pagina.
■ Observa que se seleccionan independientemente del nivel al que estén (hijos, abuelos, ...)
■ En este caso, el div de div#pagina es innecesario, ya que habíamos dicho que los IDs no se
pueden repetir. Si ya existe un elemento con ID pagina, no hace falta diferenciarlo también por
etiqueta. Si se tratase de una clase, si podría usarse.
Se pueden construir selectores muy complejos con tantos elementos como se quiera, pero una buena
práctica es mantenerlos simples. Cuántos más elementos descendientes existan en un selector, más
complejo será el procesamiento de dicha regla por los navegadores. Lo recomendable es ser despierto y
utilizar sólo los necesarios.
<div class="menu">
<div class="options">
<ul>
</ul>
</div>
</div>
Observando el fragmento de código HTML anterior, veamos las siguientes 2 formas de aplicar estilos CSS a los enlaces <a>:
/* Forma 1 */
.menu .options ul li a {
color: orange;
/* Forma 2 */
.menu a {
color: orange;
Mientras que la primera es mucho más específica, es una muy buena práctica en CSS mantener los
selectores lo menos específicos posibles para evitar problemas de Especificidad (a.k.a. CSS Peter
Griffin):
Selector hijo
Aunque el selector descendiente es bastante interesante, nos puede interesar hacer la misma operación,
pero en lugar de seleccionar todos los elementos descendientes, seleccionar sólo los descendientes
directos del elemento con el símbolo >, descartando así nietos y sucesivos.
#pagina > div {
background-color: blue;
}
Al contrario que en el caso anterior, no se seleccionan todos los elementos <div> descendientes, sino
solo aquellos que son hijos directos del primer elemento especificado.
Es posible también hacer referencia a los elementos hermanos, es decir, aquellos elementos que están
directamente a continuación del elemento especificado. Mediante el símbolo + del selector hermano
adyacente, se pueden seleccionar aquellos elementos hermanos que están seguidos el uno de otro (en el
mismo nivel):
[Link] span + span {
color: blue;
Cómo se podrá ver en este nuevo ejemplo, este combinador CSS hará que se seleccionen los elementos
span que estén a continuación de un [Link] span:
Obsérvese que el primer elemento <span> no es seleccionado, puesto que es el que estamos tomando de
base. Una buena forma para entenderlo es leerlo de la siguiente forma: «todo elemento <span> que esté
inmediatamente precedido de un <span>».
Si pensamos otras opciones en el ejemplo anterior, es posible que necesitemos ser menos específicos y
en lugar de querer seleccionar los elementos hermanos que sean adyacentes, queramos seleccionar
todos los hermanos en general, sin necesidad de que sean adyacentes. Esto se puede conseguir con el
selector hermano general, simbolizado con el carácter ~:
Como se ve en el ejemplo, no es necesario que el elemento strong se encuentre adyacente al primero,
sino que basta con que sean hermanos en el mismo nivel.
Selector universal
Por último, el selector universal se simboliza con un asterisco * y es la forma de aplicar ciertos estilos
en TODOS Y CADA UNO de los elementos HTML correspondientes.
Este ejemplo selecciona todos los elementos dentro de div#menu. Es importante recalcar la diferencia
de seleccionar #menu, a seleccionar todos los elementos dentro de #menu, que es lo que estamos
haciendo en este caso.
El selector universal puede ser muy útil en algunos casos para resetear ciertas propiedades de todo un
documento, como en el siguiente ejemplo, donde se eliminan los márgenes de todos los elementos del
documento HTML, puesto que algunos navegadores ponen márgenes diferentes y esto puede producir
ciertas inconsistencias en los diseños:
/* Elimina márgenes y rellenos de todos los elementos de un documento HTML */
*{
margin: 0;
padding: 0;
Las pseudoclases se utilizan para hacer referencia a ciertos comportamientos de los elementos HTML.
Así como los combinadores CSS se utilizan para dar estilos dependiendo de donde estén colocados en la
estructura del HTML, las pseudoclases se utilizan para dar estilos a elementos respecto al
comportamiento que experimentan en determinado momento.
Pseudoclases de enlaces
Existen algunas pseudoclases orientadas a los enlaces o hipervínculos. En este caso, permiten cambiar
los estilos dependiendo del comportamiento del enlace:
Pseudoclase Descripción
A continuación veremos un ejemplo donde seleccionamos mediante un simple selector a los enlaces que
aún no han sido visitados, cambiando el color de los mismos o su formato, lo que mostrará dichos
enlaces de color verde y en negrita:
a:link {
color: green;
font-weight: bold
Por otro lado, la pseudoclase :visited puede utilizarse para dar estilo a los enlaces que hayan sido
visitados previamente en el navegador del usuario:
a:visited {
color: purple;
font-weight: bold
Pseudoclases de ratón
Originalmente, las siguientes pseudoclases se utilizaban solamente en enlaces (Internet Explorer no los
soportaba en otros elementos). Sin embargo, actualmente pueden ser utilizadas con seguridad en
cualquier otro elemento, sin necesidad de ser <a>.
Pseudoclase Descripción
:hover Aplica estilos cuando pasamos el ratón sobre un elemento.
La primera de ellas, :hover, es muy útil e interesante, ya que permite aplicar estilos a un elemento justo
cuando el usuario está pasando el ratón sobre él. Es una de las pseudoclases más utilizadas:
/* Usuario mueve el ratón sobre un enlace */
a:hover {
background-color: cyan;
padding: 2px
/* Usuario mueve el ratón sobre un div y resalta todos los enlaces que contiene */
div:hover a {
background-color: steelblue;
color: white;
Obsérvese que podemos realizar acciones un poco más específicas, como el segundo ejemplo anterior,
donde al movernos sobre un elemento div (div:hover), aplicaremos los estilos a los enlaces (a) que están
dentro del mencionado div.
Por otro lado, la segunda pseudoclase, :active, permite resaltar los elementos que se encuentran activos,
donde el usuario está pulsando de forma activa con el ratón:
a:active {
padding: 2px
Nota: Aunque las pseudoclases anteriores se inventaron para interactuar con un ratón en un sistema de
escritorio, pueden funcionar en dispositivos táctiles. Aún así, ten en cuenta que, por ejemplo, el :hover
no tiene mucho sentido en dispositivos móviles, ya que, aunque podría hacerlo, un usuario no navega
por móvil arrastrando el dedo por la pantalla.
Pseudoclases de interacción
Existen pseudoclases orientadas principalmente a los campos de formulario de páginas webs y la
interacción del usuario con ellos, veamos otro par interesante:
Pseudoclase Descripción
Cuando estamos escribiendo en un campo de texto de un formulario de una página web, generalmente
pulsamos TAB para cambiar al siguiente campo y SHIFT+TAB para volver al anterior. Cuando estamos
posicionados en un campo se dice que ese campo tiene el foco, mientras que al pulsar TAB y saltar al
siguiente, decimos que pierde el foco.
input:focus {
Nota: Aunque estas pseudoclases suelen utilizarse con elementos de formularios como <input>,
también pueden utilizarse con otros elementos, como por ejemplo los enlaces <a>. Esta es una excelente
oportunidad para personalizar el estilo de los campos de texto de un formulario (<input> y <textarea>)
mientras el usuario escribe y se mueve por ellos.
Por otro lado, la pseudoclase :checked permite aplicar el estilo especificado a los elementos <input>
(casillas de verificación o botones de radio) u <option> (la opción seleccionada de un <select>).
Por ejemplo, se podría utilizar el siguiente fragmento de código:
input:checked + span {
color: green;
Este ejemplo añade el selector hermano + para darle formato al <span> que contiene el texto y se
encuentra colocado a continuación de la casilla <input>. De esta forma, los textos que hayan sido
seleccionados, se mostrarán en verde.
Pseudoclases de activación
Por norma general, los elementos de un formulario HTML están siempre activados, aunque se pueden
desactivar añadiendo el atributo disabled (es un atributo booleano, no lleva valor) al elemento HTML
en cuestión. Esto es una práctica muy utilizada para impedir al usuario escribir en cierta parte de un
formulario porque, por ejemplo, no es aplicable.
Existen varias pseudoclases para detectar si un campo de un formulario está activado o desactivado:
Pseudoclase Descripción
Utilizando las dos primeras pseudoclases, bastante autoexplicativas por si solas, podemos seleccionar
elementos que se encuentren activados (comportamiento por defecto) o desactivados:
/* Muestra en fondo blanco las casillas que permiten escribir */
input:enabled {
background-color: white;
input:disabled {
background-color: grey;
Por otro lado, las pseudoclases read-only y read-write nos permiten seleccionar y diferenciar
elementos que se encuentran en modo de solo lectura (tienen especificado el atributo readonly en el
HTML) o no:
input:read-only {
background-color: darkred;
color: white
}
En el ejemplo anterior, la pseudoclase :read-only le da estilo a aquellos campos <input> de un
formulario que están marcados con el atributo de sólo lectura readonly. La diferencia entre un campo
con atributo disabled y un campo con atributo readonly es que la información del campo con readonly
se enviará a través del formulario, mientras que la del campo con disabled no se enviará. Aún así,
ambas no permiten modificar el valor.
Nota: Ten en cuenta que :read-only aplicará los estilos a todos los elementos HTML que no puedan ser
modificados por el usuario.
Por otro lado, la pseudoclase :read-write es muy útil para dar estilos a todos aquellos elementos que
son editables por el usuario, sean campos de texto <input> o <textarea>.
input:read-write {
background-color: green;
color: white
Nota: La pseudoclase read-write da estilo también a elementos HTML que contengan el atributo
contenteditable, como por ejemplo un párrafo editable por el usuario con dicho atributo.
Pseudoclases de validación
En un formulario HTML es posible establecer un campo obligatorio que será necesario rellenar para
enviar el formulario. Por ejemplo, el DNI de una persona que va a matricularse en un curso, o el nombre
de usuario de alta en una plataforma web para identificarse. Campos que son absolutamente necesarios.
Para hacer obligatorios dichos campos, tenemos que indicar en el HTML el atributo required, al cuál
será posible darle estilo mediante la pseudoclase :required:
input:required {
Por otra parte, los campos opcionales (no obligatorios, sin el atributo required) pueden seleccionarse
con la pseudoclase :optional:
input:optional {
Las validaciones en formularios HTML siempre han sido un proceso tedioso, hasta la llegada de
HTML5. HTML5 brinda un excelente soporte de validaciones desde el lado del cliente, pudiendo
comprobar si los datos especificados son correctos o no antes de realizar las validaciones en el lado del
servidor, y evitando la latencia de enviar la información al servidor y recibirla de vuelta.
Ojo: Ten en cuenta que la validación de cliente es apropiada solo para reducir la latencia de
envío/recepción al servidor, pero nunca como estrategia para evitar problemas de seguridad o similares,
para la cuál se debe tener validación en el servidor siempre. Las validaciones utilizadas en frontend, es
posible falsearlas o saltárselas.
Imaginemos un campo de entrada en el que queremos obtener la edad del usuario. Nuestra intención es
que solo se puedan introducir números. Para ello hacemos uso de la expresión regular [0-9]+, que
significa «una o más cifras del 0 al 9»:
<input type="text" name="age" pattern="[0-9]+" />
Sin embargo, el atributo pattern permite expresiones regulares realmente complejas, como por ejemplo,
una expresión regular para validar el formato de un DNI, ya sea en el formato nacional de España
(12345678L) o en formato NIE (X1234567L), aceptando guiones si se indican:
<input type="text" name="dni"
pattern="(([X-Z]{1})([-]?)(\d{7})([-]?)([A-Z]{1}))|((\d{8})([-]?)([A-Z]{1}))" />
Se pueden aplicar ciertos estilos dependiendo de si se cumple o no el patrón de validación, utilizando las
siguientes pseudoclases:
input:invalid {
background-color: darkred;
color: white;
input:valid {
background-color: green;
color: white;
Sin embargo, en la validación numérica que vimos anteriormente, un usuario podría escribir 500, que es
una edad imposible, porque en el patrón de validación indicamos «una o más cifras del 0 al 9». Lo ideal
sería establecer un rango, algo que se suele hacer muy a menudo si tenemos campos numéricos de
formulario:
<input type="number" name="age" min="18" max="100" />
Este campo permite al usuario especificar su edad, utilizando los atributos de validación min y max,
que sólo permiten valores entre 18 y 100 años. Los valores fuera de este rango, no serán válidos.
De la misma forma que antes, es posible aplicar estilos para los valores fuera de rango, como dentro de
rango:
input:out-of-range {
background-color: darkred;
color: white;
input:in-range {
background-color: green;
color: white;
}
Pseudoclases de negación
Existe una pseudoclase muy útil, denominada pseudoclase de negación. Permite seleccionar todos los
elementos que no cumplan los selectores indicados entre paréntesis.
Veamos un ejemplo:
p:not(.general) {
padding: 8px;
background: #FFF;
Este pequeño fragmento de código nos indica que todos los párrafos (elementos <p>) que no
pertenezcan a la clase general, se les aplique el estilo especificado.
Consejo: Las reglas de negación pueden ser complejas, ineficientes y poco escalables. Intenta utilizarlas
sólo en los casos que sea absolutamente necesario.
Otras pseudoclases
Para finalizar el apartado de pseudoclases, quiero mencionar algunas que no encajan en los apartados
anteriores, pero que pueden ser muy útiles en algunos casos:
Pseudoclase Significado
:dir(A) Experimental. Aplica estilo al elemento que coincide con la dirección ltr o rtl.
:indeterminate Experimental. Aplica estilo a la casilla checkbox o al elemento <progress> sin definir.
:fullscreen Experimental. Aplica estilo si la página está en el modo de pantalla completa.
Otras pseudoclases como :first, :left, :right o :blank las mencionamos en el capítulo de medios
paginados.
Existen varias pseudoclases que permiten hacer referencias a los elementos del documento HTML
según su posición y estructura de los elementos hijos. A continuación muestro un pequeño resumen
de estas pseudoclases:
Pseudoclase Descripción
Para ello, volvamos a utilizar una estructura en forma de árbol para ver cómodamente la ubicación de
cada uno de los elementos.
Las dos primeras pseudoclases, :first-child y :last-child hacen referencia a los primeros y últimos
elementos (al mismo nivel) respectivamente.
strong:first-child {
background-color:cyan;
strong:last-child {
background-color:green;
}
Sin embargo, si no queremos quedarnos en los primeros o últimos elementos y necesitamos más
potencia para elegir, podemos hacer uso de la pseudoclase :nth-child(A), que permite especificar el
elemento deseado, simplemente estableciendo su número en el parámetro A:
A continuación puedes comprobar los valores de la tabla anterior de un modo más visual y práctico,
estableciendo en el campo de texto valores como n, n+2, 2n, 2n-1 (o similares) y observando los
resultados.
:nth-child()
Pseudoclase Descripción
Las pseudoclases :first-of-type y :last-of-type son las equivalentes a :first-child y :last-child pero sólo
teniendo en cuenta elementos del mismo tipo. Por otro lado, la pseudoclase :nth-of-type(A) es la
equivalente a :nth-child(A) y :nth-last-of-type(A) es la equivalente a :nth-last-child(A). Veamos un
ejemplo sobre el ejercicio anterior:
En este ejemplo, se puede ver como :nth-of-type(2) selecciona el segundo elemento strong en ambos
casos, a pesar de que en el primero ocupa la tercera posición. En este caso se selecciona porque es el
segundo elemento de su mismo tipo (<strong>).
Por otro lado, :nth-last-of-type(A) hace una selección de forma inversa, empezando por el último
elemento.
Hijos únicos
Existen también varias pseudoclases para la gestión de hijos únicos. Son las siguientes:
Pseudoclase Descripción
La propiedad :only-child nos proporciona un método para aplicar estilo a aquellos elementos que sean
el único hijo de su elemento padre. Además, como ha ocurrido anteriormente, también existe la
pseudoclase :only-of-type que es equivalente al anterior pero sólo para elementos del mismo tipo, es
decir, que puede ser que no sea el único elemento hijo, pero sí el único de su tipo.
Muy relacionada está también la pseudoclase :empty, que permite seleccionar los elementos que estén
vacíos. Ojo con esto, ya que un elemento que contenga comentarios HTML <!-- --> la pseudoclase
:empty lo detectará como vacío, pero si contiene espacios en blanco, no.
Al igual que las pseudoclases, los pseudoelementos son otra de las características de CSS que permiten
hacer referencias a «comportamientos virtuales no tangibles», o lo que es lo mismo, se le puede dar
estilo a elementos que no existen realmente en el HTML, y que se pueden generar desde CSS.
Recordemos la sintaxis de los pseudoelementos, que está precedida de dos puntos dobles (::) para
diferenciarlos de las pseudoclases, las cuales sólo tienen dos puntos (:). No obstante, este cambio surgió
posteriormente, por lo que aún hoy en día es frecuente ver fragmentos de código con pseudoelementos
con la sintaxis de pseudoclase con un solo par de puntos :.
Generación de contenido
Dentro de la categoría de los pseudoelementos CSS, como punto central, se encuentra la propiedad
content. Esta propiedad se utiliza en selectores que incluyen los pseudoelementos ::before o ::after,
para indicar que vamos a crear contenido antes o después del elemento en cuestión:
Propiedad/Pseudoelemento Descripción
Por otro lado, los pseudoelementos ::before y ::after permiten hacer referencia a «justo antes del
elemento» y «justo después del elemento», respectivamente. Así, se podría generar información
(usualmente con fines decorativos) que no existe en el HTML, pero que por circunstancias de diseño
sería apropiado colocar:
q::before {
content: "«";
color: #888;
q::before {
content: "»";
color: #888;
Los ejemplos anteriores insertan el carácter « antes de las citas indicadas con el elemento HTML <q> y
el carácter » al finalizar la misma, ambas de color gris.
Atributos HTML
Es interesante recalcar la utilidad de la expresión attr(), que en lugar de generar el contenido textual que
le indiquemos, permite recuperar esa información del valor del atributo HTML especificado. Veamos
un ejemplo para clarificarlo, concatenándolo con texto:
a::after {
}
Este pequeño ejemplo muestra a continuación de todos los enlaces la URL literalmente, dentro de dos
paréntesis. Esto puede ser realmente útil en una página de estilos que se aplica a una página en el
momento de imprimir, en los cuales se pierde la información del enlace al no ser un medio interactivo.
Truco: También se puede utilizar la expresión url() para añadir una imagen al contenido generado, tal y
como lo hacemos en la propiedad background, por ejemplo.
También existen pseudoelementos con los que podemos hacer referencia a la primera letra de un texto.
Para ello utilizamos el pseudoelemento ::first-letter, así como el pseudoelemento ::first-line si
queremos hacer referencia a la primera línea de un texto. De esta forma, podemos dar estilo a esas
secciones concretas del texto:
Pseudoelemento Descripción
p{
color: #333;
font-size: 16px;
p::first-letter {
color: black;
font-size: 42px;
p::first-line {
color: #999;
}
Esto puede darnos la posibilidad de dar formato a un texto con ciertas propiedades, como cuentos
clásicos:
Existe también un pseudoelemento para hacer referencias a los signos o marcas de la listas (<ol> o
<ul>), en el caso de que queramos que tengan, por ejemplo, un color diferente al del texto de la lista.
Se aplican a los elementos <li> de los ítems de una lista. Veamos un ejemplo:
ul ::marker {
color: green;
Esto mostraría el texto de la lista con el color habitual que tenga (por ejemplo, negro), pero los signos
que preceden a cada ítem de la lista, aparecerían en color verde. Hay que tener cuidado, puesto que el
soporte de esta característica aún no es muy bueno.
Otros pseudoelementos
::input-placeholder Aplica estilos a los textos de sugerencia de los campos de entrada. Soporte
Algunas de las propiedades que veremos no están definidas por completo, sólo son borradores o pueden
variar en la especificación definitiva, por lo que los navegadores las implementan utilizando una serie de
vendor prefixes (prefijos por navegador), que facilitan la segmentación de funcionalidades.
De esta forma, podemos utilizar varios prefijos para asegurarnos que aunque dichas funcionalidades
tengan un comportamiento o sintaxis diferente en cada navegador, podemos hacer referencia a cada una
de ellas por separado:
div {
En el ejemplo anterior, la propiedad transform se refiere a los navegadores que tengan implementada la
especificación definitiva por completo e ignorará el resto de propiedades. Por otro lado, otro navegador
(o el mismo en una versión más antigua) puede tener implementada una versión anterior a la definitiva,
por lo que hará caso a las propiedades con un prefijo concreto.
Debido al ritmo y la rápida velocidad de Internet en estas cuestiones, es muy complicado obtener una
lista de funcionalidades implementadas en cada navegador, algo que puede variar incluso en cuestión de
semanas. Aconsejo utilizar la página Can I Use, una web colaborativa para saber el estado actual, previo
e incluso futuro de las propiedades CSS o elementos HTML en cada navegador.
En esta página se puede buscar, a través de un buscador y de forma rápida y cómoda, el estado de ciertas
características por parte de las diferentes versiones de los navegadores.
Actualmente, los vendor prefixes están en proceso de desaparecer. Las principales compañías de
navegadores han optado por favorecer el uso de flags en el navegador del usuario para activar o
desactivar opciones experimentales o crear especificaciones más pequeñas y breves que puedan ser
estables mucho más rápido. Por esta razón, se aconseja utilizar vendor prefixes solo cuando necesitas
soporte específico en navegadores muy antiguos.
En el caso de querer utilizar vendor prefixes*, recomiendo encarecidamente utilizar sistemas como
autoprefixer (el más popular, que forma parte de PostCSS) o prefix-free que añaden de forma
automática y transparente los prefijos, basándose en información de herramientas como Can I Use.
Busca extensiones en el editor que utilices o la opción para activarlas, ya que te ahorrará mucho tiempo
y te permitirá tener un código más legible y modular al no tener que repetir código.
En CSS aparecen uno de los aspectos más interesantes de la web interactiva: las transiciones. En
versiones anteriores de CSS sólo se podían utilizar ciertas funcionalidades interactivas con pseudoclases
como :hover o :focus. Sin embargo, dichas transiciones ocurrían de golpe, pasando de un estado inicial
a otro final. Mediante las transiciones, tenemos a nuestra disposición una gran flexibilidad que nos
permitirá dotar de atractivos y elegantes efectos de transición que multiplicarán por mil las posibilidades
de nuestros diseños.
Las transiciones se basan en un principio muy básico, conseguir un efecto suavizado entre un estado
inicial y un estado final. Las propiedades relacionadas que existen son las siguientes:
Propiedades Valor
transition-duration 0|
transition-delay 0|
En primer lugar, la propiedad transition-property se utiliza para especificar la propiedad a la que que
afectará la transición. Podemos especificar la propiedad concreta (width o color, por ejemplo) o
simplemente especificar all para que se aplique a todos los elementos con los que se encuentre. Por otro
lado, none hace que no se aplique ninguna transición.
Nota: Debes saber que no todos los elementos permiten animación debido a su complejidad. Por
ejemplo, los background-image de gradientes no son animables actualmente.
Si establecemos una duración demasiado grande, el navegador realizará la transición con detención
intermitentes, lo que hará que la transición vaya a golpes. Además, transiciones muy largas pueden
resultar molestas a muchos usuarios.
Función de tiempo
Una función de tiempo linear siempre es constante, mientras que ease comienza suavemente, continua
de forma más rápida y termina suavemente de nuevo. Ease-in y ease-out son variaciones que van más
lento al principio o al final, y ease-in-out una mezcla de las dos.
Cubic-Bezier()
La función de tiempo cubic-bezier() es una función personalizada, donde podemos darle unos valores
concretos depediendo de la velocidad que queramos que tenga la transición. En la última columna de la
tabla anterior podemos ver los valores equivalentes a cada una de las palabras clave mencionadas. En
principio, el formato de la función es cubic-bezier(A, B, C, D), donde:
background: #DDD;
color: #222;
padding: 2px;
a:hover {
background: #FFF;
color: #666;
transition-property: all;
transition-duration: 0.2s;
transition-timing-function: ease-in;
}
Truco: Si nos fijamos bien, este estilo se aplica sólo al mover el ratón sobre el enlace (transición de
entrada). Sin embargo, si movemos el ratón fuera del enlace, no se produce transición sino que realiza
el cambio de forma brusca. Si movemos las propiedades de transición al primer bloque, se aplicarán
tanto en las transiciones de entrada como en las de salida.
Atajo: Transiciones
Como siempre, podemos resumir todas estas operaciones en una propiedad de atajo denominada
transition. Los valores del ejemplo superior, se podrían escribir como se puede ver a continuación (si
no necesitas algún valor, se puede omitir):
div {
Una vez conocemos las transiciones CSS, es muy fácil adaptarnos al concepto de animaciones de CSS,
el cual amplia el concepto de transiciones convirtiéndolo en algo mucho más flexible y potente.
Las transiciones son una manera de suavizar un cambio de un estado inicial a un estado final. La idea de
las animaciones CSS parte del mismo concepto, permitiendo añadir más estados, pudiendo realizar
cambios desde un estado inicial, a un estado posterior, a otro estado posterior, y así sucesivamente.
Además, esto será posible de forma automática, sin que el usuario tenga que realizar una acción
concreta.
El primer paso para crear animaciones es tener dos cosas claras. Por un lado, utilizaremos la regla
@keyframes, que incluye los fotogramas de la animación. Por otro lado, tendremos que utilizar las
propiedades de las animaciones, que definen el comportamiento de la misma.
Para definir dicho comportamiento necesitamos conocer las siguientes propiedades, que son una
ampliación de las transiciones CSS:
Propiedades Valor
animation-duration 0|
animation-iteration-count 1 | infinite |
La propiedad animation-name permite especificar el nombre del fotograma a utilizar, mientras que las
propiedades animation-duration, animation-timing-function y animation-delay funcionan
exactamente igual que en el tema anterior de transiciones.
Valor Significado
Por defecto, cuando se termina una animación que se ha indicado que se reproduzca sólo una vez, la
animación vuelve a su estado inicial (primer fotograma). Mediante la propiedad animation-fill-mode
podemos indicar que debe mostrar la animación cuando ha finalizado y ya no se está reproduciendo; si
mostrar el estado inicial (backwards), el estado final (forwards) o una combinación de ambas (both).
Atajo: Animaciones
Nuevamente, CSS ofrece la posibilidad de resumir todas estas propiedades en una sola, para hacer
nuestras hojas de estilos más específicas. El orden de la propiedad de atajo sería el siguiente:
div {
Consejo: Mucho cuidado al indicar los segundos en las propiedades de duración. Al ser una unidad
diferente a las que solemos manejar (px, em, etc...) hay que especificar siempre la s, aunque sea un
valor igual a 0.
Fotogramas (keyframes)
Ya sabemos como indicar a ciertas etiquetas HTML que reproduzcan una animación, con ciertas
propiedades. Sin embargo, nos falta la parte más importante: definir los fotogramas de dicha animación.
Para ello utilizaremos la regla @keyframes, la cuál es muy sencilla de utilizar y se basa en el siguiente
esquema:
En primer lugar elegiremos un nombre para la animación (el cuál utilizamos en el apartado anterior, para hacer referencia a la animación, ya
que podemos tener varias en una misma página), mientras que podremos utilizar varios selectores para definir el transcurso de los
fotogramas en la animación.
.anim {
background: grey;
color: #FFF;
width: 150px;
height: 150px;
Los selectores from y to son realmente sinónimos de 0% y 100%, así que los modificaremos y de esta
forma podremos ir añadiendo nuevos fotogramas intermedios. Vamos a modificar el ejemplo anterior
añadiendo un fotograma intermedio e indentando, ahora sí, correctamente el código:
@keyframes changeColor {
0% {
50% {
width: 400px;
100% {
Las transformaciones es uno de los elementos más interesantes que se introducen en CSS3 para
convertir el lenguaje de hojas de estilo en un sistema capaz de realizar todo tipo de efectos visuales,
incluido 2D y 3D. Las propiedades principales para realizar transformaciones son las siguientes:
transform función1, función2, ... Aplica una o varias funciones de transformación sobre un elemento.
transform-origin Cambia el punto de origen del elemento en una transformación.
Comencemos por la propiedad transform, mediante la cual podemos indicar una o varias
transformaciones para realizar sobre un elemento, ya sean 2D (sobre dos ejes) o 3D (sobre tres ejes).
Funciones 2D
Existen múltiples propiedades CSS que ofrecen diferentes funcionalidades de transformación en dos
dimensiones, que veremos a continuación:
Translaciones
Las funciones de translación son aquellas que realizan una transformación en la que mueven un
elemento de un lugar a otro. Si especificamos un valor positivo en el eje X (horizontal), lo moveremos
hacia la derecha, y si especificamos un valor negativo, lo moveremos hacia la izquierda. Lo mismo con
el eje Y (vertical):
Funciones Significado
Escalado
Las funciones de escalado realizan una transformación en la que aumentan o reducen el tamaño de un
elemento, basándose en el parámetro indicado, que no es más que un factor de escala:
Funciones Significado
En este ejemplo, transform: scale(2, 2) realiza una transformación de escalado del elemento,
ampliándolo al doble de su tamaño original. Si utilizamos scale() con dos parámetros iguales, estamos
manteniendo la proporción del elemento, pero si utilizamos diferentes valores, acabaría deformándose.
Rotaciones
Funciones Significado
rotateX(xdeg) Establece una rotación 2D en xdeg grados sólo para el eje horizontal X.
rotateY(ydeg) Establece una rotación 2D en ydeg grados sólo para el eje vertical Y.
Con transform: rotate(5deg) realizamos una rotación de 5 grados del elemento sobre si mismo.
Utilizando rotateX() y rotateY() podemos hacer lo mismo respecto al eje X o el eje Y respectivamente.
Deformaciones
Por último, las funciones de deformación establecen un ángulo para torcer, tumbar o inclinar un
elemento en 2D:
Funciones Significado
Funciones 3D
Sin embargo, esto no es todo. A las funciones anteriores, también podemos añadir las funciones
equivalentes de CSS para hacer uso del eje Z, o lo que es lo mismo, las tres dimensiones o 3D. Basta
con utilizar el eje Z o las funciones específicas de 3D para poner estas animaciones en práctica.
Recordar siempre que el eje X es el eje horizontal, el eje Y es el eje vertical y el eje Z es el eje de
profundidad.
Funciones Significado
translate3d(x, y, z) Establece una translación 3D, donde aplica los parámetros de a cada eje.
scaleZ(fz) Reescala el elemento a un nuevo tamaño con factor fz de profundidad.
scale3d(fx, fy, fz) Establece un escalado 3D, donde aplica los factores a cada eje.
rotateZ(zdeg) Establece una rotación 2D en zdeg grados sólo para el eje de profundidad Z.
rotate3d(x, y, z, deg) Establece una rotación 3D, aplicando un vector [x, y, z] y el ángulo en deg.
0% {
100% {
.anim {
background: #000;
color: #FFF;
width: 100px;
Transformaciones múltiples
Recuerda que si estableces varias propiedades transform en el mismo elemento con diferentes
funciones de transformación, la segunda propiedad de transformación sobreescribirá a la anterior, como
lo haría cualquier propiedad de CSS:
div {
transform: rotate(5deg);
Para evitar este comportamiento, una forma sencilla se basa en emplear múltiples transformaciones
separándolas mediante un espacio. En el siguiente ejemplo, aplicamos una función de rotación, una
función de escalado y una función de traslación de forma simultánea:
div {
Si lo que queremos hacer no es posible realizarlo de esta forma, probablemente lo más apropiado sería
guardar los valores en atributos de metadatos como data-tx, data-ty, data-sx, data-sy y data-rz o
similares y manipulándolos desde Javascript.
El soporte de estas propiedades es muy bueno en el ecosistema de navegadores actual, por lo que puede
utilizarse con seguridad:
.anim {
background: grey;
color: #FFF;
width: 150px;
height: 150px;
Truco: Si tienes fotogramas que van a utilizar los mismos estilos que uno anterior, siempre puedes
separarlos con comas, por ejemplo: 0%, 75% { ... }, que utilizarían dichos estilos al inicio de la
animación y al 75% de la misma.
Encadenar animaciones
Es posible encadenar múltiples animaciones, separando con comas las animaciones individuales y
estableciendo un tiempo de tardo a cada animación posterior:
.animated {
animation:
En este caso, lo que hemos hecho es aplicar varias animaciones a la vez, pero estableciendo un retardo
(cuarto parámetro) que es la suma de la duración de las animaciones anteriores. De esta forma,
encadenamos una animación con otra.
Por lo tanto, en la actualidad, cuando diseñamos una web, esta debe estar preparada para verse
correctamente en diferentes resoluciones, cosa que, a priori no es sencilla. Antiguamente, se llegó al
punto de preparar una web diferente dependiendo del dispositivo o navegador que utilizaba el usuario,
pero era algo que se terminó descartando, ya que no era práctico.
Por suerte, esos tiempos han quedado atrás, y la máxima que se sigue hoy es diseñar una sola web, que
se adapte visualmente al dispositivo utilizado.
Hoy en día se le denomina Responsive Web Design (o RWD) a los diseños web que tienen la capacidad
de adaptarse al tamaño y formato de la pantalla en la que se visualiza el contenido, respecto a los
diseños tradicionales en los que las páginas web estaban diseñadas sólo para un tamaño o formato
específico, y no tenían esa capacidad de adaptación.
Aunque en principio el concepto de web adaptativa es muy sencillo de comprender, aplicarlo puede ser
todo un quebradero de cabeza si no se conocen bien las bases y se adquiere experiencia. En
[Link] puedes encontrar algunos ejemplos de páginas que utilizan Responsive Web Design para
tener clara la idea.
Conceptos básicos
En el excelente artículo 9 basic principles of responsive web design, de Froont, hay una estupenda
explicación visual de algunos conceptos básicos necesarios para entender correctamente el Responsive
Web Design. Son los siguientes:
El primero de ellos es la diferencia entre diseño responsivo y diseño adaptativo. Como se puede ver en
la imagen a continuación, un diseño responsive responde (valga la rebuznancia) en todo momento a las
dimensiones del dispositivo, mientras que un diseño adaptable es aquel que se adapta, pero no
necesariamente responde en todo momento:
Veremos que esto puede ser la diferencia entre aplicar correctamente conceptos como media queries,
porcentajes y propiedades de ancho máximo y mínimo, que veremos más adelante.
Por otro lado, para trabajar correctamente en diseños responsive hay que tener en cuenta que debemos
trabajar con unidades relativas e intentar evitar las unidades fijas o estáticas, las cuales no responden a la
adaptación de nuestros diseños flexibles:
Otra forma interesante de trabajar esa respuesta de los diseños responsive es utilizar propiedades como
min-width o max-width, donde definimos tamaños mínimos o máximos, para que los elementos de
nuestra página puedan ampliar o reducirse según sea necesario dependiendo de la pantalla del
dispositivo utilizado.
Con estas propiedades podemos crear diseños que aprovechen al máximo toda la pantalla de
dispositivos pequeños (como móviles o tablets), mientras que establecemos unos máximos en pantallas
de dispositivos grandes, para crear unos espacios visuales que hacen que el diseño sea más agradable:
Otro concepto, que a la misma vez es una característica muy atractiva en nuestros diseños responsive es
la de mantener el flujo de los elementos cuando cambian de tamaño y evitar que estos se solapen unos
con otros.
Si estamos habituados a trabajar en diseños más estáticos que no están preparados para móviles, suele
ser duro hacer ese cambio. Sin embargo, una vez lo conseguimos, todo resulta mucho más fácil y
conseguiremos transmitir una buena respuesta y fluidez visual:
Esto último va muy de la mano del sistema habitual de recolocación de elementos que se suele seguir en
los diseños Responsive Design. Como se puede ver en la siguiente imagen, en un diseño responsive se
utilizan ciertos «puntos de control».
Por ejemplo, se suele pensar que en una resolución de escritorio queremos mostrar la información
dentro de una cuadrícula (grid) de 4 ó 5 celdas de ancho, mientras que en la versión de tablet será sólo
de 3 celdas de ancho (el resto se desplazará a la siguiente fila) y en móviles será una sola celda de
ancho, mostrándose el resto de celdas haciendo scroll hacia abajo:
Esta forma de trabajar nos proporciona múltiples ventajas:
■ Es mucho más sencillo mostrar la misma información desde diseños de pantalla grande.
Antes de comenzar a crear un diseño web preparado para móviles, es importante tener claro ciertos
detalles:
Por último, es aconsejable decidirse por una estrategia de diseño antes de comenzar. Aunque existen
otras estrategias, las dos vertientes principales más populares son las siguientes:
Estrategia Descripción
Mobile first Primero nos enfocamos en dispositivos móviles y luego pensamos en otros.
Desktop first Primero nos enfocamos en dispositivos de escritorio, y luego pensamos en otros.
La estrategia Mobile-first es la que utilizan los diseñadores de sitios webs en las que su público
objetivo es mayoritariamente usuario de móvil. Ejemplos como una web para comprar billetes de
transporte, la web de un juego o aplicación móvil o una web para pedir cita en un restaurante podrían
ser, a priori, una buena elección para utilizar Mobile-first.
Esta estrategia hace que el desarrollo en escritorio sea muy sencillo, ya que se reduce a tener un diseño
de móvil en escritorio e ir añadiendo nuevas secciones o partes para «completar» el diseño en
resoluciones grandes.
Por otro lado, la estrategia Desktop-first suele interesar más a los diseñadores de sitios webs en las que
el público objetivo son usuarios de escritorio. Por ejemplo, una página de una aplicación para PC/Mac o
similares, podría ser una buena opción para la estrategia Desktop-first. En ella, hacemos justo lo
contrario que en la anterior, lo primero que diseñamos es la versión de escritorio, y luego vamos
descargando detalles o recolocando información hasta tener la versión para dispositivos móviles.
Como explicamos en el capítulo anterior, hay ciertos conceptos que hay que tener claros antes de
comenzar con el Responsive Design. En esta sección vamos a ver como llevarlos a la práctica con
código.
Nota: Al comenzar, algunos diseñadores tienen una percepción incorrecta de que los porcentajes toman
el tamaño dependiendo de lo que mide la ventana del navegador. Realmente los porcentajes dependen
siempre del tamaño del elemento padre que los contiene. Si queremos basarnos en el tamaño del
navegador, hay que usar unidades de viewport.
Podemos comenzar usando porcentajes con las propiedades width en un ejemplo sencillo. Si
establecemos un ancho de 100% (valor por defecto en elementos de tipo block, no hace falta indicarlo)
a los elementos grises que vemos a continuación (#header, #page y #footer), un 30% al azul (#menu) y
un 70% al gris claro (#content) podríamos obtener este diseño:
El código utilizado sería algo parecido a lo siguiente:
<div id="header"></div>
<div id="page">
<div id="menu"></div>
<div id="content"></div>
</div>
<div id="footer"></div>
Nótese que los elementos #menu y #content se encuentran dentro de #page. Tengan en cuenta que,
estamos utilizando id en este ejemplo, aunque habíamos comentado que lo ideal quizás sería utilizar
clases.
Por su parte, el código CSS tendría esta pinta:
div {
min-height: 200px;
background: grey;
#menu, #content {
display: inline-block;
#menu {
background: blue;
width: 30%;
}
#content {
background: lightgrey;
width: 70%;
Sin embargo, utilizar porcentajes no nos garantiza un diseño adaptativo de calidad, hay que comprender
otros detalles. El primer problema que encontraremos será que si sumamos el tamaño de los elementos
(70% + 30%) junto a los bordes (2px por cada lado), la suma es superior al 100% del contenedor padre,
por lo que no cabe en su interior y el segundo elemento se desplaza a la zona inferior, descuadrando
todo el diseño. Lo mismo puede ocurrir si intentamos añadir margin o padding. Esto es algo muy
habitual en CSS. Y frustrante al principio.
Hay varias formas de solucionar esto:
■ Eliminar los bordes y reducir los porcentajes hasta que quepan en el 100% del padre.
■ Usar box-sizing: border-box para cambiar el modo en el que se gestionan los tamaños.
#menu, #content {
display: inline-block;
/* Añadimos este */
#page {
display: flex;
De esta forma, conseguimos que nuestro diseño se adapte de forma adecuada a la página, sin necesidad
de tener que ajustar los márgenes, rellenos, bordes o tamaño de los contenidos.
max-width: 1024px;
min-width: 800px;
}
En este caso, el elemento tiene un tamaño máximo de 1024 píxeles, y un tamaño mínimo de 800 píxeles,
por lo que si ajustamos el ancho de la ventana del navegador, dicho elemento iría variando en un rango
de 800 a 1024 píxeles, nunca haciéndose más pequeño de 800 o más grande de 1024.
Nota: Es importante darse cuenta de que este ejemplo funciona porque no hay definido un width (por
omisión, es igual a width: 100%). Desde que exista un width, las otras propiedades pierden efecto
porque se está obligando a que tenga un tamaño fijo concreto.
Con las imágenes, videos y contenidos multimedia, se puede hacer lo mismo, consiguiendo así que las
imágenes se escalen y adapten al formato especificado o incluso al tamaño de pantalla de los diferentes
dispositivos utilizados:
img,
video,
object,
embed {
max-width: 100%;
height: auto;
El viewport
En muchos casos puede que oigas hablar del viewport del navegador. Esa palabra hace referencia a la
región visible del navegador, o sea, la parte de la página que está visualizándose actualmente en el
navegador. Los usuarios podemos redimensionar la ventana del navegador para reducir el tamaño del
viewport y simular que se trata de una pantalla y dispositivo más pequeño.
Si queremos editar ciertos comportamientos del viewport del navegador, podemos editar el documento
HTML para especificar el siguiente campo meta, antes de la parte del </head>:
<meta name="viewport" content="initial-scale=1, width=device-width">
Con esta etiqueta <meta>, estamos estableciendo unos parámetros de comportamiento para el viewport
del navegador. Veamos que significan y cuales más existen:
■ yes = 1
■ no = 0.1
■ device-width = 10
■ device-height = 10
Por otra parte, user-scalable permite definir si es posible que el usuario pueda «pellizcar» la pantalla
para ampliar o reducir el zoom.
Ojo: Aunque es posible utilizar algunos de estos parámetros, es aconsejable revisar detalladamente las
consecuencias de especificar estos parámetros. Lo recomendable es utilizar sólo los que se mencionan
en el fragmento de código superior, para evitar problemas de accesibilidad que impidan ciertas acciones.
Una vez nos adentramos en el mundo del Responsive Design, nos damos cuenta en que hay situaciones
en las que determinados aspectos o componentes visuales deben aparecer en un tipo de dispositivos, o
deben existir ciertas diferencias.
Por ejemplo, una zona donde se encuentra el buscador de la página puede estar colocada en un sitio
concreto en la versión de escritorio, pero en móvil quizás nos interesa que ocupe otra zona (o que tenga
otro tamaño o forma) para aprovechar mejor el poco espacio que tenemos en la versión móvil de la
página.
Para ello, utilizaremos un concepto denominado media queries, con los que podemos hacer esas
excepciones para que sólo se apliquen a un tipo de diseño concreto.
/* reglas CSS */
/* reglas CSS */
/* reglas CSS */
/* reglas CSS */
}
Con este método, especificamos que queremos aplicar los estilos CSS para tipos de medios concretos
(screen: sólo en pantallas, en este caso) que cumplan las condiciones especificadas entre paréntesis. De
esta forma, una estrategia aconsejable es crear reglas CSS generales (como hemos hecho hasta ahora)
aplicadas a todo el documento: colores, tipo de fuente, etc. y luego, las particularidades que se aplicarían
sólo en el dispositivo en cuestión.
Aunque suele ser menos habitual, también se pueden indicar reglas @media negadas mediante la
palabra clave not, que aplicará CSS siempre y cuando no se cumpla una determinada condición.
Tambien pueden separarse por comas varias condiciones de media queries.
Truco: Al igual que not, también existe una palabra clave only que, suele usarse a modo de hack. El
comportamiento por defecto ya incluye los dispositivos que encajan con la condición, pero con la
palabra clave only conseguimos que navegadores antiguos que no la entienden, no procesen la
información, dejándola sólo para navegadores modernos.
speech Lectores de texto para invidentes (Antes aural, el cuál ya está obsoleto).
Otros tipos de medios como braille, embossed, handheld, projection, tty o tv aún son válidos, pero
están marcados como obsoletos a favor de utilizar tipos de medios de la lista anterior y restringir sus
características posteriormente.
Recordemos que con el siguiente fragmento de código HTML estamos indicando que el nuevo ancho de
la pantalla es el ancho del dispositivo, por lo que el aspecto del viewport se va a adaptar
consecuentemente:
<meta name="viewport" content="initial-scale=1, width=device-width">
Con esto conseguiremos preparar nuestra web para dispositivos móviles y prepararnos para la
introducción de reglas media query en el documento CSS.
.menu {
background: blue;
.menu {
background: red;
.menu {
background: green;
El ejemplo anterior muestra un elemento (con clase menu) con un color de fondo concreto, dependiendo
del tipo de medio con el que se visualice la página:
■ Rojo para resoluciones entre 640 píxeles y 1280 píxeles de ancho (tablets).
Estos estilos quedarán separados en varios archivos diferentes. Ten en cuenta que todos serán
descargados al cargar la página, sólo que no serán aplicados al documento hasta que cumplan los
requisitos indicados en el atributo media.
Tipos de características
En los ejemplos anteriores solo hemos utilizado max-width y min-width como tipos de características a
utilizar en condiciones de media query. Sin embargo, tenemos una lista de tipos de características que
podemos utilizar:
Existen otras características minoritarias que en algunos casos límite pueden ser interesantes, como por
ejemplo scan, resolution, monochrome, grid, color-index, color, etc...
Condicionales CSS
Aunque no forman parte de las media queries en sí, podemos utilizar la regla @supports para establecer
condicionales y crear reglas similares a @media pero dependiendo de si el navegador del usuario
soporta una característica concreta.
@supports not (display: grid) and (display: flex) {
.content {
display: flex;
justify-content: center;
.content {
display: block;
Estas reglas son muy interesantes para casos particulares donde queremos dar soporte a navegadores
antiguos, pero hay que tener en cuenta que navegadores como Internet Explorer (quizás uno de los
más interesantes para utilizarlo) no tienen soporte para la regla @supports, aún ni en su versión 11.
Uno de los procesos más problematicos y frustrantes de CSS, sobre todo para novatos o principiantes, es
el proceso de colocar y distribuir los elementos a lo largo de una página. Mecanismos como
posicionamiento, floats o elementos en bloque o en línea, suelen ser insuficientes (o muy complejos)
para crear un layout o estructuras para páginas web actuales.
El sistema flexbox es una gran mejora, sin embargo, está orientado a estructuras de una sola dimensión,
por lo que aún necesitamos algo más potente para estructuras web más específicas o complejas. Con el
paso del tiempo, muchos frameworks y librerías utilizan un sistema grid donde definen una cuadrícula
determinada, y modificando los nombres de las clases de los elementos HTML, podemos darle tamaño,
posición o colocación.
Grid CSS nace de esa necesidad, y recoge las ventajas de ese sistema, añadiendole numerosas mejoras
y características que permiten crear rápidamente cuadrículas sencillas y potentes de forma prácticamente
instantánea.
Conceptos
Antes de comenzar con Grid CSS, quizás sería conveniente dominar el sistema Flexbox, ya que Grid
toma la filosofía y bases de él. Para utilizar Grid CSS necesitaremos tener en cuenta una serie de
conceptos que utilizaremos a partir de ahora y que definiremos a continuación:
■ Contenedor: El elemento padre contenedor que definirá la cuadrícula o rejilla.
■ Ítem: Cada uno de los hijos que contiene la cuadrícula (elemento contenedor).
■ Celda (grid cell): Cada uno de los cuadritos (unidad mínima) de la cuadrícula.
<div class="a">Item 1</div> <!-- cada uno de los ítems del grid -->
</div>
Para activar la cuadrícula grid hay que utilizar sobre el elemento contenedor la propiedad display y
especificar el valor grid o inline-grid. Este valor influye en como se comportará la cuadrícula con el
contenido exterior. El primero de ellos permite que la cuadrícula aparezca encima/debajo del contenido
exterior (en bloque) y el segundo de ellos permite que la cuadrícula aparezca a la izquierda/derecha (en
línea) del contenido exterior.
inline-grid Establece una cuadrícula con ítems en línea, de forma equivalente a inline-block.
grid Establece una cuadrícula con ítems en bloque, de forma equivalente a block.
Una vez elegido uno de estos dos valores, y establecida la propiedad display al elemento contenedor,
hay varias formas de configurar nuestra cuadrícula grid. Comencemos con las propiedades que se
aplican al elemento contenedor (padre).
grid-template-columns [c1] [c2] ... Establece el de cada columna (col 1, col 2...).
grid-template-rows [f1] [f2] ... Establece el de cada fila (fila 1, fila 2...).
display: grid;
Esto significa que tendremos una cuadricula con 2 columnas (la primera con 50px de ancho y la
segunda con 300px de ancho) y con 2 filas (la primera con 200px de alto y la segunda con 75px de
alto). Ahora, dependiendo del número de ítems (elementos hijos) que tenga el contenedor grid,
tendremos una cuadrícula de 2x2 elementos (4 ítems), 2x3 elementos (6 ítems), 2x4 elementos (8 ítems)
y así sucesivamente. Si el número de ítems es impar, la última celda de la cuadrícula se quedará vacía.
display: grid;
Este nuevo ejemplo, se crea una cuadrícula de 2x2, donde el tamaño de ancho de la cuadrícula se divide
en dos columnas (mismo tamaño de ancho para cada una), y el tamaño de alto de la cuadrícula se
divide en dos filas, donde la primera ocupará el doble (2 fr) que la segunda (1 fr):
De esta forma, podemos tener un mejor control del espacio restante de la cuadrícula, y como utilizarlo.
Nota: Se pueden combinar varias unidades diferentes, pudiendo utilizar píxeles (px) y fracciones
restantes (fr), porcentajes (%) y fracciones restantes (fr) o combinaciónes similares.
display: grid;
Asumiendo que tuvieramos un contenedor grid con 8 ítems hijos (o más), el ejemplo anterior crearía una
cuadrícula con 4 columnas (la primera de 100px de ancho, la segunda y tercera de 50px de ancho y la
cuarta de 200px de ancho). Por otro lado, tendría 2 filas (la primera de 50px de alto, y la segunda de
100px de alto). En el caso de tener más ítems hijos, el patrón se seguiría repitiendo.
El ejemplo anterior sería equivalente al código CSS siguiente:
.grid {
display: grid;
<div class="header">Header</div>
<div class="sidebar">Sidebar</div>
<div class="content">Content</div>
<div class="footer">Footer</div>
</div>
Los nombres de las clases ya dan una idea del contenido que tendrán. Ahora, mediante Grid CSS lo que
haremos es darle una estructura definida. Para ello, vamos a considerar los siguientes nombres para las
lineas de nuestro grid, utilizando X para las posiciones en el eje X y utilizando Y para las posiciones en
el eje Y:
Teniendo esto en cuenta, lo único que tenemos que hacer es indicar estos nombres entre corchetes, justo
antes de la medida que establecimos como vimos en apartados anteriores. Obsérvese que también se
coloca un nombre de línea final sin medida a continuación, que representa la línea final:
.grid {
display: grid;
En este caso, los nombres utilizados son tan sólo un ejemplo didáctico. Si se considera más adecuado, se
podrían utilizar otros nombres quizás más amigables como top-line, top-medium-line, bottom-
medium-line y bottom-line, por ejemplo, en lugar de y0, y1, y2 y y3 respectivamente.
Ahora, teniendo los nombres, sólo quedaría delimitar que zonas del grid queremos que ocupe cada uno
de nuestros bloques <div> del grid. Para ello utilizaremos las propiedades grid-column-start, grid-
column-end y grid-row-start, grid-row-end. También podriamos utilizar sus propiedades de atajo
grid-column y grid-row.
.header {
background: darkred;
grid-column-start: x0;
grid-column-end: x3;
/* Equivalente a */
grid-column: x0 / x3;
.sidebar {
background: black;
grid-row: y1 / y2;
color: white;
.content {
background: orange;
grid-column: x1 / x3;
grid-row: y1 / y3;
.footer {
background: green;
grid-column: x0 / x3;
grid-row: y2;
Nota: Ten en cuenta que sería necesario darle un tamaño de alto con height al contenedor padre para
que el navegador sepa cuanto ocupará la estructura completa. También podemos modificar las medidas
1fr para dar menos proporción, por ejemplo utilizando en grid-template-rows un [y0] 0.5fr y un [y2]
0.25fr.
Propiedad Descripción
grid-template-areas Indica la disposición de las áreas en el grid. Cada texto entre comillas simboliza una fila.
grid-area Indica el nombre del área. Se usa sobre ítems hijos del grid.
De esta forma, es muy sencillo crear una cuadrícula altamente personalizada en apenas unas cuantas
líneas de CSS, con mucha flexibilidad en la disposición y posición de cada área:
.grid {
display: grid;
"menu main"
"foot foot";
■ El Item 2, el menú (menu), ocuparía el área izquierda del grid, debajo de la cabecera.
■ El Item 3, el contenido (main), ocuparía el área derecha del grid, debajo de la cabecera.
■ El Item 4, el pie de cuadrícula (foot), ocuparía toda la zona inferior del grid.
OJO: Ten en cuenta añadir contenido de texto en cada celda del grid, para que Grid CSS detecte que esa
celda no está vacía.
■ La palabra clave none: Indica que no se colocará ninguna celda en esta posición.
■ Uno o más puntos (.): Indica que se colocará una celda vacía en esta posición.
Huecos en grid
Por defecto, la cuadrícula tiene todas sus celdas pegadas a sus celdas contiguas. Aunque sería posible
darle un margin a las celdas dentro del contenedor, existe una forma más apropiada, que evita los
problemas clásicos de los modelos de caja: los huecos (gutters).
Para especificar los huecos (espacio entre celdas) podemos utilizar las propiedades grid-column-gap
y/o grid-row-gap. En ellas indicaremos el tamaño de dichos huecos:
Propiedad Descripción
grid-column-gap: 100px;
grid-row-gap: 10px;
Con esto, obtendríamos un resultado como el siguiente, indicando huecos entre columnas de 100px y
huecos entre filas de 10px:
/* grid-gap: <rowcolumn-gap> */
grid-gap: 40px;
Posición en el grid
Existen una serie de propiedades que se pueden utilizar para colocar los ítems dentro de la cuadrícula.
Con ellas podemos distribuir los elementos de una forma muy sencilla y cómoda. Dichas propiedades
son justify-items y align-items, que ya conocerás del módulo CSS flexbox:
justify-items start | end | center | stretch Distribuye los elementos en el eje horizontal.
align-items start | end | center | stretch Distribuye los elementos en el eje vertical.
Estas propiedades se aplican sobre el elemento contenedor padre, pero afectan a los ítems hijos, por lo
que actuan sobre la distribución de cada uno de los hijos. En el caso de que queramos que uno de los
ítems hijos tengan una distribución diferente al resto, aplicamos la propiedad justify-self o align-self
sobre el ítem hijo en cuestión, sobreescribiendo su distribución.
Estas propiedades funcionan exactamente igual que sus análogas justify-items o align-items, sólo que
en lugar de indicarse en el elemento padre contenedor, se hace sobre un elemento hijo. Las propiedades
sobre ítems hijos las veremos más adelante.
También podemos utilizar las propiedades justify-content o align-content para modificar la
distribución de todo el contenido en su conjunto, y no sólo de los ítems por separado:
Propiedad Valores
De esta forma, podemos controlar prácticamente todos los aspectos de posicionamiento de la cuadrícula
directamente desde los estilos CSS de su contenedor padre
grid-auto-flow row | column | dense Utiliza un algoritmo de autocolocación (intenta rellenar huecos).
Un ejemplo de como se insertarían los elementos en una cuadrícula de 2x2 utilizando grid-auto-flow
por columnas o por filas:
Atajo: Grid
Por último, existe una propiedad grid que sirve de atajo para la mayoría de propiedades CSS relativas a
cuadrículas. Su esquema de utilización sería el siguiente, junto a algunos ejemplos:
.grid {
grid: row;
Sin embargo, existen algunas propiedades más, referentes en este caso, a la posición de los hijos de la
cuadrícula donde va a comenzar o terminar una fila o columna. Las propiedades son las siguientes:
Propiedad Descripción
Con dichas propiedades, podemos indicar el siguiente código CSS sobre el primer ítem de una
cuadrícula de 4 ítems:
.grid {
display:grid;
.a {
grid-column-start: 1;
grid-row-end: 2;
De esta forma, tenemos una cuadrícula de 4 elementos, en el que indicamos la posición del ítem 1
(elemento con clase .a): comenzando en la columna 1 y acabando en el inicio de la columna 2:
Ese sería el funcionamiento normal. Donde se ve la utilidad de estas propiedades, es si variamos los
valores de forma que tomen posiciones diferentes, como por ejemplo, si indicamos que el ítem 1 debe
comenzar en la columna 1, pero acabar en la columna 3 (ocupando la hipotética primera y segunda
celda):
También es posible utilizar la palabra clave span seguida de un número, que indica que abarque hasta
esa columna o celda.
.a {
grid-column: auto;
grid-column: 4 / 6;
grid-column: span 3;
grid-column: span 3 / 6;