Krypton Solid

Tipografía receptiva con Sass Maps

Tipografía receptiva con Sass Maps

Manejar un ritmo tipográfico consistente no es fácil, pero cuando el tipo es receptivo, las cosas se vuelven aún más difíciles. Por suerte, Los mapas de Sass hacen que la tipografía receptiva sea mucho más manejable. Escribir el código es una cosa, pero hacer un seguimiento de los valores de tamaño de fuente para cada punto de interrupción es otra, y lo anterior es solo para párrafos. Lanzar en h1 a h6s, cada uno con tamaños de fuente variables para cada punto de interrupción, y se vuelve engorroso, especialmente cuando el tipo no se escala linealmente.

Manejar un ritmo tipográfico consistente no es fácil, pero cuando el tipo es receptivo, las cosas se vuelven aún más difíciles. Afortunadamente, los mapas de Sass hacen que la tipografía receptiva sea mucho más manejable.

Escribir el código es una cosa, pero hacer un seguimiento de los valores de tamaño de fuente para cada punto de interrupción es otra, y lo anterior es solo para párrafos. Lanzar en h1 a h6s, cada uno con tamaños de fuente variables para cada punto de interrupción, y se vuelve engorroso, especialmente cuando el tipo no se escala linealmente.

Otras lecturas en SmashingMag:

Si ha intentado abordar el tipo de respuesta, esto puede parecerle familiar:


p { font-size: 15px; }

@media screen and (min-width: 480px) {
  p { font-size: 16px; }
}
@media screen and (min-width: 640px) {
  p { font-size: 17px; }
}
@media screen and (min-width: 1024px) {
  p { font-size: 19px; }
}

Las variables de Sass son excelentes para hacer que los valores sean reutilizables en todo un proyecto, pero administrarlos para tamaños de fuente receptivos se convierte fácilmente en un desastre.


$p-font-size-mobile : 15px;
$p-font-size-small  : 16px;
$p-font-size-medium : 17px;
$p-font-size-large  : 19px;

$h1-font-size-mobile: 28px;
$h1-font-size-small : 31px;
$h1-font-size-medium: 33px;
$h1-font-size-large : 36px;

// I think you get the point…

Aquí es donde Mapas de Sass y los bucles son poderosos: me han ayudado a administrar valores del índice z, colores y, como verá en un momento, tamaños de fuente.

Organizar tamaños de fuente con Sass Maps

Comencemos por crear un mapa Sass con pares clave-valor: puntos de interrupción como claves y tamaños de fuente como valores correspondientes.


$p-font-sizes: (
  null  : 15px,
  480px : 16px,
  640px : 17px,
  1024px: 19px
);

Teniendo en cuenta los dispositivos móviles, vemos que la clave null representa el tamaño de fuente predeterminado (no en una consulta de medios) y los puntos de interrupción están en orden ascendente.

A continuación, el mixin, que itera a través de un mapa Sass y genera las consultas de medios apropiadas.


@mixin font-size($fs-map) {
  @each $fs-breakpoint, $fs-font-size in $fs-map {
    @if $fs-breakpoint == null {
      font-size: $fs-font-size;
    }
    @else {
      @media screen and (min-width: $fs-breakpoint) {
        font-size: $fs-font-size;
      }
    }
  }
}

Nota: Vale la pena mencionar que este mixin, junto con los siguientes, presenta una lógica de programación básica. Sass, con la ayuda de SassScript (un conjunto de extensiones integradas), hace posibles construcciones básicas de programación, como if/else declaraciones, each bucles y mucho más. Le animo a que se tome un tiempo para leer el documentación. Las “funciones de poder” de Sass te presentarán una nueva dimensión de cosas que puedes hacer con Sass.

Luego usaremos el mixin para los párrafos:


p {
  @include font-size($p-font-sizes);
}

… Lo que da como resultado el siguiente CSS:


p { font-size: 15px; }

@media screen and (min-width: 480px) {
  p { font-size: 16px; }
}
@media screen and (min-width: 640px) {
  p { font-size: 17px; }
}
@media screen and (min-width: 1024px) {
  p { font-size: 19px; }
}

¡Administrar y realizar un seguimiento de los tamaños de fuente de los elementos se vuelve mucho más fácil! Con cada elemento nuevo, cree un mapa y llame al mixin en el selector apropiado.


$h1-font-sizes: (
  null  : 28px
  480px : 31px,
  640px : 33px,
  1024px: 36px
);

h1 {
  @include font-size($h1-font-sizes);
}

Mantenga los tamaños de fuente consistentes para varios elementos:


p, ul, ol {
  @include font-size($p-font-sizes);
}

Resolver la fragmentación del punto de interrupción

¡Pero espera! ¿Qué pasa si decidimos que queremos el tamaño de fuente de ps sea de 17 píxeles y de h1s ser 33 píxeles en un punto de interrupción de 700 píxeles, en lugar de 640 píxeles? Con la solución anterior, eso requeriría cambiar manualmente cada instancia de 640px. Al intentar resolver un problema, sin darnos cuenta hemos creado otro: la fragmentación del punto de interrupción.

Si podemos administrar los tamaños de fuente en los mapas de Sass, seguramente podemos hacer lo mismo con los puntos de interrupción, ¿verdad? ¡Exactamente!

Creemos un mapa para los puntos de interrupción comunes y asignemos a cada valor un nombre apropiado. También cambiaremos un poco el mapa de tamaños de fuente usando los nombres de puntos de interrupción que asignamos en $breakpoints para establecer una relación entre los puntos de interrupción y los mapas de tamaños de fuente.


$breakpoints: (
  small : 480px,
  medium: 700px, // Previously 640px
  large : 1024px
);

$p-font-sizes: (
  null  : 15px,
  small : 16px,
  medium: 17px,
  large : 19px
);

$h1-font-sizes: (
  null  : 28px,
  small : 31px,
  medium: 33px,
  large : 36px
);

El último paso es ajustar un poco la mezcla para que cuando repita el mapa de tamaños de fuente, use el nombre del punto de interrupción para obtener el valor apropiado de $breakpoints antes de generar la consulta de medios.


@mixin font-size($fs-map, $fs-breakpoints: $breakpoints) {
  @each $fs-breakpoint, $fs-font-size in $fs-map {
    @if $fs-breakpoint == null {
      font-size: $fs-font-size;
    }
    @else {
      // If $fs-font-size is a key that exists in
      // $fs-breakpoints, use the value
      @if map-has-key($fs-breakpoints, $fs-breakpoint) {
        $fs-breakpoint: map-get($fs-breakpoints, $fs-breakpoint);
      }
      @media screen and (min-width: $fs-breakpoint) {
        font-size: $fs-font-size;
      }
    }
  }
}

Nota: El mapa de puntos de interrupción predeterminado del mixin es $breakpoints; si el nombre de la variable de puntos de interrupción es diferente, asegúrese de cambiarlo en el segundo argumento de la línea 1.

¡Voila! Ahora, ¿qué pasa si queremos que un elemento tenga un tamaño de fuente para un punto de interrupción personalizado que no existe en $breakpoints? En el mapa de tamaños de fuente, simplemente coloque el valor del punto de interrupción en lugar de un nombre como clave, y el mixin hará el trabajo por usted:


$p-font-sizes: (
  null  : 15px,
  small : 16px,
  medium: 17px,
  900px : 18px,
  large : 19px,
  1440px: 20px,
);

p {
  @include font-size($p-font-sizes);
}

La magia pasa en el mixin gracias a Sass ‘ map-has-key función. Comprueba si el nombre de la clave existe en $breakpoints: Si existe, usará el valor de la clave; si no, asumirá que la clave es un valor personalizado y lo usará en su lugar al generar la consulta de medios.


p { font-size: 15px; }

@media screen and (min-width: 480px) {
  p { font-size: 16px; }
}
@media screen and (min-width: 700px) {
  p { font-size: 17px; }
}
@media screen and (min-width: 900px) {
  p { font-size: 18px; }
}
@media screen and (min-width: 1024px) {
  p { font-size: 19px; }
}
@media screen and (min-width: 1440px) {
  p { font-size: 20px; }
}

Mejora del ritmo vertical con altura de línea

La altura de la línea también es una parte importante para lograr un ritmo vertical constante. Entonces, sin exagerar, incluyamos la altura de la línea en la solución.

Amplíe el mapa de tamaños de fuente incluyendo tanto el tamaño de fuente como la altura de línea en una lista como el valor de la clave deseada:


$breakpoints: (
  small : 480px,
  medium: 700px,
  large : 1024px
);

$p-font-sizes: (
  null  : (15px, 1.3),
  small : 16px,
  medium: (17px, 1.4),
  900px : 18px,
  large : (19px, 1.45),
  1440px: 20px,
);

Nota: aunque los valores de altura de línea se pueden definir utilizando cualquier unidad CSS válida (porcentajes, píxeles, ems, etc.), los valores «sin unidades» son recomendado y privilegiado para evitar resultados inesperados por herencia.

Luego, necesitamos modificar el mixin para incluir la altura de la línea al generar el CSS.


@mixin font-size($fs-map, $fs-breakpoints: $breakpoints) {
  @each $fs-breakpoint, $fs-font-size in $fs-map {
    @if $fs-breakpoint == null {
      @include make-font-size($fs-font-size);
    }
    @else {
      // If $fs-font-size is a key that exists in
      // $fs-breakpoints, use the value
      @if map-has-key($fs-breakpoints, $fs-breakpoint) {
        $fs-breakpoint: map-get($fs-breakpoints, $fs-breakpoint);
      }
      @media screen and (min-width: $fs-breakpoint) {
        @include make-font-size($fs-font-size);
      }
    }
  }
}

// Utility function for mixin font-size
@mixin make-font-size($fs-font-size) {
  // If $fs-font-size is a list, include
  // both font-size and line-height
  @if type-of($fs-font-size) == "list" {
    font-size: nth($fs-font-size, 1);
    @if (length($fs-font-size) > 1) {
      line-height: nth($fs-font-size, 2);
    }
  }
  @else {
    font-size: $fs-font-size;
  }
}

El mixin comprueba si el valor de la clave en el mapa de tamaños de fuente es una lista en lugar de un valor de tamaño de fuente. Si es una lista, entonces obtiene el valor correcto de la lista por valor de índice, con la ayuda del nth función. Asume que el primer valor es el tamaño de la fuente y el segundo es la altura de la línea. Veámoslo en acción:


p {
  @include font-size($p-font-sizes);
}

Y aquí está el CSS resultante:


p { font-size: 15px; line-height: 1.3; }

@media screen and (min-width: 480px) {
  p { font-size: 16px; }
}
@media screen and (min-width: 700px) {
  p { font-size: 17px; line-height: 1.4; }
}
@media screen and (min-width: 900px) {
  p { font-size: 18px; }
}
@media screen and (min-width: 1024px) {
  p { font-size: 19px; line-height: 1.45; }
}
@media screen and (min-width: 1440px) {
  p { font-size: 20px; }
}

Esta solución final es fácilmente extensible para acomodar una serie de otros atributos, como pesos de fuente, márgenes, etc. La clave es modificar el make-font-size utilidad mixin y use el nth función para obtener el valor apropiado de la lista.

Conclusión

Hay varias formas de abordar la tipografía receptiva y el ritmo vertical consistente, y no se limitan a mi sugerencia. Sin embargo, encuentro que esto me funciona la mayoría de las veces.

El uso de esta combinación probablemente generará consultas de medios duplicadas en su CSS compilado. Se ha debatido mucho sobre las consultas de medios duplicadas frente a las consultas de medios agrupadas, usando @extend en lugar de mixinsy rendimiento y tamaño de archivo; sin embargo, las pruebas han concluido que «la diferencia, aunque fea, es mínima en el peor de los casos, esencialmente inexistente en el mejor de los casos».

También me doy cuenta de que mi solución no es sólida (no está diseñada para manejar rangos de consulta de medios, max-width o la orientación de la ventana gráfica). Dichas características se pueden implementar en el mixin (mi versión personal también convierte los valores de píxeles a ems), pero para consultas complejas de medios, prefiero escribir a mano. No olvide que puede utilizar el map-get función para recuperar valores de mapas existentes.

Alternativas

Unidades de ventana gráfica (vh, vw, vmin y vmax) también se puede utilizar para crear una tipografía adaptable:

Un ejemplo de unidades de ventana gráfica en acción. Una unidad de ventana gráfica = 1% del ancho o alto de la ventana gráfica. (Para una ventana gráfica de 1000 píxeles de ancho, 1vw = 10px; para una ventana gráfica de 500 píxeles de alto, 1vh = 5px.)

Por ejemplo, las unidades del ancho de la ventana gráfica se pueden usar para construir texto de héroe fluido. Sin embargo, debido a que el texto se escalará al ancho o alto de la ventana gráfica (a diferencia del tamaño del área de contenido de la página) y porque CSS actualmente carece min y max valores para el font-size propiedad, las unidades de ventana gráfica no son adecuadas para el texto del cuerpo: no importa el valor que elija, el tamaño del texto del cuerpo en las unidades de ventana siempre terminará siendo demasiado grande o demasiado pequeño en tamaños de navegador extremos, lo que requiere la intervención de una consulta de medios.

FitText.js hace un trabajo similar, con un enfoque en el tamaño del texto para que siempre descanse en una sola línea o medida. También se pueden utilizar técnicas SVG para lograr un efecto similar.

Finalmente, Erik van Blokland ha estado trabajando en algunos posibilidades emocionantes para la tipografía receptiva, como las formas de letras que en realidad se modifican con el tamaño de la ventana gráfica para preservar el espacio, en lugar de simplemente reducirse.

Recursos adicionales

Escala modular es una gran herramienta para lograr una tipografía receptiva, y Sara Soueidan tiene un excelente artículo sobre técnicas de tipografía receptiva.

Fuente de imagen de la imagen en la portada.

Deja un comentario