CSS-анимация границ

Рассмотрим несколько способов анимации границы в CSS.

Установка границ

Существует несколько методов установки границы элемента: border , outline и box-shadow . Как подробно описано в книге Стефани Эклс «3 метода CSS для добавления границ элементов» , каждый подход имеет свои преимущества и недостатки, особенно когда дело касается анимации границ. Основная причина не использовать правильную border CSS — для целей анимации.

Анимация границ с использованием outline-offset Кевина Дж. Пауэлла

Недавно мое внимание привлекла статья «Фантастическая CSS-анимация границ» , в которой автор Коко исследовал дополнительные возможности. Вставляя сгенерированный контент с помощью ::before и ::after они создают искусственную рамку, которая затем анимируется.

Что меня больше всего привлекает, так это вспомогательные анимированные визуализации, использованные в статье. Они действительно помогают объяснить, что именно делается для достижения желаемого эффекта.

Пограничная анимация с использованием сгенерированного контента Coco

И белый слой, и цветные линии представляют собой генерируемый контент. При появлении и исчезновении белого слоя становится ясно, как они складываются и как работает анимация.

Сохранение блочной модели

Недостаток использования сгенерированного контента для имитации границы заключается в том, что в итоге вы получаете сломанную блочную модель : контент теперь может скрывать искусственную рамку, потому что указанная «граница» нарисована под ней. Чтобы смягчить это, вам нужно применить желаемую border-width в качестве padding .

Чтобы получить настоящую границу и, таким образом, сохранить работу блочной модели, вы можете использовать несколько фонов , которые затем растягиваете в область границы.

Основы

Давайте начнем с создания пунктирной границы и добавления нескольких фонов.

/* Size of the border */
--border-size: 0.5rem;

/* Create a dotted border */
border: var(--border-size) dotted lime;

/* Create two background layers:
   1. A white semi-transparent
   2. A layer with the colored boxes
 */
background-image:
  linear-gradient(to right, rgb(255 255 255 / 0.5), rgb(255 255 255 / 0.5)),

  conic-gradient(
    from 45deg,
    #d53e33 0deg 90deg,
    #fbb300 90deg 180deg,
    #377af5 180deg 270deg,
    #399953 270deg 360deg
  )
;

Изменение размера фона с помощью background-origin

Как видите, с фонами здесь происходит что-то забавное: они закрашены в рамку, но conic-gradient кажется неправильным. На самом деле это предполагаемое поведение: по умолчанию фоновые изображения не рисуются в границе, поскольку их источником является padding-box элемента. В конце концов, чтобы создать рамку, заданные фоновые изображения повторяются в самой рамке, создавая странный визуальный эффект.

Чтобы решить эту проблему, вам нужно растянуть фон так, чтобы он занимал размер границы. Вы можете сделать это вручную, растянув и изменив положение фона, но лучше всего использовать свойство background-origin для определения размера фона относительно border-box .

Поддержка браузера

  • Хром: 1.
  • Край: 12.
  • Фаерфокс: 4.
  • Сафари: 3.

Источник

Не
/* Manually add or offset the size of the border where needed */
background-position: calc(var(--border-size) * -1) calc(var(--border-size) * -1);
background-size: calc(var(--border-size) * 2 + 100%) calc(var(--border-size) * 2 + 100%);
Делать
background-origin: border-box;

Это одно дополнение делает все намного лучше:

Уменьшение белого фонового слоя с помощью background-clip

Теперь, когда фон занимает все пространство, полупрозрачный слой необходимо снова уменьшить. Вместо того, чтобы снова возиться с background-size , есть более простой способ сделать это: использовать background-clip и установить его в padding-box . Таким образом, фон больше не отображается под областью границы.

Поддержка браузера

  • Хром: 1.
  • Край: 12.
  • Фаерфокс: 4.
  • Сафари: 5.

Источник

background-clip:
  padding-box, /* Clip white semi-transparent to the padding-box */
  border-box /* Clip colored boxes to the border-box (default) */
;

Наконец, сделайте границу transparent чтобы добиться полного эффекта.

border: 0.3rem dotted transparent;

Анимация

Чтобы восстановить анимацию границы, вы можете манипулировать начальным углом conic-gradient .

--angle: 0deg;
conic-gradient(
  from var(--angle),
  #d53e33 0deg 90deg,
  #fbb300 90deg 180deg,
  #377af5 180deg 270deg,
  #399953 270deg 360deg
);

Благодаря @property это становится проще простого в браузерах, которые его поддерживают:

Поддержка браузера

  • Хром: 85.
  • Край: 85.
  • Фаерфокс: 128.
  • Сафари: 16.4.

Источник

@property --angle {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}

@keyframes rotate {
  to {
    --angle: 360deg;
  }
}

В совокупности код становится таким:

Бонусный контент: border-image

Ранее описанный подход к рисованию градиентной границы — использование CSS border-image .

Поддержка браузера

  • Хром: 16.
  • Край: 12.
  • Фаерфокс: 15.
  • Сафари: 6.

Источник

Это позволяет упростить код, поскольку вам не нужно иметь дело с перекрывающимся фоном. Анимацию можно применять так же, как и раньше.

/* Create a border */
border: 0.5rem solid transparent;

/* Paint an image in the border */
border-image:
  conic-gradient(
    from var(--angle),
    #d53e33 0deg 90deg,
    #fbb300 90deg 180deg,
    #377af5 180deg 270deg,
    #399953 270deg 360deg
  ) 1
;

Однако вы заметите, что при таком подходе некоторые вещи больше не работают:

  • border-image не соответствует border-radius ; он всегда останется прямоугольным.
  • При настройке border-image-slice для заполнения border-image рисуется не под установленным background , а сверху. Это может быть проблематично, если вы хотите, чтобы фон был полупрозрачным.

В заключение

В CSS существует множество возможностей для анимации границ. В зависимости от варианта использования вы можете использовать тот или иной вариант.