Acerca de los conflictos de Sass y las características CSS relativamente nuevas

Más recientemente, ha habido muchas características interesantes en CSS, como Variables CSS y nuevas características . Si bien todo esto puede hacer la vida mucho más fácil para los diseñadores web, estas características pueden interactuar con los preprocesadores CSS como Sass de formas inesperadas. La autora del material, cuya traducción publicamos hoy, hablará sobre los problemas que tuvo que enfrentar, cómo los enfrentó y por qué cree que todavía es imposible prescindir de Sass.











Errores



Si usted está experimentando con CSS-características min()y max()luego usando diferentes unidades de medida, podríamos estar ante mensajes de error como este: Incompatible units: vh and em.





Mensaje de error al usar diferentes unidades en las funciones min () y max ()



Este mensaje se muestra porque Sass tiene su propia funciónmin(). Como resultado, semin()ignora lafunción CSS. Además, Sass no puede realizar cálculos utilizando unidades que no tengan una relación clara entre ellas.



Por ejemplo, la relación entre unidades estácmbienindefinida, por lo que Sass puede encontrar el resultado de una funciónmin(20in, 50cm)y no arrojará un error si usa algo así en su código.



Lo mismo ocurre con otras unidades de medida. Por ejemplo, todas las unidades de la esquina están interconectados:1turn,1rado1gradsiempre se convierten a los mismos valores expresados ​​en unidades deg. Lo mismo ocurre, por ejemplo, en el caso de 1sque siempre sea igual 1000ms. 1kHzsiempre igual 1000Hz, 1dppxsiempre igual 96dpi, 1insiempre igual 96px. Es por eso que Sass puede convertir valores expresados ​​en estas unidades entre sí y mezclarlos en cálculos utilizados en varias funciones, como su propia función min().



Pero todo sale mal cuando no hay una relación clara entre las unidades de medida (como, por ejemplo, arriba, y emy vh).



Y esto sucede no solo cuando se utilizan valores expresados ​​en diferentes unidades de medida. Intentando usar una función calc()internamentemin()también da como resultado un error. Si intenta min(), poner algo como calc(20em + 7px), se muestra este error: calc(20em + 7px) is not a number for min.





Mensaje de error se produce cuando intenta utilizar calc () en min ()



Otro problema se produce en una situación cuando se trata de utilizar el CSS-variable o la salida de las funciones de CSS-matemática (comocalc(),min(),max()) en el CSS-como filtrosinvert().



Aquí está el mensaje de error que puede ver en circunstancias similares:$color: 'var(--p, 0.85) is not a color for invert





El uso de var () en el filtro: invertido () resulta en un error



Lo mismo ocurre congrayscale():$color: ‘calc(.2 + var(--d, .3))‘ is not a color for grayscale.





Uso de la calc () en el filtro: escala de grises () da como resultado un error



de diseñofilter: opacity()es también sujetos a problemas similares:$color: ‘var(--p, 0.8)‘ is not a color for opacity.





El uso de var () en el filtro: opacidad () produce un error



, pero otras funciones de usofilter, incluyendosepia(),blur(),drop-shadow(),brightness(),contrast()yhue-rotate(), en colaboración con los CSS-variables es perfectamente normal!



Resultó que la causa de este problema es similar a la que afecta a las funcionesmin()ymax(). El Sass no está incorporado en las funcionessepia(),blur(),drop-shadow(),brightness(),contrast(),hue-rotate(). Pero tiene sus propias funciones escala de grises () , invertir () y opacidad () . El primer argumento de estas funciones es el valor$color. El error aparece debido al hecho de que al usar construcciones problemáticas, Sass no encuentra tal argumento.



Por la misma razón, surgen problemas cuando se utilizan variables CSS que representan al menos dos valores hsl()o hsla().





Error al usar var () en color: hsl ()



Por otro lado, sin usar Sass, una construccióncolor: hsl(9, var(--sl, 95%, 65%))es perfectamente correcta y funciona perfectamente CSS.



Lo mismo es cierto para funciones comorgb()yrgba():





Error al usar var () en color: rgba ()



Además, si importa Compass e intenta usar una variable CSS dentrolinear-gradient()oradial-gradient(), puede encontrar otro error. Pero, al mismo tiempo,conic-gradient()puede usar variablesenvariables sin ningún problema (por supuesto, si el navegador admite esta función).





Error al usar var () en segundo plano: linear-gradient ()



La razón del problema radica en el hecho de que Compass tiene su propio linear-gradient () yradial-gradient()funciones, pero la funciónconic-gradient()nunca estuvo allí.



En general, todos estos problemas provienen de que Sass o Compass tienen sus propias funciones, cuyos nombres son los mismos que los de CSS. Tanto Sass como Compass, al cumplir con estas funciones, creen que vamos a utilizar sus propias implementaciones de estas funciones, y no las estándar.



¡Aquí hay una emboscada!



Solución



Este problema se puede resolver recordando que Sass distingue entre mayúsculas y minúsculas, pero CSS no.



Esto significa que puede escribir algo como esto Min(20em, 50vh)y Sass no reconoce su propia función en esa construcción min(). No se generarán errores. Esta construcción será CSS bien formada que funciona exactamente como se espera. Del mismo modo, para deshacerse de los problemas con otras funciones pueden ser, de forma no estándar, escribiendo sus nombres: HSL(), HSLA(), RGB(), RGBA(), Invert().



Cuando se trata de degradados, suelo utilizar esta forma: linear-Gradient()y radial-Gradient(). Hago esto porque esta notación está cerca de los nombres usados ​​en SVG, pero en esta situación, funcionará cualquier otro nombre similar que incluya al menos una letra mayúscula.



¿Por qué todas estas complicaciones?



Casi cada vez que twitteo algo sobre Sass, me dan una conferencia sobre cómo ahora que tienes variables CSS, ya no necesitas usar Sass. Decidí que debía responder esto y explicar el motivo de mi desacuerdo con esta idea.



En primer lugar, señalaré que las variables CSS me parecen extremadamente útiles y que las he usado para una variedad de tareas durante los últimos tres años. Pero supongo que debes recordar que usarlos tiene un impacto en el rendimiento. Y la búsqueda de un problema en el laberinto de llamadascalc()puede ser la experiencia más desagradable. Las herramientas estándar para desarrolladores de navegadores aún no son muy buenas en esto. Procuro no dejarme llevar por el uso de variables CSS, para no meterme en situaciones en las que sus desventajas se manifiestan más que sus ventajas.





No es fácil entender cuáles serán los resultados de evaluar estas expresiones calc () En



general, si una variable se usa como constante, no cambia de un elemento a otro, o de un estado a otro (y en tales casos, las variables CSS definitivamente deben usar necesario ), o si la variable no reduce la cantidad de CSS compilado (resolviendo el problema de repetición creado por los prefijos), entonces usaré una variable Sass.



En segundo lugar, el soporte variable siempre ha sido una razón bastante menor entre las razones por las que uso Sass. Cuando comencé a usar Sass en la segunda mitad de 2012, lo hice principalmente para bucles. Por el bien de una característica que aún falta en CSS. Si bien moví parte de la lógica de bucle al preprocesador de HTML (ya que esto reduce la cantidad de código generado y evita la necesidad de modificar tanto HTML como CSS), sigo usando bucles de Sass en muchos casos. Estos incluyen generar listas de valores, crear valores para ajustar gradientes, crear listas de puntos cuando se trabaja con una función polygon(), crear listas de transformaciones, etc.



A continuación se muestra un ejemplo de lo que habría hecho antes al crear algunos elementos HTML con el preprocesador. No importa qué preprocesador sea, pero elegí Pug:



- let n = 12;

while n--
  .item


Luego crearía una variable $nen Sass (y esta variable debería tener el mismo valor que en HTML) e iniciaría un bucle usándola, en el cual generaría las transformaciones utilizadas para posicionar cada uno de los elementos:



$n: 12;
$ba: 360deg/$n;
$d: 2em;

.item {
  position: absolute;
  top: 50%; left: 50%;
  margin: -.5*$d;
  width: $d; height: $d;
  /*    */

  @for $i from 0 to $n {
    &:nth-child(#{$i + 1}) {
      transform: rotate($i*$ba) translate(2*$d) rotate(-$i*$ba);
      &::before { content: '#{$i}' }
    }
  }
}


La desventaja de esto es que tendría que cambiar los valores tanto en el código Pug como en el código Sass si cambiara la cantidad de elementos. Además, hay mucha repetición en el código.





Código CSS generado a partir del código anterior



Ahora tomé un enfoque diferente. Es decir, usando Pug, genero índices como propiedades personalizadas y luego los uso en la declaracióntransform.



Aquí está el código que Pug planea hacer:



- let n = 12;

body(style=`--n: ${n}`)
  - for(let i = 0; i < n; i++)
    .item(style=`--i: ${i}`)


Aquí está el código Sass:



$d: 2em;

.item {
  position: absolute;
  top: 50%;
  left: 50%;
  margin: -.5*$d;
  width: $d;
  height: $d;
  /*    */
  --az: calc(var(--i)*1turn/var(--n));
  transform: rotate(var(--az)) translate(2*$d) rotate(calc(-1*var(--az)));
  counter-reset: i var(--i);

  &::before { content: counter(i) }
}


Puedes experimentar con este código aquí.





Elementos generados y diseñados mediante bucles El



uso de este enfoque ha reducido significativamente la cantidad de CSS generado automáticamente.





CSS generado a partir del código anterior



Pero si quieres crear algo como un arcoíris, no puedes prescindir de los bucles Sass.



@function get-rainbow($n: 12, $sat: 90%, $lum: 65%) {
  $unit: 360/$n;
  $s-list: ();

  @for $i from 0 through $n {
    $s-list: $s-list, hsl($i*$unit, $sat, $lum)
  }

  @return $s-list
}

html { background: linear-gradient(90deg, get-rainbow()) }


Aquí hay una versión funcional de este ejemplo.





Fondo multicolor



Por supuesto, esto se puede generar usando variables Pug, pero este enfoque no tiene ninguna ventaja sobre la naturaleza dinámica de las variables CSS y no reducirá la cantidad de código transmitido al navegador. Como resultado, no tiene sentido que renuncie a lo que estoy acostumbrado.



Utilizo mucho las funciones matemáticas integradas de Sass (y Compass), como las funciones trigonométricas. En estos días, estas características son parte de la especificación CSS , pero no todos los navegadores las admiten todavía. Sass no tiene estas funciones, pero Compass sí, por eso suelo usar Compass.



Y, por supuesto, puedo escribir mis propias funciones de este tipo en Sass. Hice esto al principio, antes de que Compass tuviera soporte para funciones trigonométricas inversas. Realmente necesito estas funciones, así que las escribí yo mismo usando la serie de Taylor . Pero en estos días, estas funciones están en Compass. Son mejores y más productivos que los que escribí yo mismo.



Las funciones matemáticas son muy importantes para mí porque soy programador, no artista. Los valores en mi CSS generalmente se generan a partir de cálculos matemáticos. Estos no son unos "números mágicos", o algo que juega un papel puramente estético. Un ejemplo de su uso es generar una lista de polígonos regulares o cuasi regulares paraclip-path... Esto se utiliza, por ejemplo, al crear algo como avatares o pegatinas, cuya forma es diferente a la rectangular.



Considere un polígono regular cuyos vértices se encuentran en un círculo. Arrastrar el control deslizante en el siguiente ejemplo, con el que podemos experimentar aquí , nos permite ver dónde se colocan los puntos para formas con diferentes números de vértices.





Una forma con tres vértices



Así es como se ve el código Sass correspondiente:



@mixin reg-poly($n: 3) {
  $ba: 360deg/$n; //  
  $p: (); //   ,  

  @for $i from 0 to $n {
    $ca: $i*$ba; //  
    $x: 50%*(1 + cos($ca)); //  x  
    $y: 50%*(1 + sin($ca)); //  y  
    $p: $p, $x $y //       
  }

  clip-path: polygon($p) //       clip-path 
}


Tenga en cuenta que estamos usando bucles y otras construcciones aquí, que son muy inconvenientes de usar con CSS puro.



Una versión un poco más avanzada de este ejemplo podría implicar la rotación del polígono agregando el mismo desplazamiento ( $oa) a la esquina correspondiente a cada vértice. Esto se puede ver en el siguiente ejemplo . Aquí se generan estrellas, que están ordenadas de manera similar, pero siempre tienen un número par de vértices. Además, cada vértice con índice impar se ubica en un círculo cuyo radio es menor que el del círculo principal ( $f*50%).





Estrella



Puedes hacerestrellas tan interesantes.





Estrellas



Puede crear pegatinas con bordes (border) creados con plantillas inusuales. En este ejemplo, se crea una pegatina a partir de un solo elemento HTML y la plantilla utilizada para la personalizaciónborderse crea utilizandoclip-pathbucles Sass y matemáticas. De hecho, aquí hay muchos cálculos.





Pegatinas con bordes complejos



Otro ejemplo es la creación de un fondo para tarjetas. Aquí, en un bucle, utilizando el operador de módulo y las funciones exponenciales, se crea un fondo con una imitación del efecto de tramado.





Efecto de difuminado



Aquí también se usan mucho las variables CSS.



A continuación, puede pensar en usar mixins para evitar tener que escribir la misma declaración una y otra vez al diseñar algo como controles deslizantes . Los diferentes navegadores usan diferentes pseudo-elementos para diseñar los componentes internos de dichos controles, por lo que para cada componente necesita definir estilos que controlen su apariencia usando diferentes pseudo-elementos.



Desafortunadamente, en CSS, por muy tentador que parezca, no puede poner algo como el siguiente código:



input::-webkit-slider-runnable-trackinput::-moz-range-trackinput::-ms-track { /*   */ }


No funcionará. Todo este conjunto de reglas se ignora si no se reconoce al menos un selector. Y, dado que ningún navegador conoce la existencia de los tres selectores en este ejemplo, estos estilos no se aplicarán en ningún navegador.



Si desea que el estilo funcione, deberá hacer algo como esto:



input::-webkit-slider-runnable-track { /*   */ }
input::-moz-range-track { /*   */ }
input::-ms-track { /*   */ }


Pero esto puede hacer que los mismos estilos aparezcan tres veces en el código. Y si necesita, digamos, cambiar una trackpropiedad background, esto significará que tendrá que editar los estilos en ::-webkit-slider-runnable-track, en ::-moz-range-tracky en ::-ms-track.



La única solución sensata a este problema es utilizar mixins. Los estilos se repiten en el código compilado, ya que no podemos prescindir de él, pero ahora, al menos, no tenemos que introducir el mismo código tres veces en el editor.



@mixin track() { /*   */ }

input {
  &::-webkit-slider-runnable-track { @include track }
  &::-moz-range-track { @include track }
  &::-ms-track { @include track }
}


Salir



La principal conclusión que puedo sacar es la siguiente: Sass in es algo de lo que no podemos prescindir todavía.



¿Usas Sass?






All Articles