Рассчитать с учетом встроенных размеров

Веб-функции: calc-size() interpolate-size

calc-size() – это функция CSS для выполнения математических операций с ключевыми словами, определяющими внутренний размер, такими как auto, min-content и fit-content. ОБЯЗАТЕЛЬНО. Используйте calc-size(), только если вам нужно изменить внутренний размер с помощью вычисления или ограничения. Для простых анимаций на основе ключевых слов (например, от 0 до auto) необходимо использовать interpolate-size: allow-keywords.

Руководство по настройке

  1. Определите внутреннюю основу. Выберите, какое внутреннее ключевое слово (auto, min-content и т. д.) должно лечь в основу расчета.
  2. Определите ограничения. Используйте математические функции CSS, такие как clamp(), min() или max(), во втором аргументе, чтобы применить ограничения дизайна к внутреннему размеру.
  3. ОБЯЗАТЕЛЬНО. Укажите резервный вариант. Всегда указывайте стандартное ключевое слово или длину размера непосредственно перед свойством, используя calc-size(), чтобы макет оставался функциональным в неподдерживаемых браузерах.
  4. Используйте логические свойства. По умолчанию используйте логические свойства, такие как inline-size или block-size, чтобы расчеты соответствовали режиму записи документа.
  5. Необязательно. Прогрессивное улучшение. Поместите сложную логику макета или анимации в блок @supports (inline-size: calc-size(auto, size + 0px)), чтобы продвинутые функции были доступны только в поддерживающих их браузерах.

Базовый синтаксис

/* calc-size(<calc-size-basis>, <calc-sum>) — mathematical operations on intrinsic sizing keywords */
.element {
  /* MANDATORY: Always provide a fallback for browsers that do not support calc-size() */
  inline-size: min-content;
  
  /* DO: Use calc-size to modify an intrinsic basis with a calculation or function */
  inline-size: calc-size(min-content, size + 2rem);
}

Допустимые аргументы для способа исчисления (<calc-size-basis>)

Первый аргумент определяет базовый размер для расчета.

Стандартные ключевые слова

  • auto – размер элемента по умолчанию.
  • min-content – наименьший размер, который может иметь элемент без переполнения.
  • max-content: размер, который элемент занимает, чтобы весь контент поместился в одну строку.
  • fit-content – эквивалент clamp(min-content, auto, max-content).
  • content – допустимо только в том случае, если calc-size() используется в свойстве flex-basis.

Специальные аргументы

  • any – общий тип, который используется, когда конкретный внутренний тип неизвестен или при вложенных вычислениях.
  • Вложенные функции calc-size(). Позволяют выполнять многоэтапные или условные вычисления.
  • <calc-sum>: определенная длина, процент или математическое выражение (например, 100px или 20%). Если в качестве основы используется фиксированное значение, ключевое слово size по-прежнему доступно (но только во втором аргументе) и представляет собой разрешенное значение этой основы.

ОБЯЗАТЕЛЬНО. Ключевое слово size недопустимо в первом аргументе (<calc-size-basis>). Это локальная переменная, которая существует только для того, чтобы ссылаться на основу из второго аргумента (<calc-sum>).

Допустимые аргументы для вычислений (<calc-sum>)

Второй аргумент – математическое выражение.

  • Обычно в нем используется ключевое слово size, которое ссылается на значение основы.
  • Хотя ключевое слово size технически необязательно, его отсутствие означает, что вычисление будет разрешено до фиксированного значения, полностью игнорируя основу.
  • Она может включать стандартные математические операторы (+, -, *, /).
  • Оно может включать математические функции CSS, такие как clamp(), min(), max() и round().
  • ОБЯЗАТЕЛЬНО. В каждом вычислении calc-size() допускает только одно значение собственного размера (базовое). Нельзя использовать разные ключевые слова для внутренних размеров в одном вызове calc-size().

Примеры использования

Анимация для встроенных размеров

По умолчанию браузеры не могут интерполировать длину (например, 0px) и ключевое слово (например, auto). Если заключить ключевое слово в calc-size(), оно станет интерполируемым значением.

Выбор подходящего инструмента для анимации

  • ОБЯЗАТЕЛЬНО. Используйте interpolate-size: allow-keywords для простых анимаций, в которых размеры меняются на внутренние (например, height: 0 на height: auto) без математических изменений. Это обязательный подход для простой интерполяции ключевых слов, который в идеале должен применяться глобально через :root.

    :root {
      /* Best practice: Enable keyword interpolation globally */
      interpolate-size: allow-keywords;
    }
    
    .item {
      height: 0;
      transition: height 0.3s ease;
    }
    
    .item.open {
      /* Simple interpolation from 0 to auto now works without calc-size() */
      height: auto;
    }
    
  • Используйте calc-size(), ТОЛЬКО если вам нужно выполнить математические вычисления для внутреннего размера во время перехода (например, добавить отступы или зафиксировать размер).

.accordion-content {
  display: block;
  overflow: hidden;
  /* MANDATORY: Fallback value for closed state */
  block-size: 0;
  transition: block-size 0.3s ease-out;
}

.accordion-content.open {
  /* MANDATORY: Fallback value for open state */
  block-size: auto;

  /* 
    DO: Use calc-size(auto, ...) to enable animation from 0 to the element's 
    intrinsic size while doing a calculation (in this case, adding a space of 2rem).
  */
  block-size: calc-size(auto, size + 2rem);
}

ОБЯЗАТЕЛЬНО. Прямая интерполяция между двумя ключевыми словами, определяющими внутренний размер, невозможна. Один из концов перехода должен быть длиной или процентом.

Учет предпочтений пользователя в отношении анимации

Анимации, которые изменяют размер больших областей макета, могут быть особенно разрушительными для пользователей с вестибулярными расстройствами. ОБЯЗАТЕЛЬНО. Всегда учитывайте настройки движения, заданные пользователем. Для этого используйте медиазапрос prefers-reduced-motion, который позволяет упростить или минимизировать необязательные анимации. Распространенные стратегии включают полное отключение движения, сокращение продолжительности или замену сдвигов макета едва заметными переходами непрозрачности.

.accordion-content {
  opacity: 0;
  transition: block-size 0.3s ease, opacity 0.3s ease;
}

.accordion-content.open {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .accordion-content {
    /* 
       EXAMPLE: Replacing disruptive layout animations with a subtle fade-in.
       Setting the block-size instantly and transitioning opacity 
       provides a clear state change without large-scale motion.
    */
    transition: opacity 1.5s ease;
  }

  .accordion-content.open {
    /* Jump the size instantly */
    block-size: auto;
  }
}

Применение ограничений к внутренним размерам

Вы можете использовать calc-size() с любой математической функцией CSS, например min(), max(), clamp() или round(), чтобы внутренний размер элемента не выходил за границы дизайна.

.dynamic-container {
  /* MANDATORY: Always provide a fallback for browsers that do not support calc-size() */
  inline-size: fit-content;

  /* 
    DO: Establish a dynamic size based on content, while:
    1. Enforcing boundaries using CSS math functions (min, clamp, etc.)
    2. Modifying the intrinsic size with fixed or relative offsets
  */
  inline-size: calc-size(fit-content, min(size + var(--extra-space), var(--max-allowed)));
}

Важные соображения

  • Проблемы с процентами. Проценты внутри <calc-sum> рассчитываются относительно размера контейнера, а не ключевого слова size. Например, calc-size(auto, size + 10%) добавляет 10% ширины родительского элемента к ширине auto элемента, что может привести к неожиданным результатам или переполнению.
  • Требование к вычислениям. ОБЯЗАТЕЛЬНО. Для простых анимаций (например, 0 до auto) используйте interpolate-size: allow-keywords вместо calc-size(). calc-size() следует использовать только в том случае, если макет требует динамических математических корректировок внутренней базы.
  • Примечание о производительности. Анимация свойств блочной модели, таких как inline-size или block-size, запускает перерасчет макета, что может быть ресурсоемким. Используйте анимацию calc-size() в основном для элементов, критически важных для макета, когда альтернативы, не связанные с макетом, недостаточны.

Резервные стратегии

calc-size() и interpolate-size – это прогрессивные улучшения. В браузерах, которые их не поддерживают, свойства будут игнорироваться, а макет останется функциональным, хотя анимация внутренних ключевых слов будет прыгать, а не переходить. Всегда указывайте стандартное ключевое слово или длину в качестве резервного варианта.

.element {
  /* Fallback for browsers that don't support calc-size() */
  inline-size: fit-content; 
  /* Modern browsers will override the fallback */
  inline-size: calc-size(fit-content, size + 2rem);
}

Резервные анимации и переходы

В браузерах без поддержки calc-size() или interpolate-size переходы, включающие ключевые слова внутреннего размера, не будут интерполироваться.

  • Постепенное сокращение. По умолчанию резервным вариантом является мгновенный переход между состояниями (например, от 0 к auto). Часто это приемлемо, поскольку макет остается функциональным.
  • Улучшенное взаимодействие. Используйте @supports, чтобы применять сложную логику макета или дополнительное оформление, которое имеет смысл только при наличии плавной встроенной анимации.
  • Избегайте измерений на основе JS. Хотя вы можете использовать JavaScript для измерения элементов и вручную анимировать их размеры, часто в этом нет необходимости, и это может привести к сбою макета. Для современных веб-приложений рекомендуется использовать встроенный мгновенный переход.

В случае с анимацией резервным вариантом будет мгновенный переход к конечному размеру. Чтобы определить поддержку в CSS или JavaScript:

/* CSS Feature Detection */
@supports (inline-size: calc-size(auto, size + 0px)) {
  .element {
    /* Apply advanced logic only when supported */
  }
}
/* JavaScript Feature Detection */
if (CSS.supports('inline-size', 'calc-size(auto, size + 0px)')) {
  // Apply advanced sizing or animations
}