====== 4. SASS Avanzado ======
Veamos ahora funcionalidades mas avanzadas de SASS
==== Mas información ====
Enlaces con mas información de SASS:
* [[https://sass-guidelin.es/|Sass Guidelines]]
* [[https://sass-lang.com/documentation/at-rules/mixin/|Sass: @mixin and @include]]
* [[https://sass-lang.com/documentation/at-rules/function/|Sass: @function]]
* [[http://thesassway.com/intermediate/if-for-each-while|Sass control directives: @if, @for, @each and @while]]
* [[https://sass-lang.com/documentation/at-rules/control/if|Sass: @if and @else]]
* [[https://sass-lang.com/documentation/at-rules/control/for|Sass: @for]]
* [[https://sass-lang.com/documentation/at-rules/control/each#with-maps|sass: @each with maps]]
Curso de SASS:
* [[https://www.chucksacademy.com/es/topic/css-preprocessors|Preprocesadores de CSS]]
===== Mixings =====
Son como trozos de código CSS que puedes añadir en otra clase CSS. Es como llamar a una "función" pero con CSS. Son muy útiles para evitar repetir código CSS.
@mixin box-shadow($color) {
-webkit-box-shadow: 2px 10px 24px $color;
-moz-box-shadow: 2px 10px 24px $color;
box-shadow: 2px 10px 24px $color;
}
.c-button {
color: #FF0000;
@include box-shadow(#FF0000);
}
.c-panel {
color: #00FF00;
@include box-shadow(#00FF00);
}
se transforma en
.c-button {
color: #FF0000;
-webkit-box-shadow: 2px 10px 24px #FF0000;
-moz-box-shadow: 2px 10px 24px #FF0000;
box-shadow: 2px 10px 24px #FF0000;
}
.c-panel {
color: #00FF00;
-webkit-box-shadow: 2px 10px 24px #00FF00;
-moz-box-shadow: 2px 10px 24px #00FF00;
box-shadow: 2px 10px 24px #00FF00;
}
===== Funciones =====
En SASS también existen funciones "normales" que calculan un valor.
@function getBorderSize($size) {
@return 10px * $size;
}
.c-button {
color: #FF0000;
border: getBorderSize(2) solid #00FF00;
}
se transforma en
.c-button {
color: #FF0000;
border: 20px solid #00FF00;
}
===== Arrays =====
Veamos ahora como usar los arrays
* Para acceder a un elemento de un array se usa la función ''nth''. **El índice empieza por 1 y no por cero**.
$lista:(10px,12px,20px,40px);
$indice:1;
$valor:nth($lista,$indice);
* Para obtener el tamaño de un array se usa la función ''length'':
$lista:(10px,12px,20px,40px);
$tamanyo:length($lista);
===== Mapas =====
Veamos ahora las funciones de maps
* Para acceder a un elemento de un map se usa la función ''map-get'':
$mapa:(
"a": enero,
"b": febrero
);
$clave:a;
$valor:map-get($mapa,$clave);
* Para obtener las claves de un map.:
$mapa:(
"a": enero,
"b": febrero
);
$keys:map-keys($mapa);
Se obtiene un array los valores ''a'' y ''b''.
===== Bucle @for to =====
Se usa para hacer un bucle desde ''0'' a ''n-1''
* Bucle con índice.
@for $i from 0 to 4 {
.g--border-#{$i} {
border: 10px * $i solid #00FF00;
}
}
se transforma en
.g--border-0 {
border: 0px solid #00FF00;
}
.g--border-1 {
border: 10px solid #00FF00;
}
.g--border-2 {
border: 20px solid #00FF00;
}
.g--border-3 {
border: 30px solid #00FF00;
}
===== Bucle @for through =====
Se usa para hacer un bucle desde ''1'' hasta ''n''
* Bucle con índice.
@for $i from 1 through 4 {
.g--border-#{$i} {
border: 10px * $i solid #00FF00;
}
}
se transforma en
.g--border-1 {
border: 10px solid #00FF00;
}
.g--border-2 {
border: 20px solid #00FF00;
}
.g--border-3 {
border: 30px solid #00FF00;
}
.g--border-4 {
border: 40px solid #00FF00;
}
===== Bucle @each de un array =====
Recorre los elementos de una lista
$lista:(3px,6px,7px,9px);
@each $value in $lista {
.g--padding-#{$value} {
padding: $value;
}
}
.g--padding-3px {
padding: 3px;
}
.g--padding-6px {
padding: 6px;
}
.g--padding-7px {
padding: 7px;
}
.g--padding-9px {
padding: 9px;
}
===== Bucle @each de un Map =====
Para recorrer un map la forma más sencilla es la siguiente:
$map:(
"s":3px,
"m":6px,
"l":7px,
"xl":9px
);
@each $key,$value in $map {
.g--padding-#{$key} {
padding: $value;
}
}
.g--padding-s {
padding: 3px;
}
.g--padding-m {
padding: 6px;
}
.g--padding-l {
padding: 7px;
}
.g--padding-xl {
padding: 9px;
}
===== Condicional @if =====
@mixin border($size) {
@if $size>=3 {
$color:#FF0000;
} @else {
$color:#00FF00;
}
border: $size*2 solid $color;
}
.c-caja1 {
color: #FF0000;
@include border(2px);
}
.c-caja2 {
color: #FF0000;
@include border(5px);
}
se transforma en
.c-caja1 {
color: #FF0000;
border: 4px solid #00FF00;
}
.c-caja2 {
color: #FF0000;
border: 10px solid #FF0000;
}
===== Funciones de Color =====
Ya existen una serie de funciones predefinidas en SASS: [[https://www.w3schools.com/sass/sass_functions_color.asp|Sass Color Functions]]
Entre las mas útiles están:
* lighten: Incrementa la luminosidad de un color
* darken: Decrementa la luminosidad de un color
* saturate: Incrementa la saturación de un color
* desaturate: Decrementa la saturación de un color
$color-fondo: #F456E3;
$color-borde: darken($color-fondo,30%);
.c-caja {
background-color: $color-fondo;
border: 4px solid $color-borde;
}
se transforma en
.c-caja {
background-color: #F456E3;
border: 4px solid #a60b95;
}
===== Variables CSS =====
En CSS existen las variables. La ventaja de las variables CSS vs las de SASS son:
* Se pueden cambiar en tiempo de ejecución desde JavaScript
* Pueden existir a nivel local dentro de los selectores.
Veamos como funcionan.
* Los nombres de las variables debe empezar por ''--''
* Para usar las variables en CSS se usa ''var(--nombre-variable)''
* Las variables de CSS se crean así:
:root {
--color-alternativo-5: #0056b8;
}
* Desde CSS se usan así.
.c-button {
background-color:var(--color-alternativo-5)
}
* Se puede definir un valor por defecto como segundo parámetro
.c-button {
background-color:var(--color-alternativo-5,#FF0000)
}
Esto permite que podamos crear más valores por defecto con el siguiente truco de forma que si no está una variable, usemos otra y sino otra ,etc.:
.c-button {
background-color:var(--color-alternativo-5,var(--color-alternativo,#FF0000))
}
Es este caso el ''background-color'' se usa la variable ''--color-alternativo-5'' pero si no existe esa variable se usaría la variable ''--color-alternativo'' pero si esa tampoco existe se usará ''#FF0000''
* Desde JavaScript se modifican así:
let root = document.documentElement;
root.style.setProperty('--color-normal-5', "#FF0000");
* Desde JavaScript se leen así:
let root = document.documentElement;
let colorNormal=getComputedStyle(root).getPropertyValue("--color-normal-5");
==== Creación de variables ====
A lo largo del curso hemos visto que debemos limitar nuestras opciones a usar serie de valores. Ahora esa serie de valores deben ser variables.
$paddings:(
"xs":"1px",
"s":"2px",
"m":"6px",
"l":"12px",
"xl":"20px"
);
:root {
@each $key,$value in $paddings {
--padding-#{$key}:$value;
}
}
Que generá en CSS
:root {
--padding-xs:1px;
--padding-s:2px;
--padding-m:6px;
--padding-l:12px;
--padding-xl:20px;
}
Esa variables se usarán siempre tanto en los componentes , como layouts, como globales.
.c-button {
--c-button-padding-vertical:var(--padding-s,6px);
--c-button-padding-horizontal:var(--padding-m,8px);
padding-top: var(--c-button-padding-vertical);
padding-bottom: var(--c-button-padding-vertical);
padding-left: var(--c-button-padding-horizontal);
padding-right: var(--c-button-padding-horizontal);
}
.g--padding-vertical-m {
padding-top: var(--padding-m);
padding-bottom: var(--padding-m);
}
El usar variable nos lleva a tener muchísimas variables en CSS lo que nos puede llevar a pensar si eso afectará al rendimiento. En el documento {{ :clase:daw:diw:1eval:css_variables_performance_benchmark_2021_by_konrad_fedorczyk_medium.pdf |CSS Variables performance benchmark 2021}} nos indica que no afecta prácticamente nada al rendimiento.
Algunas de las variables de colores en la página principal de google, ¿te suena de algo?:
{{:clase:daw:diw:1eval:colores.png|}}
=== Ejemplo de menu lateral ===
Ejemplo de menú lateral con variable locales.
Código de Àngela Hermosilla del Río
{{:clase:daw:diw:1eval:menu-lateral.png?200|}}
.c-menu-lateral {
--c-menu-logo-font-size: var(--font-size-l);
--c-menu-option-titulo-font-size: var(--font-size-m);
--c-menu-option-subtitulo-font-size: var(--font-size);
--c-menu-font-family: var(--font-family-arial);
--c-menu-option-titulo-color: var(--color-grey-1);
--c-menu-option-subtitulo-color: var(--color-grey);
--c-menu-option-titulo-color-warning: var(--color-red-3);
--c-menu-option-subtitulo-color-warning: var(--color-red-4);
--c-menu-background-color: var(--color-grey-9);
--c-menu-background-color-hover: var(--color-grey-8);
--c-menu-background-color-warning: var(--color-red-9);
--c-menu-background-color-warning-hover: var(--color-red-8);
--c-menu-padding-exterior: var(--padding-4);
--c-menu-padding-interior: var(--padding-2);
--c-menu-width: var(--width-300);
--c-menu-width-icono:var(--width-30);
display: grid;
grid-template-rows: auto 1fr auto;
padding:var(--c-menu-padding-exterior);
&__logo {
font-size: var(--c-menu-logo-font-size);
padding: var(--c-menu-padding-exterior);
background-color: var(--c-menu-background-color);
}
&__opciones{
overflow: auto;
}
&__opcion {
display: flex;
flex-direction: row;
padding: var(--c-menu-padding-exterior);
background-color: var(--c-menu-background-color);
&-icono{
padding: var(--c-menu-padding-exterior);
width: var(--c-menu-width-icono);
}
&-titulo{
font-weight: bold;
font-size: var(--c-menu-option-titulo-font-size);
color: var(--c-menu-option-titulo-color);
padding: var(--c-menu-padding-interior);
&--warning{
color: var(--c-menu-option-titulo-color-warning);
}
}
&-subtitulo{
font-size: var(--c-menu-option-subtitulo-font-size);
color: var(--c-menu-option-subtitulo-color);
padding: var(--c-menu-padding-interior);
&--warning{
color: var(--c-menu-option-subtitulo-color-warning);
}
}
&--warning{
color: var(--c-menu-background-color-warning);
@include border(var(--c-menu-background-color-warning-hover),var(--border-radius-2));
:hover{
color: var(--c-menu-background-color-warning-hover);
}
}
:hover{
background-color: var(--c-menu-background-color-hover);
}
}
&__footer {
font-size: var(--c-menu-logo-font-size);
padding: var(--c-menu-padding-exterior);
background-color: var(--c-menu-background-color);
}
}
Ajuda DANA
Inicio
Casos activos
Ver todos los casos activos
Voluntómetro
Medidor de voluntarios por localidad
Solicitar ayuda
Si necesitas asistencia
Ofrecer ayuda
Si puedes ayudar a otros
Desaparecidos
Reportar o buscar
===== Bootstrap =====
En el siguiente artículo [[https://getbootstrap.com/docs/5.0/utilities/api/|Utility API]], vemos como Boostrap ha creado algo muy similar a lo que estamos haciendo en clase.
===== Ejercicios =====
==== Ejercicio 1 ====
{{:clase:daw:diw:1eval:sombras_y_profundidad.png|}}
* Crea los globales de forma que retorne cada una de los sombreados. Sabiendo que las claves empiezan en 1 y hay otra que será ''none''.
g--shadow-none { }
g--shadow-1 { }
g--shadow-2 { }
g--shadow-3 { }
g--shadow-4 { }
g--shadow-5 { }
* Crea las variables CSS correspondientes.
* Crea el mixing ''box-shadow($key)''. Usará las funciones que has creado antes y de forma que tenga las propiedades css de:
* ''-webkit-box-shadow''
* ''-moz-box-shadow''
* ''box-shadow''
==== Ejercicio 2 ====
Haz una función llamada ''getFontSize($index)'' para ayudar a generar tamaños de fuentes. Siendo el parámetro ''$index'' un número entero.
Calcula el tamaño de la fuente con la siguiente fórmula:
$$ {Tamaño \quad fuente \quad en \quad px}=1.2^{\$index}*16 $$
La función retornará el tamaño de la fuente en base al parámetro ''$index''. Este función tiene 2 números //mágicos//. El 16 es el tamaño base de la fuente. Es decir cuando vale 0. Y el 1,2 es la tasa de crecimiento. Cuando mayor sea ese número mas rápidamente se hacen grandes los tamaños de fuentes. Una página que hace estos mismos cálculos es [[https://www.modularscale.com/?16&px&1.2|Modularscale]].
Para hacer los cálculos de potencias en SASS puedes consultar el siguiente artículo: [[https://css-tricks.com/snippets/sass/power-function/|SASS Power Function]]
Haz que usando la función ''getFontSize($tamanyo)'' y un bucle se generen automáticamente las siguientes clases CSS:
g--font-size-3s { font-size:9.25px; }
g--font-size-2s { font-size:11,11px; }
g--font-size-1s { font-size:13,33px; }
g--font-size { font-size:16px; }
g--font-size-1l { font-size:19.2px; }
g--font-size-2l { font-size:23.04px; }
.....
g--font-size-6l { font-size:47.775px; }
==== Ejercicio 3 ====
Crea los globales y las variable CSS de los siguientes colores:
{{:clase:daw:diw:1eval:paleta_de_colores.png|}}
==== Ejercicio 4 ====
Modifica la clase ''c-button'' del tema 1 para que ahora haga uso de variables CSS en los paddings, etc.
==== Ejercicio 5 ====
Dado la siguiente variable de SASS llamada ''$utilities$''
$utilities: (
"padding": (
type:0,
property: padding,
class: g--padding-,
values: (
1: 1px,
2: 5px,
3: 10px,
4: 20px,
5: 40px,
)
),
"font-size": (
type:1,
property: font-size,
class: g--font-size-,
values: (6px,7px,10px,12px,14px,16px,18px,20px)
),
"width": (
type:2,
property: width,
class: g--width-,
max:9
),
"$keys": ( xxxxs,xxxs,xxs,xs,s,m,l,xl,xxl,xxxl )
);
Que crea un programa en SASS para que genere el siguiente CSS:
.g--padding-1 { padding: 1px; }
.g--padding-2 { padding: 5px; }
.g--padding-3 { padding: 10px; }
.g--padding-4 { padding: 20px; }
.g--padding-5 { padding: 40px; }
.g--font-size-xxxxs { font-size: 6px; }
.g--font-size-xxxs { font-size: 7px; }
.g--font-size-xxs { font-size: 10px; }
.g--font-size-xs { font-size: 12px; }
.g--font-size-s { font-size: 14px; }
.g--font-size-m { font-size: 16px; }
.g--font-size-l { font-size: 18px; }
.g--font-size-xl { font-size: 20px; }
.g--width-1 { width: 1px; }
.g--width-2 { width: 4px; }
.g--width-3 { width: 9px; }
.g--width-4 { width: 16px; }
.g--width-5 { width: 25px; }
.g--width-6 { width: 36px; }
.g--width-7 { width: 49px; }
.g--width-8 { width: 64px; }
.g--width-9 { width: 81px; }
Usa siempre que puedas funciones de SASS
@function getKeyFromIndex($index) {
$key:$index*10;
@return $key;
}
@function getValueFromIndex($index) {
$value:$index*$index*1px;
@return $value;
}
$prefix: ".";
@each $utility-key, $utility in $utilities {
@if ($utility-key!= "$keys") {
$type: map-get($utility, usekeys);
$property: map-get($utility, property);
$class: map-get($utility, class);
@if ($type==0) {
$values: map-get($utility, values);
@each $key, $value in $values {
#{$prefix}#{$class}#{$key} {
#{$property}: #{$value};
}
}
}
@if ($type==1){
$keys:map-get($utilities,"$keys");
$values: map-get($utility, values);
@for $index from 1 through length($values) {
$key: nth($keys,$index);
$value:nth($values,$index);
#{$prefix}#{$class}#{$key} {
#{$property}: $value;
}
}
}
@if ($type==2){
$max:map-get($utility, max);
@for $index from 1 through $max {
$key: getKeyFromIndex($index);
$value:getValueFromIndex($index);
#{$prefix}#{$class}#{$key} {
#{$property}: $value;
}
}
}
}
}
==== Ejercicio 6 ====
Sabiendo que ya tienes los botones del tema 1.
Vamos ahora a hacer el componente ''c-dialog''.
Ventana modal
bla bla
{{:clase:daw:diw:1eval:evolucion_modal.png?1000|}}
Crea 3 mixing para reusar el CSS de ''c-button'' y ''c-dialog__close'':
* ''button-border''
* ''button-background''
* ''button-text''