Este capítulo habla sobre:
- Manipular elementos usando transformaciones para transiciones y animaciones de desempeño
- Agregar un efecto de "rebote" a una transición
- La canalización de procesamiento del navegador
- Mirando las transformaciones 3D y la perspectiva
En este capítulo, exploraremos la propiedad de transform
, que puede usar para cambiar o distorsionar la forma o posición de un elemento en la página. Esto puede implicar rotar, escalar o sesgar el elemento en dos o tres dimensiones. Las transformaciones se utilizan más comúnmente junto con transiciones o animaciones, por lo que he intercalado este capítulo entre esos dos temas. En estos dos últimos capítulos, creará una página que hace un uso intensivo de transiciones, transformaciones y animaciones.
Primero, lo guiaré a través de la aplicación de transformaciones a un elemento estático. Esto le dará una idea de cómo funcionan de forma aislada antes de agregarlos a algunas transiciones. Luego, creará un menú pequeño pero complejo con múltiples transformaciones y efectos de transición. Finalmente, veremos cómo trabajar en 3D y utilizar la perspectiva. Esto se trasladará al siguiente capítulo, donde usaremos transformaciones 3D junto con animación.
15.1. ROTAR, TRADUCIR, ESCALAR Y BORRAR
Una regla de transformación básica se parece a esto:
transform: rotate(90deg);
Esta regla, cuando se aplica a un elemento, lo gira 90 grados a la derecha (en el sentido de las agujas del reloj). La función de transformación rotate()
especifica cómo se transformará el elemento. Encontrará varias otras funciones de transformación, pero generalmente todas caen en una de cuatro categorías (ilustradas en la figura 15.1).
- Rotate: hace girar el elemento una cierta cantidad de grados alrededor de un eje.
- Translate: mueve el elemento hacia la izquierda, derecha, arriba o abajo (similar al posicionamiento relativo)
- Scale: reduce o expande el elemento.
- Skew: distorsiona la forma del elemento, deslizando su borde superior en una dirección y su borde inferior en la dirección opuesta.

Cada transformación se aplica utilizando la función correspondiente como valor de la propiedad de transform
. Creemos un ejemplo sencillo para probarlos en su navegador. Esta será una tarjeta con una imagen y texto (figura 15.2), a la que puede aplicar transformaciones.

Cree una nueva página y hoja de estilo y vincúlelas. Agregue el HTML que se muestra aquí.
<div class="card">
<img src="images/chicken1.jpg" alt="a chicken"/>
<h4>Mrs. Featherstone</h4>
<p> She may be a bit frumpy, but Mrs Featherstone gets the job done. She
lays her largish cream-colored eggs on a daily basis. She is gregarious
to a fault.</p>
<p>This Austra White is our most prolific producer.</p>
</div>
Listado 15.1. Creando una tarjeta simple
A continuación, en la hoja de estilo, agregue el CSS en la siguiente lista. Esto incluye algunos estilos base, colores y una tarjeta con una transformación de rotación aplicada.
body {
background-color: hsl(210, 80%, 20%);
font-family: Helvetica, Arial, sans-serif;
}
img {
max-width: 100%;
}
.card {
padding: 0.5em;
margin: 0 auto; 1
background-color: white;
max-width: 300px;
transform: rotate(15deg); 2
}
Listado 15.2. Diseñar una tarjeta y aplicar una transformación
- Centra la tarjeta
- Gira la tarjeta 15 grados a la derecha
Cargue esto en su navegador y verá la tarjeta rotada. Experimente un poco con esto para tener una idea de cómo se comporta la función rotate()
. Utilice un ángulo negativo para rotar la tarjeta hacia la izquierda (por ejemplo, intente rotate(-30ged)
).
A continuación, intente cambiar la transformación a algunas de las otras funciones. Utilice los siguientes valores y observe cómo se comportan cada uno:
skew(20deg)
: inclina la tarjeta 20 grados. Pruebe con un ángulo negativo para inclinarse en la otra dirección.scale(0.5)
: reduce la tarjeta a la mitad de su tamaño inicial. La funciónscale()
toma un número sin unidades. Los valores inferiores a 1 encogen el elemento; los valores superiores a 1 lo expanden.translate(20px, 40px)
: desplaza el elemento 20 píxeles hacia la derecha y 40 píxeles hacia abajo. Nuevamente, puede usar valores negativos para transformar en la dirección opuesta.
Una cosa a tener en cuenta al usar transformaciones es que, si bien el elemento puede moverse a una nueva posición en la página, no cambia el flujo del documento. Puede trasladar un elemento a lo largo de la pantalla, pero su ubicación original permanece desocupada por otros elementos. Además, al rotar un elemento, una esquina del mismo puede salirse del borde de la pantalla. De manera similar, podría cubrir partes de otro elemento a su lado (figura 15.3).

En algunos casos, me parece útil establecer un margen suficiente para uno o ambos elementos para evitar superposiciones no deseadas.
Las transformaciones no se pueden aplicar a elementos en línea como <span>
o <a>
. Para transformar un elemento de este tipo, debe cambiar la propiedad de visualización a algo que no sea inline
(como inline-block
) o cambiar el elemento a un elemento flexible o de cuadrícula (aplique display: flex
o display: grid
al elemento principal).
15.1.1. Cambiar el origen de la transformación
Se realiza una transformación alrededor de un punto de origen. Este punto sirve como eje de rotación o el punto donde comienza el escalado o el sesgo. Esto significa que el punto de origen del elemento permanece bloqueado en su lugar, mientras que el resto del elemento se transforma a su alrededor (aunque esto no se aplica a translate()
ya que todo el elemento se mueve durante una traducción).
De forma predeterminada, el punto de origen es el centro del elemento, pero puede cambiarlo con la propiedad transform-origin
. La figura 15.4 muestra algunos elementos transformados alrededor de diferentes puntos de origen.

Para el elemento de la izquierda, la rotación gira alrededor del origen, que se establece usando transform-origin: right bottom
. El elemento en el medio escala hacia el origen (right top)
. Y el elemento de la derecha se sesga de tal manera que su origen (left top)
permanece en su lugar mientras que el resto del elemento se estira.
El origen también se puede especificar en porcentajes, medidos desde la parte superior izquierda del elemento. Las siguientes dos declaraciones son equivalentes:
transform-origin: right center;
transform-origin: 100% 50%;
También puede usar una longitud para especificar el origen en píxeles, ems u otra unidad. Aunque, en mi experiencia, las palabras clave top
, right
, bottom
, left
y center
son todo lo que necesita en la mayoría de los casos.
15.1.2. Aplicar múltiples transformaciones
Puede especificar varios valores para la propiedad transform
, cada uno separado por un espacio. Cada valor de transformación se aplica sucesivamente de derecha a izquierda. Si aplica transform: rotate(15deg) translate(15px, 0)
, el elemento se traslada 15 px a la derecha y luego se gira 15 grados en el sentido de las agujas del reloj. Edite su hoja de estilo para trabajar un poco con esto.
.card {
padding: 0.5em;
margin: 0 auto;
background-color: white;
max-width: 300px;
transform: rotate(15deg) translate(20px, 0); 1
}
Listado 15.3. Aplicar múltiples transformaciones
- 1 Traduce 20 px a la derecha, luego gira 15 grados en el sentido de las agujas del reloj
Probablemente sea más fácil ver este efecto si abre las DevTools de su navegador y manipula los valores en vivo para ver cómo afectan al elemento. Observe que cambiar los valores de translate()
parece mover el elemento a lo largo de un eje diagonal, en lugar de las direcciones cardinales normales; esto se debe a que la rotación tiene lugar después de la traducción.
Puede ser un poco complicado trabajar con esto. En general, encuentro que es más fácil hacer las manipulaciones translate()
en último lugar cronológicamente (primero en el orden de origen para la transformación), por lo que puedo trabajar con las coordenadas normales izquierda / derecha, arriba / abajo. Para ver esto, invierta el orden de transform: translate(20px, 0) rotate(15 grados)
.
15.2. TRANSFORMACIONES EN MOVIMIENTO
Las transformaciones por sí solas no son tan prácticas. Un cuadro con un skew()
aplicado puede parecer interesante, pero no es exactamente fácil de leer. Pero cuando se usa junto con el movimiento, las transformaciones se vuelven mucho más útiles.
Creemos una página que utilice este concepto. En la figura 15.5 se muestra una captura de pantalla de la página que creará. Agregará mucho movimiento a esta página.

En esta sección, creará el menú de navegación (nav)
a la izquierda. Inicialmente, aparece como solo cuatro íconos apilados verticalmente, pero, al pasar el mouse, aparece el texto del menú. Este ejemplo incluirá varias transiciones y un par de transformaciones. Vamos a configurar la página, luego veremos más de cerca el menú de navegación. (En el siguiente capítulo, creará la sección de tarjetas principal en el centro y agregará más transformaciones y algo de animación).
Cree una nueva página y una nueva hoja de estilo llamada style.css y agregue el siguiente marcado. Este marcado incluye un enlace a dos fuentes web (Alfa Slab One y Raleway) de la API de Google Fonts. También tiene el marcado para el encabezado de la página y el menú de navegación.
<!doctype html>
<html lang="en">
<head>
<title>The Yolk Factory</title>
<link
href="https://fonts.googleapis.com/css?family=Alfa+Slab+One|Raleway"
rel="stylesheet"> 1
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<h1 class="page-header">The Yolk Factory</h1>
</header>
<nav class="main-nav">
<ul class="nav-links">
<li>
<a href="/">
<img src="images/home.svg" class="nav-links__icon"/> 2
<span class="nav-links__label">Home</span> 2
</a>
</li>
<li>
<a href="/events">
<img src="images/calendar.svg" class="nav-links__icon"/> 2
<span class="nav-links__label">Events</span> 2
</a>
</li>
<li>
<a href="/members">
<img src="images/members.svg" class="nav-links__icon"/> 2
<span class="nav-links__label">Members</span> 2
</a>
</li>
<li>
<a href="/about">
<img src="images/star.svg" class="nav-links__icon"/> 2
<span class="nav-links__label">About</span> 2
</a>
</li>
</ul>
</nav>
</body>
</html>
Listado 15.4. Marcado de página para transformaciones en movimiento
- Agrega las fuentes Alfa Slab One y Raleway a la página
- Los enlaces de navegación contienen cada uno una imagen y una etiqueta.
El elemento de navegación contiene la mayor parte de este marcado. Incluye una lista desordenada (<ul>)
de enlaces. Cada enlace consta de una imagen de icono y una etiqueta de texto. Tenga en cuenta que las imágenes de los iconos aquí están en formato SVG. Esto se volverá importante más adelante. Agregará más contenido a la página cuando esté listo para darle estilo en el próximo capítulo.
SVG: abreviatura de gráficos vectoriales escalables. Este es un formato de imagen basado en XML que define una imagen usando vectores. Debido a que la imagen está definida matemáticamente, se puede escalar hacia arriba y hacia abajo a cualquier tamaño. SVG es ampliamente compatible con todos los navegadores.
A continuación, agregará algunos estilos básicos, incluido un degradado de fondo y un relleno alrededor del título principal. También aplicará las fuentes web a la página. Copie o agregue la siguiente lista en su hoja de estilo. Estos son solo los estilos base y el encabezado de la página; trabajará en diseñar el menú a continuación.
html {
box-sizing: border-box;
}
*,
*::before,
*::after {
box-sizing: inherit;
}
body {
background-color: background-color: hsl(200, 80%, 30%);
background-image: radial-gradient(hsl(200, 80%, 30%), 1
hsl(210, 80%, 20%))); 1
color: white;
font-family: Raleway, Helvetica, Arial, sans-serif;
line-height: 1.4;
margin: 0;
min-height: 100vh; 2
}
h1, h2, h3 {
font-family: Alfa Slab One, serif;
font-weight: 400;
}
main {
display: block;
}
img {
max-width: 100%;
}
.page-header {
margin: 0;
padding: 1rem; 3
}
@media (min-width: 30em) { 4
.page-header { 4
padding: 2rem 2rem 3rem; 4
} 4
}
Listado 15.5. Estilos base y encabezado
- Gradiente de fondo azul profundo
- Asegura que el cuerpo llene la ventana gráfica para que el degradado llene la pantalla
- Relleno más pequeño para el encabezado en las ventanas gráficas móviles
- Acolchado más grande para el encabezado en pantallas más grandes
Este ejemplo utiliza varios conceptos de capítulos anteriores. He utilizado un degradado radial para el fondo del cuerpo. Esto agrega un poco de profundidad a la página. (El background-color
proporciona un valor de respaldo para Opera Mini, que no admite degradados radiales). La fuente web Alfa Slab One se aplica a los títulos y Raleway al cuerpo del texto. También proporcioné estilos receptivos para el encabezado de la página mediante una consulta de medios, agregando un relleno más grande cuando el tamaño de la pantalla se lo puede permitir.
Tomaremos el menú en varias etapas. Primero, diseñemos el menú y luego proporcionemos un comportamiento receptivo. Hará esto con un primer enfoque móvil (capítulo 8), así que comencemos con la pequeña ventana gráfica. El encabezado y el menú deben verse como en la figura 15.6.

Debido a que desea diseñar los enlaces de navegación horizontalmente para ventanas gráficas más pequeñas, tiene sentido un enfoque que utilice un flexbox. Puede espaciar uniformemente los elementos de navegación a lo ancho de la página aplicando align-content: space-between
al contenedor flexible. A continuación, establecerá los colores de la fuente y alineará los iconos. Agregue la siguiente lista a su hoja de estilo.
.nav-links {
display: flex; 1
justify-content: space-between; 1
margin-top: 0;
margin-bottom: 1rem;
padding: 0 1rem;
list-style: none;
}
.nav-links > li + li {
margin-left: 0.8em;
}
.nav-links > li > a {
display: block;
padding: 0.8em 0;
color: white;
font-size: 0.8rem;
text-decoration: none; 2
text-transform: uppercase; 2
letter-spacing: 0.06em; 2
}
.nav-links__icon {
height: 1.5em;
width: 1.5em;
vertical-align: -0.2em; 3
}
.nav-links > li > a:hover {
color: hsl(40, 100%, 70%);
}
Listado 15.6. Estilos móviles para los enlaces del menú de navegación
- Utiliza una caja flexible para distribuir los elementos de navegación por la pantalla de forma horizontal
- Estilos del texto del enlace
- Mueve los iconos ligeramente hacia abajo para centrarlos con las etiquetas de texto
Mantendrá el menú como este en ventanas gráficas más pequeñas. Pero en pantallas más grandes, puede superponer más efectos. Para el diseño de escritorio, lo acoplará en el lado izquierdo de la pantalla usando una posición fija. Esto se verá como la figura 15.7.

Este menú está construido a partir de dos módulos: he nombrado el elemento externo main-nav
y la estructura interna nav-links
. El main-nav
sirve como contenedor, que colocará a la izquierda. El main-nav
también proporciona el fondo oscuro. Pongamos esto en su lugar.
Agregue la siguiente lista a su hoja de estilo; asegúrese de que la segunda media query y su contenido se coloquen después de los estilos de main-nav
existentes para que puedan anular los estilos móviles cuando sea necesario.
@media (min-width: 30em) { 1
.main-nav {
position: fixed;
top: 8.25rem;
left: 0;
z-index: 10; 2
background-color: transparent; 3
transition: background-color .5s linear; 4
border-top-right-radius: 0.5em;
border-bottom-right-radius: 0.5em;
}
.main-nav:hover {
background-color: rgba(0, 0, 0, 0.6); 5
}
}
/* ... */
@media (min-width: 30em) { 6
.nav-links {
display: block;
padding: 1em;
margin-bottom: 0;
}
.nav-links > li + li {
margin-left: 0;
}
.nav-links__label {
margin-left: 1em;
}
}
Listado 15.7. Colocación del menú para ventanas gráficas grandes
- Aplica estilos solo a pantallas medianas y grandes
- Asegura que la navegación se muestre frente a otro contenido agregado a la página más tarde
- Inicialmente deja transparente el color de fondo
- Agrega un efecto de transición al fondo
- Aplica un fondo oscuro semitransparente al pasar el mouse
- 6 Anula el flexbox de los estilos móviles para hacer que los enlaces se apilen verticalmente
La declaración position: fixed
coloca el menú en su lugar y lo mantiene allí, incluso cuando la página se desplaza. La regla display: block
anula la display: flex
de los estilos móviles, lo que hace que los elementos del menú se apilen unos sobre otros.
Ahora comencemos a superponer algunos efectos de transición y transformación. Para eso, harás tres cosas:
- Aumente el tamaño del icono mientras se desplaza un enlace.
- Oculte las etiquetas de los enlaces, luego haga que todas aparezcan con una transición gradual cuando el usuario pase el mouse sobre el menú.
- Utilice una traducción para agregar un efecto de "entrada rápida" a la etiqueta del enlace junto con la aparición gradual.
Analicemos estos en cada uno de ellos.
15.2.1. Ampliando el icono
Mire la estructura de los enlaces de navegación. Cada elemento de la lista contiene un enlace (<a>)
, que a su vez contiene un icono y una etiqueta:
<li>
<a href="/">
<img src="images/home.svg" class="nav-links__icon"/>
<span class="nav-links__label">Home</span>
</a>
</li>
Los elementos de la lista, junto con el padre <ul>
, es un módulo mucho más grande y más profundamente anidado de lo que prefiero hacer. Por lo general, buscaría una forma de dividirlo en módulos más pequeños, pero tendremos que mantenerlo todo junto para lograr algunos de estos efectos.
Primero, aumentemos la escala del ícono al pasar el mouse. Hará esto con una transformación de escala, luego le aplicará una transición para que el cambio ocurra sin problemas. En la figura 15.8, el elemento del menú Eventos se coloca sobre el mouse y su icono de calendario se amplía ligeramente.

La imagen de Eventos tiene una altura y un ancho establecidos, por lo que podría agrandarla aumentando estas propiedades. Pero, esto haría que otros elementos se movieran a medida que se recalculara el flujo del documento.
Al usar una transformación en su lugar, los elementos que la rodean no se ven afectados y la etiqueta Eventos no se desplaza hacia la derecha. Actualice su CSS para agregar este efecto cuando el elemento esté suspendido o enfocado.
@media (min-width: 30em) {
.nav-links {
display: block;
padding: 1em;
margin-bottom: 0;
}
.nav-links > li + li {
margin-left: 0;
}
.nav-links__label {
margin-left: 1em;
}
.nav-links__icon {
transition: transform 0.2s ease-out; 1
}
.nav-links a:hover > .nav-links__icon,
.nav-links a:focus > .nav-links__icon {
transform: scale(1.3); 2
}
}
Listado 15.8. Ampliando el icono cuando su enlace está suspendido o enfocado
- Transiciones de la propiedad de transformación
- Aumenta el tamaño del icono
Ahora, mientras desliza el mouse por los elementos del menú, verá que los íconos crecen un poco para ayudar a indicar sobre qué elemento está colocando el cursor. Elegí intencionalmente usar recursos de imagen SVG aquí, por lo que no hay pixelación u otras distorsiones extrañas cuando cambia el tamaño de la imagen. La transformación scale()
es una forma perfecta de hacer esto.
Los iconos son una parte importante de algunos diseños. Las técnicas utilizadas para los íconos han evolucionado y, durante mucho tiempo, la mejor práctica fue poner todos sus íconos en un solo archivo de imagen, llamado sprite sheet. Luego, usando una imagen de fondo CSS y un tamaño y posicionamiento de fondo cuidadosos, muestre un ícono de la sprite sheet en un elemento.
Luego, las fuentes de iconos se hicieron populares. En lugar de incrustar sprites en una imagen, este enfoque implica incrustar cada icono como un personaje en un archivo de fuente personalizado. Al usar fuentes web, un solo carácter se representaría como un icono. Servicios como Font-Awesome (https://fontawesome.io/) proporcionan cientos de iconos de uso general para facilitar esta tarea.
Estas técnicas aún funcionan, pero te animo a que cambies a iconos SVG. SVG es mucho más versátil y más eficaz. Puede usar un SVG como fuente <img>
, como lo hizo en este capítulo, pero SVG también ofrece otras opciones. Puede crear una hoja de sprites SVG, o como SVG es un formato de archivo basado en XML, puede insertarlo directamente en su HTML. Por ejemplo:
<li>
<a href="/">
<svg class="nav-links__icon" width="20" height="20" viewBox="0 0 20
20">
<path fill="#ffffff" d="M19.871 12.165l-8.829-9.758c-0.274-0.303-
0.644-0.47-1.042-0.47-0 0 0 0 0 0-0.397 0-0.767 0.167-1.042
0.47l-8.829 9.758c-0.185 0.205-0.169 0.521 0.035 0.706 0.096
0.087 0.216 0.129 0.335 0.129 0.136 0 0.272-0.055 0.371-
0.165l2.129-2.353v8.018c0 0.827 0.673 1.5 1.5 1.5h11c0.827 0 1.5-
0.673 1.5-1.5v-8.018l2.129 2.353c0.185 0.205 0.501 0.221 0.706
0.035s0.221-0.501 0.035-0.706zM12 19h-4v-4.5c0-0.276 0.224-0.5
0.5-0.5h3c0.276 0 0.5 0.224 0.5 0.5v4.5zM16 18.5c0 0.276-0.224
0.5-0.5 0.5h-2.5v-4.5c0-0.827-0.673-1.5-1.5-1.5h-3c-0.827 0-1.5
0.673-1.5 1.5v4.5h-2.5c-0.276 0-0.5-0.224-0.5-0.5v-9.123l5.7-
6.3c0.082-0.091 0.189-0.141 0.3-0.141s0.218 0.050 0.3 0.141l5.7
6.3v9.123z"></path>
</svg>
<span class="nav-links__label">Home</span>
</a>
</li>
Esto le permite apuntar a partes del SVG directamente desde CSS si lo desea; puede cambiar dinámicamente los colores, o incluso el tamaño y la posición, de varias partes de un SVG, utilizando CSS normal. Sin embargo, los tamaños de archivo son más pequeños y las imágenes no se pixelan como GIF, PNG u otros formatos de imagen basados en ráster.
Si no está familiarizado con SVG, consulte https://css-tricks.com/using-svg/ para obtener una buena introducción a las diversas formas en que puede usar SVG en sus páginas web.
Ahora que los íconos se ven geniales, dirijamos nuestra atención a las etiquetas junto a ellos.
15.2.2. Creación de etiquetas de "volar en"
No es necesario que las etiquetas del menú estén visibles en todo momento. Puede ocultarlos de forma predeterminada, dejando los iconos en su lugar para indicar al usuario que el menú está allí. Luego, cuando el usuario mueve el mouse sobre el menú o las pestañas hasta un elemento del menú, puede desaparecer en las etiquetas. De esta manera, cuando el usuario pasa el mouse cerca de los íconos, aparece todo el menú, usando una serie de efectos a la vez: el fondo y las etiquetas se desvanecerán, con las etiquetas comenzando un poco a la izquierda de su posición final (figura 15.9).

Este efecto requiere dos transiciones separadas en las etiquetas al mismo tiempo: una para la opacidad y otra para una transformación translate()
. Actualice esta parte de su hoja de estilo, realizando los cambios indicados en la siguiente lista.
@media (min-width: 30em) {
.nav-links {
display: block;
padding: 1em;
margin-bottom: 0;
}
.nav-links > li + li {
margin-left: 0;
}
.nav-links__label {
display: inline-block; 1
margin-left: 1em;
padding-right: 1em;
opacity: 0; 2
transform: translate(-1em); 3
transition: transform 0.4s cubic-bezier(0.2, 0.9, 0.3, 1.3), 4
opacity 0.4s linear; 4
}
.nav-links:hover .nav-links__label, 5
.nav-links a:focus > .nav-links__label { 5
opacity: 1; 5
transform: translate(0); 5
}
.nav-links__icon {
transition: transform 0.2s ease-out;
}
.nav-links a:hover > .nav-links__icon,
.nav-links a:focus > .nav-links__icon {
transform: scale(1.3);
}
}
Listado 15.9. Transición en las etiquetas de elementos de navegación
- Hace que la etiqueta sea un bloque en línea para que se le puedan aplicar transformaciones
- Oculta la etiqueta inicialmente
- Desplaza la etiqueta 1 em hacia la izquierda
- Agrega transiciones a los valores que cambiarán
- Al pasar el mouse o enfocar, hace que la etiqueta sea visible y la vuelve a colocar en su posición correcta.
Este menú ocupa una pequeña parte del espacio de la pantalla, pero están sucediendo muchas cosas. Algunos de estos selectores son bastante largos y complicados.
Observe cómo la pseudoclase :hover
que acaba de agregar está en el elemento nav-links
de nivel superior, mientras que la pseudoclase :focus
está en <a>
dentro. (El enfoque generalmente solo se puede aplicar a ciertos elementos como enlaces y botones). De esta manera, todas las etiquetas aparecen tan pronto como se pasa el mouse sobre el menú. Además, una etiqueta individual también aparece si el usuario la enfoca usando la tecla Tab del teclado.
Cuando está oculta, la etiqueta se desplaza 1 em hacia la izquierda usando translate()
. Luego, a medida que se desvanece, vuelve a su posición real. He omitido el segundo parámetro de la función translate()
aquí y he especificado solo el valor x, que controla la traducción horizontal. Como no es necesario traducir el elemento hacia arriba y hacia abajo, está bien.
También vale la pena ver la función personalizada cubic-bezier()
. Esto produce un efecto de rebote: la etiqueta se mueve más allá de la ubicación final antes de asentarse donde se detiene. Esta curva se ilustra en la figura 15.10.

Observe que la curva se extiende fuera de la parte superior del cuadro, lo que significa que el valor excede el valor al final de la transición. En la transición de una translate(-1em)
a una translate(0)
, la transformación de la etiqueta alcanzará momentáneamente un valor de aproximadamente 0.15 cm más allá de la posición final antes de retroceder. De manera similar, también puede crear un rebote al comienzo de la función de temporización moviendo la primera palanca de control debajo de la parte inferior de la caja. Sin embargo, no puede extenderse fuera de los bordes izquierdo y derecho, ya que esto produciría una curva de transición ilógica.
Cargue la página en su navegador y observe cómo se comporta esta transición. El rebote es sutil, por lo que es posible que deba reducir el tiempo de transición para verlo conscientemente, pero agrega un poco de peso e impulso a la etiqueta, lo que hace que el movimiento se sienta un poco más natural.
15.2.3. Escalonando las transiciones
El menú parece bastante bueno en este momento. Hagamos un último ajuste para que se sienta pulido. Utilizará la propiedad transition-delay
para establecer un retraso ligeramente diferente para cada elemento del menú. Esto escalonará las animaciones para que vuelen en una "ola" rodante en lugar de todas a la vez (figura 15.11).

Para lograr esto, usará el selector de pseudo-clase: nth-child()
para apuntar a cada elemento del menú según su posición en la lista, y luego aplicará un retardo de transición sucesivamente más largo a cada uno. Agregue el siguiente fragmento de código a su hoja de estilo después del resto de los estilos nav-links
.
.nav-links:hover .nav-links__label,
.nav-links a:focus > .nav-links__label {
opacity: 1;
transform: translate(0);
}
.nav-links > li:nth-child(2) .nav-links__label { 1
transition-delay: 0.1s; 2
}
.nav-links > li:nth-child(3) .nav-links__label { 3
transition-delay: 0.2s; 4
}
.nav-links > li:nth-child(4) .nav-links__label { 5
transition-delay: 0.3s;
}
.nav-links > li:nth-child(5) .nav-links__label { 5
transition-delay: 0.4s;
}
Listado 15.10. Agregar un retraso de transición escalonado a los elementos del menú
- Apunta a la etiqueta del segundo elemento del menú
- Retrasa su transición en una décima de segundo
- Apunta a la etiqueta del tercer elemento del menú
- Retrasa su transición en dos décimas de segundo
- Repita tantas veces como sea necesario
El selector :nth-child(2)
apunta al segundo elemento de la lista, al que aplicó un ligero retraso. El tercer elemento (:nth-child(3))
tiene un retraso un poco más largo. El cuarto y el quinto, cada uno más largo aún. No es necesario que oriente el primer elemento porque desea que su transición comience de inmediato; no necesita retraso de transición.
Cargue esto en su navegador y coloque el cursor sobre el menú para ver el efecto. Se siente fluido y vivo. Apague el mouse para ver que los elementos se desvanecen con el mismo tiempo escalonado.
Encontrará una desventaja en este tipo de enfoque: el menú solo puede ser tan largo como el número de estos selectores que escriba. Agregué una regla para apuntar a un quinto elemento del menú, aunque nuestro menú actualmente solo tiene cuatro elementos. Esta es una medida de seguridad en caso de que se agregue otro elemento de menú en el futuro. Incluso podría agregar un sexto solo para estar seguro. Pero tenga en cuenta que, dado que existe la posibilidad de que el menú supere este recuento en algún momento, deberá agregar más reglas al CSS.
La repetición de un bloque de código como este se puede hacer más fácil con un preprocesador. Consulte el apéndice B para ver un ejemplo.
Ahora que el menú está creado, puede agregar más a esta página. Lo hará en el próximo capítulo, así que tenga esta página a mano para agregarla. Pero antes de eso, hay un par de cosas más que debes saber sobre las transformaciones.
15.3. RENDIMIENTO DE ANIMACIÓN
La existencia de determinadas transformaciones puede parecer redundante. El resultado de una traducción a menudo se puede lograr usando posicionamiento relativo y, en el caso de imágenes o SVG, el resultado de una transformación de escala se puede lograr estableciendo explícitamente una altura y / o ancho.
Las transformaciones son mucho más eficaces en el navegador. Si anima la posición de un elemento (haciendo la transición de la propiedad left
, por ejemplo), puede experimentar un rendimiento notablemente más lento. Este es particularmente el caso cuando se anima un elemento complejo grande o una gran cantidad de elementos en la página a la vez. Este comportamiento de rendimiento se aplica tanto a las transiciones (cubiertas en el capítulo 14) como a las animaciones (que cubriré en el próximo capítulo).
Si está haciendo algún tipo de transición o animación, siempre debe favorecer una transformación sobre el posicionamiento o el tamaño explícito si puede. Para comprender por qué es así, debemos observar más de cerca cómo se representa la página en el navegador.
15.3.1. Mirando la canalización de renderizado
Una vez que el navegador calcula qué estilos se aplican a qué elementos de la página, debe traducir esos estilos a píxeles en la pantalla. Este es el proceso de renderizado, que se puede dividir en tres etapas: diseño, pintura y composición.

En la primera etapa, diseño, el navegador calcula cuánto espacio ocupará cada elemento en la pantalla. Debido a la forma en que funciona el flujo de documentos, el tamaño y la posición de un elemento pueden influir en el tamaño y la posición de muchos otros elementos en la página. Esta etapa arregla todo eso.
Cada vez que cambie el ancho o alto de un elemento, o ajuste sus propiedades de posición (como top
o left
), se debe volver a calcular el diseño del elemento. Esto también se hace si JavaScript inserta o elimina un elemento del DOM. Cuando se produce un cambio de diseño, el navegador debe redistribuir el flujo de la página, volviendo a calcular el diseño de todos los demás elementos que se mueven o cambian de tamaño como resultado del cambio.
Después del diseño viene la pintura. Este es el proceso de rellenar píxeles: se dibuja el texto; las imágenes, los bordes y las sombras están todos coloreados. Esto no se muestra físicamente en la pantalla, sino que se dibuja en la memoria. Partes de la página están pintadas en capas.
Si cambia el color de fondo de un elemento, por ejemplo, debe volver a pintarlo. Pero, debido a que el color de fondo no tiene ningún impacto en la posición o el tamaño de los elementos de la página, no es necesario volver a calcular el diseño para tener en cuenta este cambio. Cambiar un color de fondo es menos intensivo desde el punto de vista informático que cambiar el tamaño de un elemento.
En las condiciones adecuadas, un elemento de la página se puede promover en su propia capa. Cuando esto sucede, se pinta por separado de las otras capas de la página. Los navegadores pueden tomar esta capa y enviarla a la GPU (unidad de procesamiento de gráficos) de la computadora para renderizarla, en lugar de pintarla en la CPU principal como la capa principal. Esto es beneficioso porque la GPU está altamente optimizada para realizar este tipo de cálculo.
Esto a menudo se conoce como aceleración de hardware porque depende de una pieza del hardware de la computadora para aumentar la velocidad de renderizado. Tener más capas significa más uso de memoria; pero, a cambio, puede acelerar el tiempo de procesamiento del renderizado.
En la etapa compuesta, el navegador toma todas las capas que se han pintado y las dibuja en la imagen final que se mostrará en pantalla. Estos se dibujan en un orden determinado para que las capas correctas aparezcan frente a otras capas, en los casos en que se superponen.
Dos propiedades, opacity
y transform
, cuando se cambian, dan como resultado un tiempo de renderizado mucho más rápido. Cuando cambia uno de estos en un elemento, el navegador puede promover ese elemento a su propia capa de pintura y usar la aceleración de GPU. Debido a que el elemento está en su propia capa, la capa principal no cambiará durante la animación y no será necesario volver a pintarla.
Cuando se realiza un cambio único en la página, esta optimización generalmente no hace una diferencia notable. Pero cuando el cambio es parte de una animación, la pantalla debe actualizarse decenas de veces por segundo; en cuyo caso, la velocidad importa. La mayoría de las pantallas se actualizan 60 veces por segundo. Idealmente, los cambios durante la animación deberían volver a calcularse al menos así de rápido para producir el movimiento más fluido posible en la pantalla. Cuanto más trabajo tenga que hacer el navegador para cada nuevo cálculo, más difícil será alcanzar esta velocidad.
Los navegadores han avanzado mucho en la optimización del proceso de renderizado, segmentando los elementos en capas lo mejor que pueden. Si anima la propiedad de transform
o opacity
en un elemento, los navegadores modernos, para que la animación sea fluida, generalmente toman buenas decisiones basadas en una serie de factores, incluidos los recursos del sistema. Pero, ocasionalmente, puede encontrar animaciones entrecortadas o parpadeantes.
Si experimenta esto, puede usar una propiedad llamada will-change
para ejercer control sobre las capas de renderizado. Esta propiedad le indica al navegador, de antemano, que debe esperar que cambie una determinada propiedad en el elemento. Por lo general, esto significa que el elemento se promoverá a su propia capa de pintura. Por ejemplo, aplicar will-change: transform
indica que espera cambiar la propiedad de transformación para ese elemento.
Sin embargo, no aplique esto a ciegas en la página hasta que vea problemas de rendimiento, ya que tenderá a utilizar más recursos del sistema. Asegúrese de probar antes y después, dejando solo will-change
en la hoja de estilo si obtiene un mejor rendimiento. Para profundizar en cómo funciona esta propiedad y cuándo debe o no debe usarla, consulte el excelente artículo de Sara Soueidan en https://dev.opera.com/articles/css-will-change-property/.
Debo señalar que una cosa ha cambiado desde que se escribió este artículo: establece que solo las transformaciones 3D promueven un elemento a su propia capa. Este ya no es el caso; los navegadores más recientes ahora también usan aceleración de GPU para transformaciones 2D.
Al realizar la transición o la animación, que veremos en el próximo capítulo, intente hacer cambios solo para transform
y opacity
. Luego, si es necesario, puede cambiar las propiedades que dan como resultado una pintura pero no un rediseño. Solo cambie las propiedades que afecten al diseño cuando sea su única opción y mírelas primero si alguna vez nota problemas de rendimiento con sus animaciones. Para obtener un desglose completo de las propiedades que dan como resultado el diseño, la pintura y / o el compuesto, consulte https://csstriggers.com/.
15.4. TRANSFORMACIONES TRIDIMENSIONALES (3D)
Hasta ahora, las transformaciones que ha utilizado son todas 2D. Estos son los más fáciles de trabajar (y los más comunes) ya que la página en sí es 2D. Pero no está confinado a esta limitación. La rotación y la traslación se pueden realizar en las tres dimensiones: X, Y y Z.
Puede usar la función translate()
, como ha visto, para traducir horizontal y verticalmente (dimensiones X e Y). Esto también se puede hacer con las funciones translateX()
y translateY()
. Las siguientes dos declaraciones producen el mismo resultado:
transform: translate(15px, 50px);
transform: translateX(15px) translateY(50px);
También puede traducir en la dimensión Z usando translateZ()
, que mueve un elemento conceptualmente más cerca o más lejos del usuario. Del mismo modo, puede rotar un elemento alrededor de ejes en las tres dimensiones. Pero, a diferencia de translate, rotateZ()
es la versión con la que ya estás familiarizado; es decir, rotate()
también tiene un alias como rotateZ()
porque gira alrededor del eje Z. Las funciones rotateX()
y rotateY()
giran alrededor del eje X horizontal (inclinando un elemento hacia adelante y hacia atrás) y alrededor del eje Y vertical (girando — o guiñando — el elemento hacia la izquierda o hacia la derecha), respectivamente. Consulte la figura 15.13 para ver una ilustración de estas funciones.

15.4.1. Controlando la perspectiva
Sin embargo, antes de agregar transformaciones 3D a la página, debe especificar una cosa más: la perspectiva. Los elementos transformados juntos forman una escena 3D. Luego, el navegador calcula una imagen 2D de esta escena 3D y la muestra en la pantalla. Puede pensar en la perspectiva como la distancia entre la "cámara" y la escena. Mover la cámara cambia la forma en que aparece la escena en la imagen final.
Si la cámara está cerca (es decir, la perspectiva es pequeña), los efectos 3D son mucho más fuertes. Si la cámara está lejos (es decir, la perspectiva es grande), los efectos 3D son mucho más sutiles. En la figura 15.14 se muestran algunas perspectivas diferentes.

El elemento girado de la izquierda, sin una perspectiva aplicada, no se ve en 3D. Aparece aplastado horizontalmente; no hay una sensación real de profundidad. Las transformaciones 3D sin perspectiva aparecen planas así; las partes del elemento que están "más lejos" no aparecen más pequeñas. Por otro lado, el cuadro del medio tiene aplicada una perspectiva de 400px
. Su borde derecho, el borde que está más lejos del espectador, parece un poco más pequeño y el borde que está más cerca parece más grande. La perspectiva aplicada al cuadro de la derecha es mucho más corta, 100px
. Esto exagera el efecto, por lo que el borde del elemento más alejado se contrae drásticamente en la distancia.
Puede especificar esta distancia de perspectiva de dos formas: utilizando una transformación de perspective()
o utilizando la propiedad perspective
. Cada uno se comporta un poco diferente. Juntemos un ejemplo básico para ilustrar. Este ejemplo será mínimo, solo para mostrar los efectos de la perspectiva.
Primero, rotará cuatro elementos, inclinándolos hacia atrás usando rotateX()
(figura 15.15). Cada elemento se rota de la misma manera y se aplica la misma transformación de perspective()
; por tanto, los cuatro elementos parecen iguales.

Cree una nueva página para esta demostración y cópiela en el HTML que se muestra aquí.
<div class="row">
<div class="box">One</div>
<div class="box">Two</div>
<div class="box">Three</div>
<div class="box">Four</div>
</div>
Listado 15.11. Cuatro cuadros para ayudar a ilustrar las transformaciones 3D y la perspectiva
A continuación, aplicará una transformación 3D y una transformación de perspectiva a cada uno de los cuadros. También agregará color y relleno para completar un poco el tamaño y para ayudar a que el efecto sea más evidente. Agregue una hoja de estilo a la página con el código que se muestra en esta lista.
.row {
display: flex;
justify-content: center;
}
.box {
box-sizing: border-box;
width: 150px;
margin: 0 2em;
padding: 60px 0;
text-align: center;
background-color: hsl(150, 50%, 40%);
transform: perspective(200px) rotateX(30deg); 1
}
Listado 15.12. Aplicar transformaciones 3D a las cajas
- Gira el cuadro 30 grados hacia atrás y aplica una perspectiva
En este ejemplo, todos los cuadros tienen el mismo aspecto. Cada uno tiene su propia perspectiva, aplicada mediante la función perspective()
. Este método aplica una perspectiva a un solo elemento; en este ejemplo, lo ha aplicado directamente a cada cuadro. Es como si se tomaran cuatro fotografías distintas de cada elemento, cada una desde la misma posición.
A veces querrá que varios elementos compartan una perspectiva común, como si todos existieran dentro del mismo espacio 3D. La figura 15.16 muestra una ilustración de esto. Estos son los mismos cuatro elementos, pero todos alcanzan la distancia hacia un punto de fuga común. Es como si se tomara una foto de los cuatro elementos juntos. Para lograr este efecto, utilizará la propiedad perspective
en su elemento principal.

Para ver este efecto, elimine la función perspective()
de los cuadros y, en su lugar, agréguela al contenedor usando la propiedad perspective
. Estos cambios se muestran aquí.
.row {
display: flex;
justify-content: center;
perspective: 200px; 1
}
.box {
box-sizing: border-box;
width: 150px;
margin: 0 2em;
padding: 60px 0;
text-align: center;
background-color: hsl(150, 50%, 40%);
transform: rotateX(30deg); 2
}
Listado 15.13. Establecer una perspectiva común
- Agrega la perspectiva al contenedor
- No apliques una transformación de perspectiva a los cuadros
Al aplicar una perspectiva común al contenedor principal (u otro antepasado), todos los elementos dentro del principal que tienen aplicadas transformaciones 3D compartirán esa perspectiva.
Agregar una perspectiva es una parte importante de las transformaciones 3D. Sin él, los elementos más alejados del espectador no aparecerán más pequeños y los que estén más cerca no aparecerán más grandes. Este ejemplo es bastante mínimo. En el próximo capítulo, usará estas técnicas en un ejemplo más práctico para "volar" algunos elementos en la página desde la distancia.
15.4.2. Implementación de transformaciones 3D avanzadas
Algunas otras propiedades pueden resultar útiles al manipular elementos en 3D. No dedicaré mucho tiempo a esto, ya que los casos de uso del mundo real son pocos y distantes entre sí. Pero es bueno saber que existen en caso de que alguna vez los necesite. Le señalaré algunos ejemplos en línea si desea profundizar.
De forma predeterminada, la perspectiva se representa como si el espectador (o la cámara) estuviese colocada directamente delante del centro del elemento. La propiedad perspective-origin
desplaza la posición de la cámara hacia la izquierda o hacia la derecha y hacia arriba o hacia abajo. La figura 15.17 muestra el ejemplo anterior, pero con la cámara desplazada hacia la parte inferior izquierda.

Para ver esto en su página de muestra, agregue la declaración en este listado.
.row {
display: flex;
justify-content: center;
perspective: 200px;
perspective-origin: left bottom; 1
}
Listado 15.14. Usar perspective-origin para mover la posición de la cámara
- Mueve la posición de la cámara a la parte inferior izquierda del elemento.
Esta es la misma distancia de perspectiva que antes, pero aquí la perspectiva se desplaza para que todos los cuadros estén a la derecha del espectador. Puede especificar la posición utilizando las palabras clave top
, left
, bottom
, right
y center
. También puede utilizar cualquier porcentaje o valor de longitud, medido desde la esquina superior izquierda del elemento (perspective-origin: 25% 25%,
por ejemplo).
Si usa rotateX()
o rotateY()
para girar un elemento más de 90 grados, sucede algo interesante: la "cara" del elemento ya no está dirigida hacia usted. En cambio, está de espaldas y ves la parte posterior del elemento. El elemento de la figura 15.18 se ha transformado con rotateY(180deg)
. Parece una imagen especular del original.

Esta es la cara posterior del elemento. De forma predeterminada, la cara posterior es visible, pero puede cambiar esto aplicando backface-visibility: hidden
al elemento. Con esta declaración aplicada, el elemento solo será visible si está mirando hacia el espectador y oculto si está mirando hacia otro lado.
Una posible aplicación de esta técnica es colocar dos elementos uno al lado del otro, como los dos lados de una tarjeta. La parte frontal de la tarjeta será visible, pero la parte posterior de la tarjeta estará oculta. Luego, puede rotar su elemento contenedor para voltear ambos elementos, haciendo que el frente esté oculto y la parte posterior visible. Para ver una demostración de este efecto de giro de tarjeta, consulte el artículo en https://desandro.github.io/3dtransforms/docs/card-flip.html.
La propiedad transform-style
se vuelve importante si va a construir escenas complejas con elementos anidados en 3D. Supongamos que ha establecido una perspectiva en un contenedor y luego ha aplicado transformaciones 3D a los elementos que contiene. Ese elemento contenedor, cuando se renderice, será una representación 2D de esa escena. Es como una fotografía de un objeto 3D. Esto se ve bien porque ese elemento debe renderizarse en su pantalla 2D.
Si luego aplica una rotación 3D en el contenedor, no se verá bien. En lugar de rotar toda la escena, parecerá que está rotando una fotografía 2D de una escena 3D. La perspectiva estará equivocada y la ilusión de profundidad en la escena se hará añicos. Consulte la figura 15.19 para ver un ejemplo que ilustra esto.

La escena renderizada a la izquierda muestra un cubo 3D creado al transformar sus seis lados en su lugar. La imagen del medio muestra lo que sucede si intenta transformar todo el cubo junto (es decir, el elemento principal). Para corregir esto, debe aplicar transform-style: preserve-3d
al elemento padre (derecha).
El estilo de transformación preserve-3d
no es compatible con ninguna versión de Internet Explorer.
Para obtener una explicación más completa de esto, así como ejemplos de trabajo, visite el tutorial de Ana Tudor en https://davidwalsh.name/3d-transforms. Aunque es divertido jugar con ejemplos como este, nunca he necesitado usar preserve-3d
en un proyecto del mundo real. Pero si decide jugar con las transformaciones 3D solo para ver qué puede construir, puede encontrar útil el tutorial.
RESUMEN
- Utilice transformaciones para escalar, rotar, trasladar y sesgar elementos en dos y tres dimensiones.
- Las transformaciones son esenciales para las transiciones y animaciones de alto rendimiento.
- Comprenda cómo funciona la canalización de renderizado y téngalo en cuenta al crear animaciones.
- Para usar una curva de función de temporización personalizada para agregar un efecto de rebote a las transiciones.