{"id":3405,"date":"2026-10-24T15:41:51","date_gmt":"2026-10-24T15:41:51","guid":{"rendered":"https:\/\/alexcgdesign.com\/blog\/?p=3405"},"modified":"2026-10-27T19:45:21","modified_gmt":"2026-10-27T19:45:21","slug":"transiciones-css","status":"publish","type":"post","link":"https:\/\/alexcgdesign.com\/blog\/transiciones-css\/","title":{"rendered":"Transiciones en CSS desde cero: transition paso a paso"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Las <strong>transiciones en CSS<\/strong> son lo que hace que un men\u00fa se abra suave en lugar de aparecer de golpe. En este tutorial desde cero aprendes a usar <code>transition<\/code> con un proyecto real: un sidebar que se oculta con un bot\u00f3n y un buscador hecho con <code>popover<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Vas a entender las cuatro propiedades que forman una transici\u00f3n, cu\u00e1ndo usar <code>cubic-bezier()<\/code> y <code>linear()<\/code>, y c\u00f3mo animar <code>display: none<\/code>, algo que hasta hace poco era imposible en CSS. Todo con el playground que hice para este video, donde puedes probar cada curva antes de copiarla.<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe title=\"\u274c NO Subestimes Transition en CSS (Tutorial desde CERO)\" width=\"1290\" height=\"726\" src=\"https:\/\/www.youtube.com\/embed\/aI_JPJAVXvk?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n\n\n\n<div class=\"wp-block-buttons is-content-justification-center is-layout-flex wp-container-core-buttons-is-layout-fe0a7de2 wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button is-style-outline is-style-outline--1\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/www.youtube.com\/watch?v=aI_JPJAVXvk\" target=\"_blank\" rel=\"noreferrer noopener\">Ver el video en YouTube<\/a><\/div>\n<\/div>\n\n\n\n<div class=\"wp-block-group acg-callout is-layout-flow wp-block-group-is-layout-flow\">\n<p class=\"acg-callout__title wp-block-paragraph\">En este tutorial<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Resultado:<\/strong> un sidebar que se oculta con transici\u00f3n y un buscador con <code>popover<\/code> que aparece y desaparece animado<\/li>\n\n\n\n<li><strong>Tecnolog\u00edas:<\/strong> HTML y CSS (sin JavaScript)<\/li>\n\n\n\n<li><strong>Aprendes:<\/strong> <code>transition-property<\/code>, <code>duration<\/code>, <code>timing-function<\/code>, <code>delay<\/code>, el shorthand, <code>transition-behavior<\/code> y <code>@starting-style<\/code><\/li>\n\n\n\n<li><strong>Nivel:<\/strong> principiante<\/li>\n\n\n\n<li><a href=\"#codigo-fuente\">Ir directo al c\u00f3digo fuente<\/a><\/li>\n<\/ul>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Qu\u00e9 vas a construir<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Dos ejemplos. El primero es <strong>Brote<\/strong>, el sidebar de una tienda de plantas: al pulsar \u00abOcultar\u00bb, el men\u00fa baja y se recorta con un retraso calculado. El segundo es un <strong>buscador tipo paleta de comandos<\/strong> que se abre con un bot\u00f3n, entra desde abajo con un fundido y sale igual, todo con HTML y CSS.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Qu\u00e9 necesitas<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Un editor de c\u00f3digo, por ejemplo VS Code con Live Server<\/li>\n\n\n\n<li>HTML y CSS b\u00e1sicos: selectores, propiedades y pseudoclases<\/li>\n\n\n\n<li>El playground de transiciones, para probar las curvas: <a href=\"https:\/\/transiciones.cursocss.com\" target=\"_blank\" rel=\"noopener\">transiciones.cursocss.com<\/a><\/li>\n\n\n\n<li>Un navegador actualizado (Chrome, Edge, Safari o Firefox recientes) para <code>transition-behavior<\/code> y <code>@starting-style<\/code><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Paso a paso<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\u00bfQu\u00e9 es una transici\u00f3n en CSS?<\/strong> Una transici\u00f3n (<code>transition<\/code>) es el cambio gradual de una propiedad entre un <strong>estado A<\/strong> y un <strong>estado B<\/strong>, en vez de instant\u00e1neo. Sin transici\u00f3n, el fondo del sidebar pasa de blanco a rojo en 0 segundos; con transici\u00f3n, el navegador calcula los pasos intermedios durante el tiempo que le digas. Solo necesitas un estado inicial con la transici\u00f3n declarada, un estado final y algo que dispare el cambio.<\/p>\n\n\n\n<div class=\"wp-block-group acg-steps is-layout-flow wp-block-group-is-layout-flow\">\n<div class=\"wp-block-group acg-step is-layout-flow wp-block-group-is-layout-flow\">\n<h3 class=\"wp-block-heading\">1. El disparador: qu\u00e9 hace que cambie el estado<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Para que una transici\u00f3n ocurra necesitas un <strong>disparador<\/strong>: algo que provoque el paso del estado A al B. En JavaScript ser\u00eda un evento, como un clic. En CSS es una pseudoclase como <code>:hover<\/code>, <code>:focus<\/code> o <code>:checked<\/code>, y con <code>:has()<\/code> ese cambio llega al elemento padre.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En el sidebar, el bot\u00f3n \u00abOcultar\u00bb es un checkbox. El selector pregunta: si <code>.app<\/code> tiene un <code>.toggle__input<\/code> marcado, cambia el sidebar. Ese es el estado final.<\/p>\n\n\n\n<pre class=\"wp-block-code language-css\"><code>.app:has(.toggle__input:checked) .sidebar {\n    background-color: red;\n}<\/code><\/pre>\n<\/div>\n\n\n\n<div class=\"wp-block-group acg-step is-layout-flow wp-block-group-is-layout-flow\">\n<h3 class=\"wp-block-heading\">2. transition-property y transition-duration<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><code>transition-property<\/code> define <strong>qu\u00e9<\/strong> propiedades se animan. Su valor por defecto es <code>all<\/code>, pero con eso solo no ves nada: falta <code>transition-duration<\/code>, que dice <strong>cu\u00e1nto<\/strong> dura. Acepta segundos (<code>1s<\/code>) o milisegundos (<code>1000ms<\/code>).<\/p>\n\n\n\n<pre class=\"wp-block-code language-css\"><code>.sidebar {\n    transition-property: all;\n    transition-duration: 1000ms;\n}<\/code><\/pre>\n<\/div>\n\n\n\n<div class=\"wp-block-group acg-callout acg-callout--warn is-layout-flow wp-block-group-is-layout-flow\">\n<p class=\"acg-callout__title wp-block-paragraph\">Ojo con transition: all<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Con <code>all<\/code> se anima todo lo que cambie, hasta un <code>margin<\/code>. Eso consume recursos del navegador. Adem\u00e1s, animar <code>margin<\/code> o <code>top<\/code>, <code>left<\/code>, <code>right<\/code> y <code>bottom<\/code> recalcula el layout y afecta al rendimiento. Anima solo lo imprescindible, y si algo se mueve usa <code>transform<\/code> y <code>opacity<\/code>.<\/p>\n<\/div>\n\n\n\n<div class=\"wp-block-group acg-step is-layout-flow wp-block-group-is-layout-flow\">\n<h3 class=\"wp-block-heading\">3. Mover elementos con transform: translate()<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><code>translate()<\/code> mueve el elemento sin tocar el layout. El primer valor es el eje X (positivo a la derecha, negativo a la izquierda) y el segundo el eje Y (positivo hacia abajo, negativo hacia arriba). Con <code>translateY(100%)<\/code> lo bajas el 100 % de su propia altura.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00edjate en que ahora <code>transition-property<\/code> nombra solo <code>transform<\/code> y <code>opacity<\/code>: es la forma recomendada.<\/p>\n\n\n\n<pre class=\"wp-block-code language-css\"><code>.sidebar {\n    transform: translateY(0);\n\n    transition-property: transform, opacity;\n    transition-duration: 1000ms;\n}\n\n.app:has(.toggle__input:checked) .sidebar {\n    transform: translateY(100%);\n}<\/code><\/pre>\n<\/div>\n\n\n\n<div class=\"wp-block-group acg-step is-layout-flow wp-block-group-is-layout-flow\">\n<h3 class=\"wp-block-heading\">4. transition-timing-function: c\u00f3mo progresa la animaci\u00f3n<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Si la transici\u00f3n dura 2 segundos, en el segundo 2 siempre estar\u00e1 en su estado final. Lo que cambias con <code>transition-timing-function<\/code> es <strong>c\u00f3mo<\/strong> progresa por el camino. Los valores por defecto son:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>ease<\/code> (por defecto): arranca r\u00e1pido y frena suave<\/li>\n\n\n\n<li><code>linear<\/code>: velocidad constante<\/li>\n\n\n\n<li><code>ease-in<\/code>: arranca lento y termina r\u00e1pido<\/li>\n\n\n\n<li><code>ease-out<\/code>: arranca r\u00e1pido y frena al final<\/li>\n\n\n\n<li><code>ease-in-out<\/code>: lento al inicio y al final<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code language-css\"><code>.sidebar {\n    transition-property: transform, opacity;\n    transition-duration: 1000ms;\n    transition-timing-function: ease-in;\n}<\/code><\/pre>\n<\/div>\n\n\n\n<div class=\"wp-block-group acg-step is-layout-flow wp-block-group-is-layout-flow\">\n<h3 class=\"wp-block-heading\">5. cubic-bezier() y linear(): curvas a tu medida<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><code>cubic-bezier()<\/code> dibuja la curva de la animaci\u00f3n con cuatro n\u00fameros. En la gr\u00e1fica, el eje horizontal es el tiempo y el vertical, el progreso. Esta curva empieza muy lenta y termina de golpe:<\/p>\n\n\n\n<pre class=\"wp-block-code language-css\"><code>transition-timing-function: cubic-bezier(1.00, 0.03, 0.76, 0.11);<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Si un valor de Y se sale del rango 0\u20131, la animaci\u00f3n <strong>retrocede y rebota<\/strong> antes de llegar al final:<\/p>\n\n\n\n<pre class=\"wp-block-code language-css\"><code>transition-timing-function: cubic-bezier(0.31, -0.97, 0.69, 2.00);<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><code>linear()<\/code> es otra forma de controlar la velocidad: le das puntos de progreso, donde <code>0<\/code> es el inicio y <code>1<\/code> el final. Aqu\u00ed va al final, regresa al 25 % y vuelve a terminar:<\/p>\n\n\n\n<pre class=\"wp-block-code language-css\"><code>transition-timing-function: linear(\n    0,\n    1,\n    0.25,\n    1\n);<\/code><\/pre>\n<\/div>\n\n\n\n<div class=\"wp-block-group acg-callout acg-callout--tip is-layout-flow wp-block-group-is-layout-flow\">\n<p class=\"acg-callout__title wp-block-paragraph\">Consejo<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Nadie se aprende las curvas de B\u00e9zier de memoria. Usa un generador, como el de <a href=\"https:\/\/transiciones.cursocss.com\" target=\"_blank\" rel=\"noopener\">transiciones.cursocss.com<\/a>, copia la funci\u00f3n y p\u00e9gala. En la mayor\u00eda de los proyectos, <code>ease<\/code> es suficiente.<\/p>\n<\/div>\n\n\n\n<div class=\"wp-block-group acg-step is-layout-flow wp-block-group-is-layout-flow\">\n<h3 class=\"wp-block-heading\">6. transition-delay: cu\u00e1nto espera antes de empezar<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><code>transition-delay<\/code> retrasa el inicio. Lo potente es darle un retraso distinto a cada propiedad, en el mismo orden que <code>transition-property<\/code>. Aqu\u00ed el sidebar primero baja con <code>transform<\/code> y, un segundo despu\u00e9s, se recorta con <code>clip-path<\/code> (el pol\u00edgono sale del generador <a href=\"https:\/\/bennettfeely.com\/clippy\/\" target=\"_blank\" rel=\"noopener\">Clippy<\/a>):<\/p>\n\n\n\n<pre class=\"wp-block-code language-css\"><code>.sidebar {\n    clip-path: polygon(0 0, 100% 0, 100% 100%, 0% 100%);\n    transform: translateY(0);\n\n    transition-property: transform, clip-path;\n    transition-duration: 1000ms;\n    transition-timing-function: ease;\n    transition-delay: 0s, 1s;\n}\n\n.app:has(.toggle__input:checked) .sidebar {\n    transform: translateY(100%);\n    clip-path: polygon(0 0, 100% 0, 100% 0, 0 0);\n}<\/code><\/pre>\n<\/div>\n\n\n\n<div class=\"wp-block-group acg-callout acg-callout--warn is-layout-flow wp-block-group-is-layout-flow\">\n<p class=\"acg-callout__title wp-block-paragraph\">Error t\u00edpico: 0 sin unidad<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En la lista de <code>transition-delay<\/code> escribe <code>0s<\/code>, no <code>0<\/code>. Los tiempos en CSS necesitan unidad: con <code>0<\/code> la declaraci\u00f3n no es v\u00e1lida y el retraso no se aplica.<\/p>\n<\/div>\n\n\n\n<div class=\"wp-block-group acg-step is-layout-flow wp-block-group-is-layout-flow\">\n<h3 class=\"wp-block-heading\">7. El shorthand transition: todo en una l\u00ednea<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Todo lo anterior cabe en <code>transition<\/code>: propiedad, duraci\u00f3n, funci\u00f3n y retraso, separados por espacios, y cada propiedad separada por comas. Lo que coincide con el valor por defecto (<code>ease<\/code>, retraso <code>0s<\/code>) no hace falta escribirlo.<\/p>\n\n\n\n<pre class=\"wp-block-code language-css\"><code>transition: transform 1s, clip-path 1s 1s;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">En cada propiedad, el primer tiempo es la duraci\u00f3n y el segundo, el retraso: <code>clip-path 1s 1s<\/code> dura un segundo y espera otro antes de empezar. Esta l\u00ednea hace exactamente lo mismo que las cuatro propiedades del paso anterior.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En el repositorio, la versi\u00f3n final va un paso m\u00e1s all\u00e1: cada estado tiene su propio <code>transition<\/code>. Al ocultarse, el sidebar primero baja y luego se recorta; al volver, primero se descubre y luego sube. La transici\u00f3n que se aplica es siempre la del estado al que vas.<\/p>\n\n\n\n<pre class=\"wp-block-code language-css\"><code>.sidebar {\n    transition: clip-path 1s 0s, transform 1s 1s;\n}\n\n.app:has(.toggle__input:checked) .sidebar {\n    transform: translateY(300px);\n    clip-path: polygon(0 0, 100% 0, 100% 0, 0 0);\n    transition: transform 1s 0s, clip-path 1s 1s;\n}<\/code><\/pre>\n<\/div>\n\n\n\n<div class=\"wp-block-group acg-cta acg-cta--sponsor is-layout-flow wp-block-group-is-layout-flow\">\n<p class=\"acg-cta__eyebrow wp-block-paragraph\">Patrocinador oficial del curso<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Publica tus proyectos con Hostinger<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">El playground de transiciones de este video lo hice con el AI Builder de Hostinger. Con el cup\u00f3n <strong>ALEXCG<\/strong> tienes un 10 % de descuento extra en tu hosting.<\/p>\n\n\n\n<div class=\"wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/hostinger.com\/alexcg\" target=\"_blank\" rel=\"sponsored noopener\">Obtener el descuento<\/a><\/div>\n<\/div>\n<\/div>\n\n\n\n<div class=\"wp-block-group acg-step is-layout-flow wp-block-group-is-layout-flow\">\n<h3 class=\"wp-block-heading\">8. Ejemplo avanzado: un buscador con popover<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">El atributo <code>popover<\/code> esconde el elemento y lo prepara para mostrarse despu\u00e9s. El bot\u00f3n con <code>popovertarget<\/code> apunta al <code>id<\/code> del elemento que abre. Sin una l\u00ednea de JavaScript:<\/p>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;!-- Bot\u00f3n de buscar --&gt;\n&lt;button class=\"search-btn\" popovertarget=\"palette\"&gt;\n  Buscar\n&lt;\/button&gt;\n\n&lt;!-- Buscador --&gt;\n&lt;section class=\"palette\" id=\"palette\" popover&gt;\n  &lt;search class=\"palette__search\"&gt;\n    &lt;input type=\"search\" autofocus placeholder=\"Escribe un comando o busca\u2026\"&gt;\n    &lt;kbd&gt;esc&lt;\/kbd&gt;\n  &lt;\/search&gt;\n&lt;\/section&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u00bfEl problema? Por detr\u00e1s, HTML pasa de <code>display: none<\/code> a <code>display: block<\/code> (con la pseudoclase <code>:popover-open<\/code>). Y <code>display<\/code> es una propiedad discreta: si le pones una transici\u00f3n, no pasa nada.<\/p>\n<\/div>\n\n\n\n<div class=\"wp-block-group acg-step is-layout-flow wp-block-group-is-layout-flow\">\n<h3 class=\"wp-block-heading\">9. Animar display con transition-behavior: allow-discrete<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/developer.mozilla.org\/es\/docs\/Web\/CSS\/transition-behavior\" target=\"_blank\" rel=\"noopener\"><code>transition-behavior: allow-discrete<\/code><\/a> permite incluir <code>display<\/code> en la transici\u00f3n. En realidad no lo anima: retrasa el cambio a <code>none<\/code> lo que dure la transici\u00f3n, y eso da tiempo a que <code>transform<\/code> y <code>opacity<\/code> se animen al cerrar.<\/p>\n\n\n\n<pre class=\"wp-block-code language-css\"><code>.palette {\n  display: none;\n  transform: translateY(100%);\n  opacity: 0;\n\n  transition-property: display, transform, opacity;\n  transition-duration: .5s;\n  transition-behavior: allow-discrete;\n}\n\n.palette:popover-open {\n  display: block;\n  transform: translateY(0);\n  opacity: 1;\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Si quitas <code>transition-behavior<\/code>, todo vuelve a ser de golpe. Con \u00e9l, al cerrar, el buscador baja y se desvanece. En Chrome y Edge puedes a\u00f1adir tambi\u00e9n <code>overlay<\/code> a <code>transition-property<\/code> para que el popover no salga de la capa superior antes de tiempo. Lo explico m\u00e1s a fondo en <a href=\"https:\/\/alexcgdesign.com\/blog\/3-caracteristicas-css\/\">3 caracter\u00edsticas de CSS que no conoc\u00edas<\/a>.<\/p>\n<\/div>\n\n\n\n<div class=\"wp-block-group acg-step is-layout-flow wp-block-group-is-layout-flow\">\n<h3 class=\"wp-block-heading\">10. @starting-style en CSS: la animaci\u00f3n de entrada<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Falta la entrada: de <code>display: none<\/code> a <code>block<\/code> no hay un estado anterior del que partir. <a href=\"https:\/\/developer.mozilla.org\/es\/docs\/Web\/CSS\/@starting-style\" target=\"_blank\" rel=\"noopener\"><code>@starting-style<\/code><\/a> define los estilos que tiene el elemento <strong>justo antes de mostrarse<\/strong>, y desde ah\u00ed se anima.<\/p>\n\n\n\n<pre class=\"wp-block-code language-css\"><code>.palette:popover-open {\n  display: block;\n  transform: translateY(0);\n  opacity: 1;\n\n  @starting-style {\n    opacity: 0;\n    transform: translateY(100%);\n  }\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Con esto el buscador entra desde abajo con un fundido y sale igual.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Resumen:<\/strong> <code>transition<\/code> = propiedad + duraci\u00f3n + curva + retraso. Para animar <code>display<\/code>, <code>allow-discrete<\/code>. Para la entrada, <code>@starting-style<\/code>.<\/p>\n<\/div>\n<\/div>\n\n\n\n<h2 id=\"codigo-fuente\" class=\"wp-block-heading\">C\u00f3digo fuente<\/h2>\n\n\n\n<div class=\"wp-block-group acg-download is-layout-flow wp-block-group-is-layout-flow\">\n<p class=\"wp-block-paragraph\">El repositorio incluye los dos proyectos del video: el sidebar Brote con todas las transiciones y el buscador con <code>popover<\/code>, <code>transition-behavior<\/code> y <code>@starting-style<\/code>.<\/p>\n\n\n\n<div class=\"wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/github.com\/AlexCGDesign\/transiciones-curso-cero\" target=\"_blank\" rel=\"noopener\">Descargar el c\u00f3digo en GitHub<\/a><\/div>\n<\/div>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Preguntas frecuentes<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\u00bfQu\u00e9 es transition en CSS y para qu\u00e9 sirve?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><code>transition<\/code> hace que el cambio de una propiedad CSS ocurra de forma gradual en lugar de instant\u00e1nea. Sirve para que men\u00fas, botones, modales o tarjetas pasen de un estado a otro con suavidad. Se compone de cuatro propiedades principales: <code>transition-property<\/code>, <code>transition-duration<\/code>, <code>transition-timing-function<\/code> y <code>transition-delay<\/code>, que puedes escribir juntas con el shorthand <code>transition<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u00bfPor qu\u00e9 no funciona mi transition en CSS?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Las causas m\u00e1s comunes son tres: falta <code>transition-duration<\/code> (por defecto es 0), la propiedad que cambias no se puede animar (como <code>display<\/code> sin <code>allow-discrete<\/code>), o el elemento no cambia de estado porque el disparador no coincide (revisa el selector). Revisa tambi\u00e9n que los tiempos lleven unidad: <code>0s<\/code>, no <code>0<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u00bfC\u00f3mo se anima display: none en CSS?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A\u00f1ade <code>display<\/code> a <code>transition-property<\/code> y usa <code>transition-behavior: allow-discrete<\/code>: as\u00ed el cambio a <code>none<\/code> espera a que termine la transici\u00f3n. Para la entrada, define el estado de partida dentro de <code>@starting-style<\/code>. Funciona en las versiones recientes de Chrome, Edge, Safari y Firefox.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u00bfQu\u00e9 diferencia hay entre transition y animation en CSS?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><code>transition<\/code> anima el paso entre dos estados y necesita un disparador, como <code>:hover<\/code>, <code>:checked<\/code> o una clase. <code>animation<\/code> usa <code>@keyframes<\/code>, puede tener muchos pasos, repetirse y arrancar sola al cargar la p\u00e1gina. Para abrir y cerrar elementos, <code>transition<\/code> suele bastar.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">M\u00e1s proyectos<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/alexcgdesign.com\/blog\/3-caracteristicas-css\/\">3 caracter\u00edsticas de CSS: @starting-style, transition-behavior y m\u00e1s<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/alexcgdesign.com\/blog\/animar-variables-css-property\/\">Animaciones avanzadas en CSS con @property<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/alexcgdesign.com\/blog\/selectores-hermano-css\/\">Selectores avanzados de CSS: selectores hermanos<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/alexcgdesign.com\/blog\/dropdown-css\/\">Men\u00fa dropdown con CSS<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/alexcgdesign.com\/blog\/centrar-en-css\/\">C\u00f3mo centrar en CSS (7 maneras)<\/a><\/li>\n<\/ul>\n\n\n\n<div class=\"wp-block-group acg-cta is-layout-flow wp-block-group-is-layout-flow\">\n<p class=\"acg-cta__eyebrow wp-block-paragraph\">Curso en vivo<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Domina CSS desde cero<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Muy pronto empiezo un curso de CSS en vivo, de cero a profundidad. Reg\u00edstrate y te aviso de todas las novedades.<\/p>\n\n\n\n<div class=\"wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/cursocss.com\" target=\"_blank\" rel=\"noopener\">Quiero enterarme<\/a><\/div>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Aprende transiciones en CSS desde cero: transition, cubic-bezier, linear() y c\u00f3mo animar display none con allow-discrete y @starting-style. Con c\u00f3digo.<\/p>\n","protected":false},"author":1,"featured_media":3419,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acg_migrated":"2026-10-24","footnotes":""},"categories":[39,2],"tags":[],"class_list":["post-3405","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-css-tutoriales","category-diseno-web"],"blocksy_meta":{"styles_descriptor":{"styles":{"desktop":"","tablet":"","mobile":""},"google_fonts":[],"version":7}},"_links":{"self":[{"href":"https:\/\/alexcgdesign.com\/blog\/wp-json\/wp\/v2\/posts\/3405","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/alexcgdesign.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/alexcgdesign.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/alexcgdesign.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/alexcgdesign.com\/blog\/wp-json\/wp\/v2\/comments?post=3405"}],"version-history":[{"count":4,"href":"https:\/\/alexcgdesign.com\/blog\/wp-json\/wp\/v2\/posts\/3405\/revisions"}],"predecessor-version":[{"id":3410,"href":"https:\/\/alexcgdesign.com\/blog\/wp-json\/wp\/v2\/posts\/3405\/revisions\/3410"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/alexcgdesign.com\/blog\/wp-json\/wp\/v2\/media\/3419"}],"wp:attachment":[{"href":"https:\/\/alexcgdesign.com\/blog\/wp-json\/wp\/v2\/media?parent=3405"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/alexcgdesign.com\/blog\/wp-json\/wp\/v2\/categories?post=3405"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/alexcgdesign.com\/blog\/wp-json\/wp\/v2\/tags?post=3405"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}