2 puntos por GN⁺ 2024-09-05 | 1 comentarios | Compartir por WhatsApp
  • Como CSS @property ya es compatible en todos los navegadores modernos, ahora se puede especificar en las propiedades personalizadas la sintaxis, el valor inicial y si se heredan, y permitir que el navegador interpole los valores de forma natural
  • El botón CTA de ejemplo define --gradient-angle como <angle> para hacer la transición de 0deg a 360deg y crear un borde brillante giratorio con conic-gradient
  • El efecto hover asigna tipos a propiedades como --gradient-percent, --gradient-angle-offset y --gradient-shine para que la longitud y el brillo del destello cambien suavemente
  • La velocidad de rotación se controla declarando dos veces la misma animación: la segunda queda en dirección inversa y pausada, y en hover se ralentiza a la mitad desde la posición actual
  • Definir propiedades personalizadas basadas en @property habilita expresiones de CSS que antes eran difíciles de implementar y también tiene potencial de uso en aplicaciones grandes y sistemas de diseño

Animación de propiedades personalizadas habilitada por @property

  • @property es una regla que permite especificar la sintaxis admitida, el valor inicial y si una propiedad personalizada se hereda
  • Está vinculada a la CSS Properties and Values API de CSS Houdini y recientemente pasó a estar soportada en todos los navegadores modernos
  • Si el navegador conoce el tipo de una propiedad personalizada, puede interpolar entre valores, lo que facilita crear transiciones y animaciones más suaves que usando solo variables CSS comunes

Borde brillante giratorio para un botón CTA

  • El ejemplo implementa en CSS el estilo de un botón CTA brillante que se ve con frecuencia en la web
  • La propiedad personalizada clave es --gradient-angle, y con @property se declaran la sintaxis <angle> y el valor inicial 0deg
@property --gradient-angle {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}
  • Gracias a esta definición, el navegador puede hacer una transición natural de 0deg a 360deg, renderizando el conic-gradient como si estuviera girando
@keyframes rotate-gradient {
  to { --gradient-angle: 360deg; }
}

.rotate-gradient {
  background: conic-gradient(from var(--gradient-angle), transparent, black);
  animation: rotate-gradient 10s linear infinite;
}
  • En el demo de CodePen se puede ver este concepto con el mínimo de código

Un brillo de borde creado con capas de fondo

  • El borde brillante se construye combinando linear-gradient y conic-gradient en background, asignando un origen distinto a cada fondo
    • linear-gradient usa padding-box, por lo que no se desborda hacia el área del borde
    • conic-gradient usa border-box, así que se extiende hasta el espacio creado por el grosor del borde
    • Se añade un borde transparente de 1px para que el conic-gradient giratorio quede visible
.border-gradient {
  background:
    linear-gradient(black, black) padding-box,
    conic-gradient(from var(--gradient-angle), transparent 25%, white, transparent 50%) border-box;
  border: 1px solid transparent;
}

Un gradiente que cambia suavemente al hacer hover

  • Para cada propiedad personalizada necesaria en la transición de hover, se declara syntax en @property para que el navegador pueda interpolar los cambios de valor
  • El fondo del botón está compuesto por un linear-gradient para el color interior y un conic-gradient para el brillo del borde
  • --gradient-percent define el tamaño del área brillante y, al hacer hover, cambia a un porcentaje mayor para alargar el destello
  • --gradient-angle-offset se usa para reajustar el ángulo del gradiente y evitar que el brillo parezca saltar hacia adelante o hacia atrás durante el hover
  • El brillo de --gradient-shine se reduce para mezclarse de forma más natural con el color de resaltado del entorno

Cómo se ralentiza la rotación durante el hover

  • El truco de CSS para bajar la velocidad de rotación consiste en declarar dos veces la misma animación de rotación
  • La segunda animación se coloca en dirección inversa, con la duración reducida a la mitad, y en el estado base queda en paused
  • En hover, animation-play-state: running sobrescribe el paused y ralentiza la rotación a la mitad de velocidad
  • Cuando termina el hover, la animación no salta de vuelta a la posición inicial, sino que vuelve a acelerarse desde la posición actual
  • La animación del botón CTA usa esta técnica para que la rotación y el movimiento sigan sincronizados incluso cuando cambia la velocidad

Pequeños destellos y resaltado interno

  • El pequeño patrón de puntos dentro del botón se renderiza creando un fondo radial-gradient en el pseudo-elemento ::before
  • --gradient-angle vuelve a reutilizarse aquí, mientras una máscara conic-gradient gira y deja ver solo parte del patrón de puntos
  • El ángulo del gradiente de la máscara se desplaza 45deg para alinearse con la rotación del borde brillante
.shiny-cta::before {
  mask-image: conic-gradient(
    from calc(var(--gradient-angle) + 45deg),
    black,
    transparent 10% 90%,
    black
  );
}
  • En el pseudo-elemento ::after se añade un gradiente con el color de resaltado para que gire junto con el área brillante
  • Ese resaltado interno refuerza la sensación de luz fluyendo dentro del botón

Ajuste de colores en hover y acabado final

  • Como ::before y ::after ya están en uso en el botón, el texto del botón se envuelve en un span
  • En uno de los pseudo-elementos del span se aplica un box-shadow difuso con el color de resaltado y se extiende hasta el tamaño del botón
  • En hover, este pseudo-elemento crece y se reduce lentamente, creando una sensación suave, como de respiración
  • Combinado con el color de resaltado que gira en el interior, completa el efecto final del botón CTA

Potencial para sistemas de diseño

1 comentarios

 
GN⁺ 2024-09-05
Comentarios en Hacker News
  • No soy desarrollador web, pero he hecho sitios web de juguete sin frameworks y he realizado tareas básicas en algunos frameworks web; cuando CSS apareció por primera vez, sentía que al poco tiempo uno podía tenerlo todo en la cabeza y usarlo
    El CSS del primer ejemplo en CodePen se ve casi como una sintaxis críptica, y me pregunto si de verdad hace falta incluso un pequeño lenguaje de programación para animaciones dentro del sistema de estilos
    Esto parece algo que podría hacerse con JavaScript; entiendo el rechazo a usar JS para todo, pero al final, si es un lenguaje de programación, este tipo de trabajo parece más cercano a su función principal

    • No entiendo muy bien esa sensación. Si no eres desarrollador web, en especial de frontend, probablemente tampoco tengas muchas ocasiones de crear elementos HTML con este tipo de efectos llamativos, así que no veo por qué sería un problema lo que CSS puede hacer con funciones avanzadas
      Por supuesto también se puede hacer con JavaScript, e incluso podrías poner un canvas y programar el efecto en la GPU con WebGL. Pero entonces tendrías que volver a implementar a mano todas las funciones de accesibilidad de un botón HTML, y no está claro que eso sea más fácil
    • Es por rendimiento. Si lo haces con JS, tiene que ejecutarse de forma fluida 60 veces por segundo, y como JS es de un solo hilo, en cuanto se bloquea el hilo principal se pierden cuadros
      Los motores modernos de JS son impresionantes, pero no son tan eficientes como el código nativo, así que aumenta el uso de CPU y al final también perjudica la duración de la batería
    • Cualquier oportunidad de evitar JavaScript en un sitio me parece bienvenida, incluso si implica más trabajo. Los visitantes que usan JavaScript desactivado pueden evitar muchos exploits y rastreadores que hoy atormentan a la web
      Por la misma razón, agradezco los sitios donde JavaScript no es obligatorio
    • No es buena idea necesitar un lenguaje de programación completo para cosas que solo tienen que ver con la estética de la página
      Algunas plataformas de hosting permiten personalizar con HTML y CSS por seguridad, pero bloquean JS. Pasa en sitios como Itch.io, donde puedes decorar juegos y perfiles, y usar animaciones CSS permite crear efectos vistosos sin dar acceso a JavaScript, así que tiene sentido y resulta útil
    • Parece que no entiendes bien el problema que esto busca resolver ni conoces la sintaxis, y por eso ves como un cambio negativo algo que no se entiende de inmediato
  • Al leer este artículo sentí esa resistencia mental que aparece ante un concepto desconocido. Antes de ver los ejemplos del blog, recomiendo leer primero el artículo de MDN enlazado en la primera frase
    @property parece ser de esas cosas que se entienden de verdad al probarlas, y si quieres implementar una UI compleja reduciendo la dependencia de JS, conocer este tipo de funciones crípticas de CSS puede ser un arma muy poderosa

    • Incluso leyendo el artículo de MDN, no logro entenderlo. Esto parece literalmente una variable de CSS, ¿no?
      Las variables de CSS ya cascaban y se podían sobrescribir con clases y demás; cosas como bg-opacity de Tailwind no funcionan justamente así?
    • Me pasa algo parecido. Creo que este artículo lo explicó bastante mal
      Viendo MDN, suena a que es casi igual que las antiguas variables de CSS, pero con alcance delimitado a un elemento específico o a sus hijos, y con restricciones añadidas que reconocen unidades CSS como ángulos o porcentajes
      Aun así, no creo que lo use. Una ventaja tan pequeña no justifica el costo de complejidad y compatibilidad, e intento evitar sintaxis nuevas innecesarias. Desde las variables de CSS, he perdido bastante interés en las nuevas funciones de CSS
    • Pensé que era el único, pero sí, se siente realmente ajeno
      No veo muy bien qué ventaja tiene frente a usar transform de CSS
  • Me gusta trabajar con CSS, pero también trabajo con colegas a quienes CSS se les hace difícil, así que recomiendo mucho el canal de YouTube de Kevin Powell
    Ha tratado esta función varias veces, y en un video que subió hace una semana muestra una utilidad interesante que hacen posible las propiedades registradas: https://youtu.be/U8NykwZNbGs
    También hay un artículo que explica las propiedades registradas con ejemplos fáciles de seguir: https://moderncss.dev/providing-type-definitions-for-css-wit...

  • Me entusiasma el trabajo reciente en CSS, especialmente Houdini. No sentía algo así desde que vi un libro sobre funciones de IE 5.5
    En los últimos 14 años se han añadido muchas funciones nuevas a CSS, pero eran más bien capacidades básicas que uno esperaría de un framework de estilos, como nuevas opciones de layout o variables
    Pero los desarrolladores de IE realmente iban sin miedo, e incluso se podían convertir fragmentos de código JS en módulos y adjuntarlos a elementos desde CSS. Por fin siento que vuelven ese tipo de funciones radicales
    Ejemplo: https://developer.chrome.com/docs/css-ui/houdini

    • No me queda claro si aquí “iban sin miedo” se usa en sentido positivo o negativo
    • Creo que así era como funcionaba css3pie(http://css3pie.com/), ¿no?
  • Es un artículo breve y bueno. Si quieres ver más ejemplos, sobre todo ejemplos mucho más simples con los que es más fácil captar la idea rápido, recomiendo este viejo artículo de CSS-Tricks
    Es de 2021, pero sigue vigente y está muy bien hecho: https://css-tricks.com/exploring-property-and-its-animating-...
    En especial, creo que te gustará el ejemplo de pantalla flip que hace pasar números como los de aeropuertos o temporizadores

  • Estuve alejado del desarrollo web por un tiempo, y me tomó demasiado entender qué hace realmente esta función. Creo que el artículo no lo explica bien.
    Según entendí, en vez de usar un valor primitivo como 360deg, se usa algo como from var(--gradient-angle), y ese valor se toma y sustituye desde donde fue definido en el bloque @property --gradient-angle {...}
    También está inherits: false;; entiendo cómo funciona, pero no sé por qué es necesario. Ya se puede controlar la herencia con selectores CSS, así que me cuesta seguir la idea de que ahora también se pueda controlar desde otro lado
    También me pregunto por qué hay que definir un tipo en el bloque @property. En otras partes de CSS no se definen tipos, así que me da la impresión de que el navegador podría inferirlo viendo dónde se usa @property

    • Para mí, la mayor ventaja fue que esto permite animar variables CSS
      Hace tiempo, en un experimento para cambiar el diseño de YouTube a algo estilo neón, hice que el color principal se controlara con una sola variable CSS, y movía lentamente su tono a lo largo de todo el espectro
      Sin @property no se pueden animar variables CSS, así que no se trata solo de usar una variable en lugar de un valor primitivo, sino de poder animar esa variable y todos los lugares donde se referencia. Con solo @keyframes neon-flow { from { --dc-neon-hue: 0; } to { --dc-neon-hue: 360; } } se pueden mover el color principal, las sombras y demás
      inherits: false controla cómo se hereda una propiedad personalizada. Puede hacer que se herede a los hijos como color: red, o que solo se aplique a ese elemento, como display: flex
      El tipo parece necesario para saber, en tiempo estático, qué se va a animar. Una variable CSS puede ser cualquier cosa, pero una propiedad CSS normal ya aporta información de tipo por la propia propiedad, como color
      Lo interesante es que esta sintaxis de tipos es la misma gramática formal que se ve en MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/color#forma... Se siente como si hubieran expuesto el interior de CSS como una API utilizable por desarrolladores
    • Las propiedades CSS como tal ya existían antes de @property; por ejemplo, podías declarar --my-prop: 10px y luego usar var(--my-prop) en otro lugar
      La novedad de @property es que permite definir la propiedad de antemano para especificar qué tipo de sintaxis debe aceptar, si debe heredar el valor del padre y cuál es su valor predeterminado con initial-value
      Así, si algún elemento asigna --my-prop: 5px a una propiedad declarada como tipo ángulo, ese valor se ignora. Antes eso podía ser un valor válido y causar efectos secundarios no deseados según el lugar donde se usara
      Además, si escribes --my-prop: initial, puedes hacer que use initial-value sin necesidad de conocer el valor predeterminado exacto
    • Gracias por esta explicación. Cuesta entender el artículo porque no explica qué hace @property ni cómo se usa
      Queda completamente tapado por un ejemplo excesivamente complicado
  • Este sitio web me pone de buen humor
    Siempre me gustó jugar con CSS, pero después de más de 10 años haciendo desarrollo web y trabajando profesionalmente con cosas de la web, también he visto cuánto odia la gente CSS
    Puedo pasar tiempo infinito navegando y experimentando con HTML+CSS escrito a mano, e incluso lo despliego para ver cómo se siente en un teléfono real. El 99% de eso no termina usándose en ningún lado
    Para la mayoría será una pérdida de tiempo, pero este sitio de verdad me alegró el día

    • Me gusta muchísimo CSS. También me parece bastante fácil de entender
      Sí se ha vuelto más complejo en los últimos 10 años, pero hoy puedo hacer de forma mucho más simple cosas que hace 10 años eran más complicadas, y el código de entonces todavía sigue funcionando
    • La gente que dice en voz alta que odia CSS por lo general es gente que no entiende CSS
      Y está bien. Yo tampoco entiendo APEX, ni APL, ni el framework de moda de hoy. Pero CSS sí lo entiendo, y por eso lo disfruto bastante
      A algunas personas les hace clic y a otras no. El problema aparece cuando a alguien que no conecta con CSS le toca trabajar con CSS por su empleo, y obviamente termina odiándolo. Si mi trabajo fuera mantener instalaciones de Active Directory, yo también lo odiaría. Pero eso no significa que CSS sea malo
    • CSS es divertido para jugar y vale la pena explorar sus nuevas funciones. Pero a veces da la impresión de que las funciones de CSS salen con una vibra de “¿qué más podríamos hacer?”
      Seguro existe algún foro donde se discuten estas cosas seriamente, pero siento que me lo estoy perdiendo
    • Todavía soy bastante minimalista, pero he estado escribiendo más CSS a mano para agarrarle la onda a trabajar fuera de herramientas como Bootstrap o Tailwind
      En producción, sobre todo, casi siempre he escrito el frontend enteramente en JSX, pero desde que me metí en la madriguera del web scraping, he mejorado mucho mi comprensión de la lógica de selectores
      Como idea medio provocadora relacionada con esto, creo que si en el trabajo usáramos más elementos semánticos, la lógica de selectores no sería tan problemática como ahora. Y tampoco tendríamos que mantener por nuestra cuenta comportamientos que HTML puro ya define, como los modales
    • En cuanto tienes que implementar algo que funcione de forma bastante amplia, en vez de tocar solo tu combinación específica de dispositivo·pantalla·navegador·versión del navegador·SO, las pequeñas violaciones de la especificación se vuelven realmente desesperantes
      Antes Microsoft era el infractor de especificaciones más infame; ahora diría que lo es Apple
  • Estas animaciones hacen que todo se vea como publicidad display de los 2000. Y no en el buen sentido
    De verdad espero que esta estética no se ponga de moda

    • Pienso igual. Me pareció interesante que se pudieran hacer los ejemplos de CodePen solo con CSS, pero también los sentí algo excesivos; si hubiera visto el primer botón de llamada a la acción en un sitio web real, me habría parecido cursi y vergonzoso
      Estas cosas transmiten una sensación fuerte de marketing y manipulación. Preferiría que me dejaran leer el sitio y decidir qué quiero hacer. Que no me interrumpan forzando mi atención hacia los elementos que generan dinero
    • Al principio pensé que CodePen estaba tratando de venderme un upgrade
    • Estas son cosas que ya se están haciendo en código de apps nativas, así que la web también debería tener una función equivalente
      Si no, todo el mundo terminará implementándolo dentro de ecosistemas cerrados
  • PFM, o “magia pura”, es justo la sensación que da ver lo que se puede hacer con animaciones CSS
    Pero está tan especializado para CSS y solo para CSS que aprenderlo y conceptualizarlo es más difícil que implementarlo de forma procedimental con JS. No se me da bien pensar de esa manera, y con solo las opciones de uso de flex en CSS ya tengo suficiente

    • CSS realmente parece su propio territorio alienígena. Tampoco ayuda que la sintaxis le resulte extraña a la mayoría de los desarrolladores
      Pero es potente, realmente muy potente, y muy eficiente en la mayoría de los navegadores. La abrumadora mayoría de los desarrolladores de apps web no necesita el 99% de lo que ofrece CSS, pero está bueno saber que esas funciones existen
    • Por eso contraté a un diseñador que sabe programar HTML+CSS
      Si dejas en la página elementos sin estilo conectados a la lógica de negocio, el diseñador puede darles el estilo que quiera. Si hace falta, después se puede iterar para pulir la UI
    • Es un paradigma declarativo, como SQL
      Si vienes de una visión puramente imperativa, hace falta algo de tiempo para leer la especificación y experimentar, pero creo que es una forma de pensar que vale más allá de usar SQL y CSS. Claro que SQL y CSS por sí mismos ya valen mucho
    • JS siempre, siempre es el último recurso. En los últimos años, a medida que las funciones de CSS llegaron a la mayoría de los navegadores, he quitado bastante JS del código y me gusta dejar la página en JavaScript Zero
      Me haría muy feliz que solo le pusieran nombre a la función “masonry” de CSS[1] para poder usarla sin scripts
      [1] https://github.com/w3c/csswg-drafts/issues/9733
    • En este caso, property es parte de la API de CSS Houdini y permite manipular CSS desde JavaScript de una forma mucho más potente que antes
      https://developer.mozilla.org/en-US/docs/Web/API/Houdini_API...
  • El entusiasmo que muestra el autor por este nuevo fragmento de CSS es de un nivel que casi no veía desde hace 10 años, y eso me encanta
    Si estuviera en mis 20, probablemente habría pasado horas o días jugueteando con las posibilidades de esta función. Era divertido hacer que algo funcionara en CSS
    Ahora, gracias a flexbox, grid y a que la mayoría de los sitios web y apps siguen principios de diseño estándar, siento que se volvió bastante más fácil y que las UI web están cerca de ser un problema resuelto

    • Me pregunto cuáles son esos principios de diseño estándar
    • No sé qué se supone que se resolvió. ¿El layout?
      Todavía hay veces en las que tengo que volver a leer las partes ambiguas de flex y grid. El posicionamiento sticky es una de las funciones más útiles, pero si no funciona por la razón que sea, depurarlo y entender la causa es muy difícil o casi imposible. También están problemas como que algún padre tenga overflow
      También es difícil encontrar documentación que explique bien estos casos límite, y depurar CSS solo con el código fuente, sin herramientas de desarrollador, es casi imposible, así que hay que inspeccionar los elementos en tiempo de ejecución
      La mayoría de los elementos de entrada nativos siguen teniendo posibilidades de estilo muy limitadas, y para los modales y popovers nativos también hubo que esperar años. La última vez que revisé, todavía no se podía animar la altura al pasar de display: none a block
      Me pregunto si no nos hemos acostumbrado demasiado a los problemas de CSS y por eso ya perdimos el sentido crítico