CSS: guía de funciones completa de calc ()

CSS tiene una función especial calc()utilizada para realizar cálculos simples. Aquí hay un ejemplo de su uso:

.main-content {
  /*  80px  100vh */
  height: calc(100vh - 80px);
}

Aquícalc() puede experimentar con el código CSS en el que se utiliza . El autor del artículo, cuya traducción publicamos hoy, quiere hablar sobre todo lo que vale la pena saber sobre esta función tan útil.





Función Calc () y valores de propiedad CSS


El único lugar donde puede usar la función calc()es con valores de propiedad CSS. Eche un vistazo a los siguientes ejemplos en los que, utilizando esta función, establecemos los valores de varias propiedades.

.el {
  font-size: calc(3vw + 2px);
  width:     calc(100% - 20px);
  height:    calc(100vh - 20px);
  padding:   calc(1vw + 5px);
}

La función calc()también se puede usar para establecer cualquier parte separada de la propiedad:

.el {
  margin: 10px calc(2vw + 5px);
  border-radius: 15px calc(15px / 3) 4px 2px;
  transition: transform calc(1s - 120ms);
}

¡Esta función puede incluso ser parte de otra función que es responsable de formar parte de cierta propiedad! Por ejemplo, aquí se calc()usa para ajustar la posición del cambio de color del degradado:

.el {
  background: #1E88E5 linear-gradient(
    to bottom,
    #1E88E5,
    #1E88E5 calc(50% - 10px),
    #3949AB calc(50% + 10px),
    #3949AB
  );
}

La función calc () es una herramienta para trabajar con propiedades numéricas.


Tenga en cuenta que en todos los ejemplos anteriores usamos la función calc()cuando trabajamos con propiedades numéricas. También hablaremos sobre algunas características de trabajar con propiedades numéricas (están asociadas con el hecho de que a veces no se requiere el uso de unidades de medida). Ahora notamos que esta función está diseñada para realizar operaciones con números, y no con cadenas o con otra cosa.

.el {
  /* ! */
  counter-reset: calc("My " + "counter");
}
.el::before {
  /* ! */
  content: calc("Candyman " * 3);
}

Hay muchas unidades de medida que se pueden utilizar en el CSS para especificar el tamaño de los elementos y sus partes: px, %, em, rem, in, mm, cm, pt, pc, ex, ch, vh, vw, vmin, vmax. Todas estas unidades se pueden usar con la función calc().

Esta función también puede funcionar con números utilizados sin especificar unidades:

line-height: calc(1.2 * 1.2);

También se puede usar para calcular ángulos:

transform: rotate(calc(10deg * 5));

Esta función también se puede usar en aquellos casos en que no se realizan cálculos en la expresión que se le pasa:

.el {
  /*   ,    */
  width: calc(20px);
}

Calc () no se puede usar en consultas de medios


Aunque esta función está diseñada para establecer valores de propiedad CSS, desafortunadamente no funciona en consultas de medios:

@media (max-width: 40rem) {
  /* 40rem   */
}

/*  ! */
@media (min-width: calc(40rem + 1px)) {
  /* ,  40rem */
}

Si una vez que tales construcciones demuestren ser viables, esto será muy bueno, ya que permitirá crear consultas de medios mutuamente excluyentes que parecen muy lógicas (por ejemplo, las que se muestran arriba).

Usando diferentes unidades en una expresión


La admisibilidad de usar diferentes unidades de medida en una expresión es probablemente la oportunidad más valiosa calc(). Similar se utiliza en casi todos los ejemplos anteriores. Aquí, solo para llamar su atención, otro ejemplo que muestra el uso de diferentes unidades de medida:

/*      */
width: calc(100% - 20px);

Esta expresión dice lo siguiente: "El ancho es igual al ancho del elemento del que se restan 20 píxeles".

En una situación en la que el ancho del elemento puede cambiar, es completamente imposible calcular el valor deseado por adelantado, utilizando solo indicadores expresados ​​en píxeles. En otras palabras, no puede preprocesar el calc()uso de algo como Sass e intentar obtener algo como polyfill. Sí, esto no es necesario, dado que los navegadores son calc()muy compatibles . El punto aquí es que dichos cálculos, en los que se mezclan los valores expresados ​​en diferentes unidades de medida, deben realizarse en el navegador (durante la "ejecución" de la página). A saber, la capacidad de realizar tales cálculos es el valor principal calc().

Aquí hay un par de ejemplos más del uso de valores expresados ​​en diferentes unidades:

transform: rotate(calc(1turn + 45deg));

animation-delay: calc(1s + 15ms);

Probablemente pueda preprocesar estas expresiones, porque mezclan valores cuyas unidades no están relacionadas con nada de lo que se determina mientras la página se ejecuta en el navegador.

Comparación de calc () con cálculos del preprocesador


Acabamos de decir que la característica más útil calc()no es susceptible de preprocesamiento. Pero el preprocesamiento le da al desarrollador algunas características que coinciden con las capacidades calc(). Por ejemplo, cuando usa Sass, también puede calcular valores de propiedad:

$padding: 1rem;

.el[data-padding="extra"] {
  padding: $padding + 2rem; //  3rem;
  margin-bottom: $padding * 2; //  2rem; 
}

Aquí, se pueden hacer cálculos que indican las unidades de medida, aquí puede agregar las cantidades expresadas en las mismas unidades de medida, puede multiplicar ciertos valores por valores cuyas unidades no están indicadas. Pero no es posible realizar cálculos con valores expresados ​​en diferentes unidades de medida. Se imponen restricciones similares a las restricciones en dichos cálculos calc()(por ejemplo, los números por los que se multiplica o divide algo deben ser valores sin unidades).

Revelar el significado de los valores numéricos utilizados en CSS


Incluso si no aprovecha las oportunidades que se pueden lograr solo con ayuda calc(), esta función se puede utilizar para revelar el significado de los valores utilizados en CSS. Suponga que desea que el valor de una propiedad sea exactamente 1/7 del ancho del elemento:

.el {
  /*   , */
  width: calc(100% / 7);

  /*   */
  width: 14.2857142857%;
}

Este enfoque puede ser útil en algo así como una especie de API-CSS con estilo propio:

[data-columns="7"] .col { width: calc(100% / 7); }
[data-columns="6"] .col { width: calc(100% / 6); }
[data-columns="5"] .col { width: calc(100% / 5); }
[data-columns="4"] .col { width: calc(100% / 4); }
[data-columns="3"] .col { width: calc(100% / 3); }
[data-columns="2"] .col { width: calc(100% / 2); }

Operadores matemáticos de la función calc ()


La expresión para ser evaluada con la ayuda de calc()los operadores que se pueden utilizar +, -, *y /. Pero en su aplicación hay algunas características.

Al sumar ( +) y restar ( -), debe usar los valores con las unidades especificadas

.el {
  /*  */
  margin: calc(10px + 10px);

  /*  */
  margin: calc(10px + 5);
}

Tenga en cuenta que el uso de valores incorrectos lleva al hecho de que un anuncio en particular también se vuelve incorrecto.

Al dividir ( /), es necesario que la unidad de medida no se indique en el segundo número

.el {
  /*  */
  margin: calc(30px / 3);

  /*  */
  margin: calc(30px / 10px);

  /*  (   ) */
  margin: calc(30px / 0);
}

Al multiplicar ( *), uno de los números no debe tener una unidad de medida:

.el {
  /*  */
  margin: calc(10px * 3);

  /*  */
  margin: calc(3 * 10px);

  /*  */
  margin: calc(30px * 3px);
}

La importancia de los espacios.


Los espacios utilizados en las expresiones son importantes en las operaciones de suma y resta:

.el {
  /*  */
  font-size: calc(3vw + 2px);

  /*  */
  font-size: calc(3vw+2px);

  /*  */
  font-size: calc(3vw - 2px);

  /*  */
  font-size: calc(3vw-2px);
}

Aquí es bastante posible usar números negativos (por ejemplo, en una construcción como calc(5vw — -5px)), pero este es un ejemplo de una situación en la que los espacios no solo son necesarios, sino también útiles en términos de claridad de expresiones.

Tab Atkins me dijo que la razón por la cual los operadores de suma y resta deben estar separados por espacios es, de hecho, las peculiaridades de las expresiones de análisis. No puedo decir que entendí completamente esto, pero, por ejemplo, el analizador procesa la expresión 2px-3pxcomo un número 2con una unidad de medidapx-3px. Y nadie necesitará una unidad de medida tan extraña. Analizar expresiones con el operador de suma tiene sus propios problemas. Por ejemplo, un analizador puede tomar este operador como parte de la sintaxis utilizada para describir números. Pensé que se necesitaba un espacio para manejar correctamente la sintaxis de las propiedades personalizadas ( --), pero ese no es el caso.

Al multiplicar y dividir espacios alrededor de operadores no se requieren. Pero creo que puede recomendar el uso de espacios con estos operadores para aumentar la legibilidad del código, y para no olvidarse de los espacios y al ingresar expresiones que usan la suma y la resta.

Los espacios que separan los corchetes calc()de una expresión no juegan ningún papel. La expresión, si lo desea, incluso puede seleccionarse moviéndose a una nueva línea:

.el {
  /*  */
  width: calc(
    100%     /   3
  );
}

Es cierto, debes tener cuidado aquí. No calcdebe haber espacios entre el nombre de la función ( ) y el primer paréntesis de apertura:

.el {
  /*  */
  width: calc (100% / 3);
}

Construcciones anidadas: calc (calc ())


Al trabajar con una función calc(), puede usar construcciones anidadas, pero esto no es realmente necesario. Esto es similar a usar corchetes sin calc:

.el {
  width: calc(
    calc(100% / 3)
    -
    calc(1rem * 2)
  );
}

No tiene sentido construir construcciones anidadas a partir de funciones calc(), ya que las mismas pueden reescribirse usando solo corchetes:

.el {
  width: calc(
   (100% / 3)
    -
   (1rem * 2)
  );
}

Además, no se necesitan paréntesis en este ejemplo, ya que las reglas para determinar la prioridad de los operadores se aplican al calcular las expresiones presentadas aquí. La división y la multiplicación se realizan antes de la suma y la resta. Como resultado, el código se puede reescribir así:

.el {
  width: calc(100% / 3 - 1rem * 2);
}

Pero en el caso de que parezca que los corchetes adicionales aclaran el código, pueden usarse. Además, si sin paréntesis, basándose solo en la prioridad de los operadores, la expresión se calculará incorrectamente, entonces dicha expresión necesita paréntesis:

.el {
  /* ,   , */
  width: calc(100% + 2rem / 2);

  /*     ,    */
  width: calc((100% + 2rem) / 2);
}

Propiedades CSS personalizadas y calc ()


Ya aprendimos sobre una de las excelentes características calc(), sobre cálculos que usan valores con diferentes unidades. Otra característica interesante de esta función es cómo se puede aplicar con propiedades CSS personalizadas. A las propiedades personalizadas se les pueden asignar valores que se pueden usar en los cálculos:

html {
  --spacing: 10px;
}

.module {
  padding: calc(var(--spacing) * 2);
}

Estoy seguro de que es fácil imaginar un conjunto de estilos CSS en el que se realizan muchas configuraciones en un solo lugar estableciendo valores para propiedades CSS personalizadas. Estos valores se utilizarán en todo el código CSS.

Las propiedades personalizadas, además, pueden referirse entre sí (tenga en cuenta que no se calc()usa aquí). Los valores obtenidos se pueden usar para establecer los valores de otras propiedades CSS (pero aquí no se puede calc()prescindir).

html {
  --spacing: 10px;
  --spacing-L: var(--spacing) * 2;
  --spacing-XL: var(--spacing) * 3;
}

.module[data-spacing="XL"] {
  padding: calc(var(--spacing-XL));
}

Para algunos esto puede no parecer muy conveniente, ya que al acceder a una propiedad personalizada, debe recordar calc(). Pero esto me parece interesante en términos de legibilidad de código.

La fuente de las propiedades personalizadas puede ser el código HTML. A veces esto puede ser extremadamente útil. Por ejemplo, en Splitting.js se agregan índices a palabras y símbolos.

<div style="--index: 1;"> ... </div>
<div style="--index: 2;"> ... </div>
<div style="--index: 3;"> ... </div>
div {
  /*     HTML (   ) */
  animation-delay: calc(var(--index, 1) * 0.2s);
}

Asignación de unidades a propiedades personalizadas después de declarar estas propiedades


Supongamos que estamos en una situación en la que tiene sentido escribir un número sin unidades de medida en una propiedad personalizada, o en una situación en la que dicho número sea conveniente, antes del uso real, de alguna manera convierta sin usar unidades. En tales casos, se puede asignar un valor a una propiedad personalizada sin especificar unidades. Cuando sea necesario convertir este número en uno nuevo, expresado en ciertas unidades de medida, se puede multiplicar 1indicando las unidades de medida deseadas:

html {
  --importantNumber: 2;
}

.el {
  /*    ,  ,        */
  padding: calc(var(--importantNumber) * 1rem);
}

Trabajar con flores


Cuando se describen colores usando formatos como RGB y HSL, se usan números. Estos números pueden ser trabajados calc(). Por ejemplo, puede establecer algunos valores básicos de HSL y luego cambiarlos según sea necesario ( aquí hay un ejemplo):

html {
  --H: 100;
  --S: 100%;
  --L: 50%;
}

.el {
  background: hsl(
    calc(var(--H) + 20),
    calc(var(--S) - 10%),
    calc(var(--L) + 30%)
  )
}

No puede combinar calc () y attr ()


La función CSS attr()puede parecer bastante atractiva. Y la verdad: tomas el valor del atributo de HTML y luego lo usas. Pero…

<div data-color="red">...</div>
div {
  /*    */
  color: attr(data-color);
}

Desafortunadamente, esta función no comprende los "tipos" de valores. Como resultado, attr()es adecuado solo para trabajar con cadenas y para configurar las propiedades CSS que lo utilizan content. Es decir, tal diseño resulta bastante funcional:

div::before {
  content: attr(data-color);
}

Dije esto aquí porque alguien podría intentar extraer un attr()cierto número del código HTML y usarlo en los cálculos:

<div class="grid" data-columns="7" data-gap="2">...</div>
.grid {
  display: grid;

  /*         */
  grid-template-columns: repeat(attr(data-columns), 1fr);
  grid-gap: calc(1rem * attr(data-gap));
}

Sin embargo, lo bueno es que realmente no importa, ya que las propiedades personalizadas en HTML son excelentes para resolver estos problemas:

<div class="grid" style="--columns: 7; --gap: 2rem;">...</div>
.grid {
  display: grid;

  /* ! */
  grid-template-columns: repeat(var(--columns), 1fr);
  grid-gap: calc(var(--gap));
}

Herramientas del navegador


Las herramientas de desarrollo del navegador generalmente muestran expresiones con lo calc()mismo que se describe en el código fuente CSS.


Herramientas para desarrolladores de Firefox, pestaña Reglas

Si necesita averiguar qué calculará la funcióncalc(), puede consultar la pestañaComputed(esta pestaña se puede encontrar en las herramientas para desarrolladores de todos los navegadores que conozco). Allí, se mostrará el valor calculadocalc().


Pestaña calculada de Chrome Developer Tools

Soporte del navegador


Aquí puede obtener información sobre la compatibilidad del calc()navegador para la función . Si hablamos de navegadores modernos, el nivel de soporte calc()es más del 97%. Si necesita admitir navegadores bastante antiguos (como IE 8 o Firefox 3.6), generalmente lo hacen: agregue calc()la misma propiedad antes de la propiedad para calcular el valor que se establece en un formato que entienden los navegadores antiguos:

.el {
  width: 92%; /*   */
  width: calc(100% - 2rem);
}

La función calc()tiene muchos problemas conocidos, pero solo los navegadores antiguos los padecen. En Caniuse puede encontrar una descripción de 13 de estos problemas. Éstos son algunos de ellos:

  • El navegador Firefox debajo de la versión 59 no es compatible con calc()las funciones utilizadas para configurar el color. Por ejemplo: color: hsl(calc(60 * 2), 100%, 50%).
  • IE 9-11 no representará la sombra especificada por la propiedad box-shadowsi se usa para determinar cualquiera de los valores calc().
  • Ni IE 9-11 ni Edge admiten el diseño de vistas width: calc()cuando se aplican a las celdas de la tabla.

Ejemplos de vida


Pregunté a varios desarrolladores de CSS sobre cuándo utilizaron la función por última vez calc(). Sus respuestas fueron una pequeña selección que ayudará a todos a aprender sobre cómo otros programadores usan calc()en su trabajo diario.

  • He utilizado calc()para crear la clase de ayuda para los campos de la gestión: .full-bleed { width: 100vw; margin-left: calc(50% — 50vw); }. Puedo decir que calc()está en mis 3 funciones CSS más útiles.
  • Usé esta función para asignar espacio para un "pie de página" fijo de la página.
  • calc() . , font-size, . font-sizecalc() line-height. ( , calc() , , , rem em. , ).
  • , . . — : .margin { width: calc( (100vw — var(--content-width)) / 2); }.
  • calc() - , . : .drop-cap { --drop-cap-lines: 3; font-size: calc(1em * var(--drop-cap-lines) * var(--body-line-height)); }.
  • , .
  • , padding vw/vh.
  • Solicito calc()evadir restricciones background-position. Esto es especialmente cierto para las restricciones en el ajuste de las posiciones de cambio de color en gradientes. Por ejemplo, esto se puede describir de la siguiente manera: "posicionar la posición del cambio de color, sin llegar 0.75emal fondo".



¡Queridos lectores! ¿Usas CSS calc()?

All Articles