Blog de programación, errores, soluciones

Chose Language:
Author: Admin/Publisher |not checked

Generando CSS con SASS

Al principio, he estado pensando si debería o no escribir sobre este tema, pero me he dado cuenta que por más que los creadores intente de que el CSS esté ordenado, hay gente que sigue mezclando el código SASS con el CSS.

Importante– Hay algo que tenemos que dejar en claro y es que no debemos dejar accesible el código SASS al usuario que utiliza nuestra página. El código SASS no debe estar en la carpeta public, el código que debe estar en la carpeta public o carpeta accesible por los usuarios debe ser CSS y minificado.

En ofuscación de código ya habíamos hablado que Laravel usa una carpeta assets, esta carpeta es la que tendria todo nuestro código SASS, CSS, Javascript u otros que conforman la parte del Front end sin processar. Para procesar estos códigos podemos utilizar grunt, gulp u otra app que nos permita procesarlos, en caso de laravel utilice laravel-mix.

Para nuestro código SASS deberemos utilizar una carpeta como esta o si le gusta el nombre assets podemos crear una que tenga este nombre. En mi proyecto de ejemplo crearé esta carpeta assets, de modo que quede algo asi:

  1. Proyecto(tutorialSASS)
    1. assets(folder)
    2. other files(index.html, prueba1,prueba2, …,pruebaN)
Lugar del proyecto
mkdir tutorialSASS

En mi caso será htdocs, la carpeta donde estoy creando la carpeta tutorial SASS, ya que estoy usando XAMPP.

Instalación de SASS

En mi caso estoy en Windows y me voy a aprovechar de que ya tengo chocolatey instalado:

Power Shell[Administrator]
choco install sass

La instalación de SASS debería de instalar el lenguaje de programación Dart, en caso de que no lo instale o que de error en la instalación deberás instalar Dart primero.

Power Shell[Administrator]
choco install dart-sdk

En caso de que nos diga que Dart ya está instalado, puede agregar --force al final del comando forzando a instalar denuevo.

Para chequear que sass se ha instalado con éxito puedes utilizar el comando sass en consola.

Escoje la sintaxis que mejor vaya contigo

Una vez instalado SASS debemos tener en cuenta que tenemos dos tipos de archivos .scss y .sass en SASS estos 2 tipos de archivo tienen diferentes sintaxis:

SCSS sintaxis

La sintaxis que utiliza {} y ; es prácticamente igual a la de CSS y, por tanto, casi todo lo que sea CSS funcionara en esta sintaxis sin grandes problemas.

Archivos .scss
@mixin button-base() {
  @include typography(button);
  @include ripple-surface;
  @include ripple-radius-bounded;

  display: inline-flex;
  position: relative;
  height: $button-height;
  border: none;
  vertical-align: middle;

  &:hover { cursor: pointer; }

  &:disabled {
    color: $mdc-button-disabled-ink-color;
    cursor: default;
    pointer-events: none;
  }
}

SASS sintaxis

La sentencia que se guía por la indentación de su contenido es la sintaxis original que tenía sass y por tal motivo los archivos con esta indentación tienen extensión .sass.

archivo .sass
@mixin button-base()
  @include typography(button)
  @include ripple-surface
  @include ripple-radius-bounded

  display: inline-flex
  position: relative
  height: $button-height
  border: none
  vertical-align: middle

  &:hover
    cursor: pointer

  &:disabled
    color: $mdc-button-disabled-ink-color
    cursor: default
    pointer-events: none

Utilizando SASS en nuestro proyecto

Ya empezaré utilizando la carpeta que creamos tutorialSASS y crearé dentro de esta un index.php, en tanto a la carpeta que tenga nuestro código SASS crearemos una carpeta assets y dentro de esta otra sass.

En mi index haré código html solo para probar nuestro css.

index.php
<!doctype html>
<html lang="">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <title></title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="main.css">
    </head>
    <body>
        <h1>header 1</h1>
        <h2>header 2</h2>
        <h3>header 3</h3>
        <h4>header 4</h4>
        <h5>header 5</h5>
    </body>
</html>

Ahora necesitaríamos un código SASS que interactúe con los header, en mi caso utilizaré la sintaxis de SCSS porque me parece mucho mejor.

headers.scss
$fontsize:1em;
h1{
    font-size: $fontsize * 1.5;
}
h2{
    font-size: $fontsize * 1.4;
}
h3{
    font-size: $fontsize * 1.3;
}
h4{
    font-size: $fontsize * 1.2;
}
h5{
    font-size: $fontsize * 1.1;
}

Ok ahora necesitaríamos generar nuestro main.css a partir de este header.scss, con esta intención en mente vamos a nuestra consola cmd y tipeamos(escribimos):

project folder
sass --watch assets/sass/headers.scss main.css
Sass is watching for changes. Press Ctrl-C to stop.

Esto es porque mientras este esto está constantemente mirando si hay cambios en nuestro archivo .scss si hay cambios este hará nuestro main.css.

Podemos salir una vez terminemos de hacer los cambios en nuestro archivo con Ctrl + C para parar el proceso de watch.

Aquí concluimos como usar SASS en modo vanilla(original), recuerde que hay otras formas de procesar nuestro código SASS para generar CSS(grunt, gulp, laravel Mix, etc).

Hasta aquí vimos como generar CSS y los 2 tipos de archivos que tenemos en SASS. Ahora nos toca ver el código SASS.

Código SASS

En esta seccion de este post veremos las diferentes características que tiene el código SASS que nos permite crear CSS de forma mas sencilla y mas clara.

Comentarios

SASS tiene distintas formas dehacer comentarios, y estos difieren dependiendo del el archivo que creamos si .sass o scss.

Tenga en cuenta que esta es la unica vez que haremos referencia a la extencion de archivos ya que se diferencian bastante los comentarios. Sin ser los comenarios scss es similar a como se escribe codigo en casi todos los lenguajes y .sass tiene practicamente las reglas que posee python.

SCSS tiene comentarios similares a los que tiene PHP

comentarios en archivos .scss
//comentario de linea
/*
 comentario de multiples lineas
*/
/*! Este comentario se mantendra incluso en el codigo generado*/
comentarios en archivos .sass
//comentario en sass
   esta línea también será parte del comentario y se debe a la tabulacion
/* esto es un comentario
   esto es parte del comentario
   esta línea también es parte del comentario
/* este es otro comentario.
/*! este comentario se mantendrá incluso luego de la generación de css

Comentario para documentación

En SASS tenemos funciones y las veremos más adelante, y, por tanto, necesitaremos comentarios para saber que hacen, a estos comentarios los podemos hacer con ///

Este es el ejemplo de la pagina de SASS

documentation comment [.sass]
/// Computes an exponent.
///
/// @param {number} $base
///   The number to multiply by itself.
/// @param {integer (unitless)} $exponent
///   The number of `$base`s to multiply together.
/// @return {number} `$base` to the power of `$exponent`.
@function pow($base, $exponent)
  $result: 1
  @for $_ from 1 through $exponent
    $result: $result * $base
  @return $result

Como podemos ver estos comentarios también poseen @ esto es para indicar parámetros, retornos autor etc, estos @ los utilizara el generador de documentación que también lo deberá instalar si quiere hacer documentación de esta manera.

No confundas @ dentro del código sass a @ dentro del comentario.

Puedes saber más sobre como escribir código de documentación en http://sassdoc.com/ también nos indica como instalar este software complementario.

Para no ser menos veamos como instalarlo:

npm install sassdoc -g

Simple verdad, utilizar ese para generar la documentación también es muy simple simplemente tenemos que usar:

sassdoc <ruta donde está el archivo en nuestro proyecto>

Función url()

Hay varias funciones especiales, pero en este post tocaremos la función url() ya que las otras son para internet Explorer o no están soportadas en todos los navegadores.

La url dada dentro de () de url() debe estar entre "" para evitar errores y demás, en caso de que necesites una variable o otra cosa puedes usar una interpolación ejemplo:

Ejemplo de url correcta [.scss]
$roboto-font-path: "../fonts/roboto";

@font-face {
    // This is parsed as a normal function call that takes a quoted string.
    src: url("#{$roboto-font-path}/Roboto-Thin.woff2") format("woff2");

    font-family: "Roboto";
    font-weight: 100;
}

Evita todo uso de texto sin "" dentro de url() así como también intentos de concatenación.

variables

Todas las variables en sass empiezan con $, por ejemplo $color sería una variable. Como toda variable podemos guardar un valor en esta para luego ser usado con el nombre de esta.

Ejemplo

Ejemplo
$main-font-color: darkgray;
p{
   color:$main-font-color;
}
body{
   color:$main-font-color;
}

En esta ocasión estamos utilizando una variable de ámbito global para poner el mismo color a todos los textos. Puedes poner una variable de ámbito local entre los corchetes { } pertenecientes a algún elemento.

Ejemplo

Ejemplo de local y global
$golbal: darkgray;
p{
  $local:red; 
  color:$local;
}
body{
   color:$global;
}

Valores Por defecto

Es probable que queramos hacer un archivo SASS(.sass,scss) con valores por defecto como archivo base y estos puedan ser cambiados según lo que desee el cliente.

Esto lo puedes hacer con !default y utilizar el archivo con use.

library.scss
$black: #000 !default;
$border-radius: 0.25rem !default;
$box-shadow: 0 0.5rem 1rem rgba($black, 0.15) !default;

code {
  border-radius: $border-radius;
  box-shadow: $box-shadow;
}
style.scss
@use 'library' with (
  $black: #222,
  $border-radius: 0.1rem
);

Shadowing

Tal vez estás pensando que ocurre cuando la variable local y la global poseen el mismo nombre, cuando ocurre esto el valor de la variable local es tomado, pero este valor no cambia el valor de la variable global.

Las variables build-in y las variables de funciones son un tanto diferentes, ya que usan build in modules lo tocaré más adelante para no entreverar el tema

interpolacion #{}

Las interpolaciones nos permiten combinar el resultado de una expresión SASS con una porción o pedazo de CSS.

Ya vimos un ejemplo de interpolación antes en url() veámoslo denuevo.

Ejemplo de url correcta [.scss]
$roboto-font-path: "../fonts/roboto";

@font-face {
    // This is parsed as a normal function call that takes a quoted string.
    src: url("#{$roboto-font-path}/Roboto-Thin.woff2") format("woff2");

    font-family: "Roboto";
    font-weight: 100;
}

Como puede ver en esta ocasión la url final cuando sea nuestro codigo SASS procesado sera url(../fonts/roboto/Robot-Thin.woff2)

Ahora veamos otro ejemplo, yo podría querer hacer algo como las platillas de un framework de CSS por ejemplo en bootstrap tenemos el grid o grilla de 12 columnas.

Nuestra base para hacer algo como eso sería algo así:

Ejemplo simple de interpolacion
$nr:1;

.col-#{$nr}{
width:100%/(12-$nr)
}
.col-1 {
  width: 9.0909090909%;
}

Tenga en cuenta que en el ejemplo anterior no puedo utilizar la variable directamente sobre .col-, continuaremos este tema de la grid en los siguientes apartados de este post, Dando como resultado final un grid.

At-Rules @

Antes de ver los diferentes At-Rules, tenemos que entender lo que es un At-Rule en CSS, en español le llamamos reglas y son una declaración de como debe comportarse nuestro CSS. Veamos un ejemplo fácil de entender de CSS.

Creo que el at-Rule más conocido de CSS es @media, el cual nos ayuda con nuestras paginas responsives, talvez no conoscas este at-rule debido a que lo usas constantemente con un framework CSS como puede ser bootstrap por ejemplo en las col-sm-6 por ejemplo.

Fragmento de codigo CSS de bootstrap
@media (min-width: 576px) {
  .container-sm, .container {
    max-width: 540px;
  }
}
@media (min-width: 768px) {
  .container-md, .container-sm, .container {
    max-width: 720px;
  }
}
@media (min-width: 992px) {
  .container-lg, .container-md, .container-sm, .container {
    max-width: 960px;
  }
}
@media (min-width: 1200px) {
  .container-xl, .container-lg, .container-md, .container-sm, .container {
    max-width: 1140px;
  }
}
@media (min-width: 1400px) {
  .container-xxl, .container-xl, .container-lg, .container-md, .container-sm, .container {
    max-width: 1320px;
  }
}

Como puede ver el container varía según el tamaño de la pantalla. Si desas ver el código del grid de bootstrap puedes encontrarlo en https://github.com/twbs/bootstrap/blob/main/dist/css/bootstrap-grid.css

Volviendo a SASS tenemos, varios at rules los cuales nos ayudaran a «programar» en nuestro código SASS, aunque talvez no guste a algunas personas que lo llame programar porque de hecho no estás programando un programa, estás diciéndole como vas a hacer un procesado de CSS.

@use

es una regla utilizada para la carga de mixins, functiones y variables de otros archivos SASS, Las hojas de estilo cargadas con @use son llamadas módulos

la reglas reglas use van al principio de nuestro archivo, con una excepción la cual es @forward.

foundation/code.scss
code {
  padding: .25em;
  line-height: 0;
}
foundation/lists.scss
ul, ol {
  text-align: left;

  & & {
    padding: {
      bottom: 0;
      left: 0;
    }
  }
}
style.scss
@use 'foundation/code';
@use 'foundation/lists';

como puede ver el uso de @use es muy similar a el uso de use de cualquier proyecto que utilize composer en PHP como pueden ser los proyectos de Laravel.

Volviendo al uso de @use ¿como podemos acceder a un miembro de nuestro modulo?

Para acceder a un miembro del modulo deberas de utilizar el nombre del namespace seguido de . y el miembro que queramos usar(<namespace>.<miembro>), este es por defecto el ultimo componente de la url dada por ejemplo si la url es la siguiente @use ‘root/components/notes.scss’ el namespace sera notes.

Otra opción es usar @include <namespace>.<member> en vez de usar <namespace>.<member> y esta ultima es la mas utilizada.

También junto con use podemos utilizar aliases:

poniendole un alias al namespace
@use "src/corners" as c;

.button {
  @include c.rounded;
  padding: 5px + c.$radius;
}

Usar as para el alias esta bien pero que tal si yo quiero utilizar directamente las variables, mixins y funciones de el archivo que estoy cargando.

Para esto puedes usar as *

carga de modulo sin namespace
@use "src/corners" as *;

.button {
  @include rounded;
  padding: 5px + $radius;
}

@forward

carga hojas de estilos SASS dejando habiltados los mixins, funciones y variables cuando es cargada con la regla @use.

La regla @ forward hace posible la organización de archivos SASS dejando a los usuarios cargar una solo archivo como entrada.

Ejemplo: recuerda que dije que haríamos un gril o grilla con todo lo que diéramos aquí. Podríamos utilizar varios archivos con las distintas @media de este modo hacer las cosas responsive.

media.scss
@forward "media/media_xsmall";
@forward "media/media_small";
@forward "media/media_medium";
@forward "media/media_large";
@forward "media/medias_xlarge";
main.scss
@use "media";
Utilizar la regla @forward es recomendable en vez de utilizar @import y por ende no veremos @ import en este post.

@import

Importa el contenido de un archivo en otro este puede ser CSS como SASS. Esta regla se encuentra en desuso y se recomienda utilizar forward en su lugar.

@mixin y @include

La regla @mixin nos permite definir estilos reutilizables dentro de la hoja de estilo. Esto nos permite eludir la creacion de clases no semanticas como .float-left.

Sintaxis
@mixin <name> { ... }

Tambien a los mixin les podemos pasar argumentos con la siguiente sintaxis:

Sintaxis
@mixin name(<arguments...>) { ... }

Los mixins pueden ser incluidos en otras partes de la hoja de estilo utilizando la regla @include, en esta ocasión cambiaré el ejemplo que da la página oficial y haremos un ejemplo para que haga .float-left donde queramos, ya que me parece mal mencionar dicho aspecto y no dar un ejemplo simple.

Ejemplo de @mixin y @include[scss]
$fontcolor: black;
@mixin light-border{
    border:1px solid gray;
    background-color:inherit;
    border-radius:5px;
}
@mixin fl {
   float:left;
   margin-left:5px;
}

.card{
    @include fl;
    @include light-border;
   color:$fontcolor;
}

¿Puedo incluir un mixin dentro de otro mixin?

Sí, puedes incluir tantos como quieras o escalonarlos, aunque es posible que te sea difícil saber lo que estás haciendo si escalonas demasiado. Por ejemplo, si anidas de esta manera.

  • mixin
    • mixin
      • mixin

Es probable que te pierdas en alguna operación/accion futura que quieras hacer o que el resultado no sea el esperado.

Por eso es conveniente mantener las cosas simples y el codigo facil de leer.

@function

Las funciones nos permiten hacer operaciones complejas, que pueden ser reutilizadas a lo largo de la hoja de estilo SASS o scriptSASS.

En esta ocasión haremos un ejemplo simple supongamos que tenemos un botón para un formulario y cuando pase el mouse por encima de este cambie su color al color opuesto.

Veamos como podríamos hacer esto con SASS.

[scss]
$formbutton:seagreen;

@function invert-color($rcolor){
    $inverted: change-color($rcolor, $hue: hue($rcolor) + 180);
    @return $inverted;
}

form button{
    color:black;
    background-color:$formbutton;
    :hover{
        background-color:invert-color($formbutton);
    }
}

@extends

Hay ocasiones que una clase necesita tener los estilos de otra, además de sus propios estilos. Esto con CSS lo hacemos de la siguiente manera.

si teniamos las clases a y b, y b poseía todos los estilos de b

en CSS
.a, .b{
  /*codigo que posee tanto a como b*/
}
.b{
 /*codigo solo de b*/
}

Para poder genera esta clase de CSS tendremos que utilizar la palabra @extends.

El siguiente es un ejemplo de la pagina oficial de SASS que analizaremos:

Ejemplo de extends
.error {
  border: 1px #f00;
  background-color: #fdd;

  &--serious {
    @extend .error;
    border-width: 3px;
  }
}
.error, .error--serious {
  border: 1px #f00;
  background-color: #fdd;
}
.error--serious {
  border-width: 3px;
}

Como podemos ver en nuestro código SASS utilizamos @extend en &–serious esto hara que el código del padre este presente en el futuro .error–serious tenga en cuenta que & hace que tome el nombre de la clase padre en este caso .error ya que es una clase anidada dentro de .error

Si no tuviéramos & en –serious quedaria .error –serious y esto no es lo que queremos, de hecho seria como una sintaxis mal escrita de CSS.

Además de esto en CSS cuando un selector está separado, de esta manera quiere decir que todos los elementos –serious(no existe) que están dentro de los elementos con clase .error tendrán ese estilo.

Por último tenemos nuestro resultado(result) luego de realizar el watch.

@error

La regla error se usa en los mixins como en las funciones, ya que es probable que otro programador use tu hoja de estilo SASS en un futuro, también es probable que este pase parámetros no esperados a estas funciones o mixins.

En este caso es conveniente que la función o mixin tire un error y pare la ejecución de esta.

El siguiente es el ejemplo en la pagina oficial pero sin todo el código, lo que nos interesa es que entienda como se usa y para que se usa.

@error example
@mixin reflexive-position($property, $value) {
  @if $property != left and $property != right {
    @error "Property #{$property} must be either left or right.";
  }
   /*code
goes
here*/
}

como podemos ver este mixin solo acepta right o left como parámetro cualquier otro parámetro dispara el error.

@warn

Warn es muy parecido a error de echo se aplica tanto a mixin como a las funciones, pero en cambio a dar un error nos dará una advertencia. Su propósito es advertir a el usuario que ciertos parámetros no son correctos o se desaconseja su uso, también puedes desaconsejar el uso cuando se llama a tu API de manera no optima.

El ejemplo de la pagina oficial es bastante claro:

@warn example
$known-prefixes: webkit, moz, ms, o;

@mixin prefix($property, $value, $prefixes) {
  @each $prefix in $prefixes {
    @if not index($known-prefixes, $prefix) {
      @warn "Unknown prefix #{$prefix}.";
    }

    -#{$prefix}-#{$property}: $value;
  }
  #{$property}: $value;
}

.tilt {
  // Oops, we typo'd "webkit" as "wekbit"!
  @include prefix(transform, rotate(15deg), wekbit ms);
}

en el ejemplo anterior nuestro mixin ve si el prefijo pasado esta entre los prefijos conocidos para CSS(webkit,moz,ms,o). En nuestro caso cuando en tilt usamos el mixin prefix no estamos utilizando webkit sino wekbit el cual no es un prefijo valido. En este caso al utilizar watch nos advertirá de este error de tipeo(escritura).

@debug

Es probable que cuando estes creando tu hoja de estilos SASS quieras saber el valor de una expresion que has creado esto lo puedes hacer utilizando @debug

@at-root

todo lo escrito en at-root sera emitido en la raiz del documento en pocas palabras no habra ninguna clase de nesting

veamos un ejemplo simple ya que la pagina official da un ejemplo que utiliza un modulo build-in de SASS y aun no se ha tocado ese tema.

Ejemplo simple de at-route
.error{
    border: 1px solid black;
 @at-root.error2{
    color:red;
 }   
}

el css que generara el correr el codigo anterior sera el siguiente:

CSS generado
.error {
  border: 1px solid black;
}
.error2 {
  color: red;
}

en caso de que @at-root no sea aplicado el css quedaria como sigue:

sin uso de @at-root
.error {
  border: 1px solid black;
}
.error .error2 {
  color: red;
}

Las siguientes reglas son para el control de flujo en nuestra hoja de estilo SASS.


@if y @else

If y else cumplen la misma funcion que en cualqueir lenguaje de programacion.if controla si el bloque sera ejecutado segun el valor de la sentencia: if <sentencia>{/*bloque*/} obviamente sentencia debe dar un valor booleano. En caso de que la sentencia no cumpla, en definitiva si su valor es false podemos usar la expresion @else o @else-if.

Sintaxis
@if $condition{
   // do something
}

@each

Esta regla es muy parecida a foreach en PHP, si tienes alguna familiaridad con programar en PHP te será muy fácil de usar. Esta regla permite dar estilo o evaluar código para cada elemento perteneciente a una lista o par en un mapa de pares.

Sintaxis
@each $variable in $expression {
 ... 
}
Sintaxis
@each $variable1, $variable2 in $expression { 
   ... 
}

Tenga en cuenta que las variables las estamos definiendo in situ, es decir en el mismísimo @each Ejemplo de el sitio oficial para un pair map.

Aplicando each a un mapa de pares [.scss]
$icons: ("eye": "\f112", "start": "\f12e", "stop": "\f12f");

@each $name, $glyph in $icons {
  .icon-#{$name}:before {
    display: inline-block;
    font-family: "Icon Font";
    content: $glyph;
  }
}
@charset "UTF-8";
.icon-eye:before {
  display: inline-block;
  font-family: "Icon Font";
  content: "\f112";
}

.icon-start:before {
  display: inline-block;
  font-family: "Icon Font";
  content: "\f12e";
}

.icon-stop:before {
  display: inline-block;
  font-family: "Icon Font";
  content: "\f12f";
}

@for

Recorre o cuenta desde un numero a otro, si se utiliza to el ultimo numero ex excluido, en cambio si se usa through es incluido

Sintaxis con to
@for $variable from $expresion1 to $expresion2{
  ...
}

o

Sintaxis con through
@for $variable from $expresion1 through $expresion2{
  ...
}

@while

Como en todos los lenguajes de programación, el bloque dentro de while se ejecuta mientras la condición sea verdadera, tenga en cuenta que la condición también puede ser una expresión y no solo una variable, es por ello que en la documentación original esta aparece como <expression>

Sintaxis
@while $condition { 
... //bloque dentro de while
}

Valores

Operaciones

Work-in-progress

The text that continues is being created and could change

Operatoroperator typeoperator name
notunarynegation
+numeric, unaryadds
numeric, unarySubtraction
/numeric, unarydivision
*numericmultiplier
%numericmodule
==equalityequal
!=equalitynot equal
>relationalgreater than
<relationalless than
>=relationalgreater than or equal
<=relationalless than or equal
notbooleanopposit of expresion
andbooleana and b si a y b son true
orbooleana or b si a o b son true

Modulos Build-in

Comandos de consola

Work-in-progress-end

Work in progress ended keep reading without worrying

Comming Soon

Under research, or under creation

Category: otros
Something wrong? If you found an error or mistake in the content you can contact me on Twitter | @luisg2249_luis.
Last 4 post in same category