Как сделать составную границу блока: solid и dashed
При создании пошаговых интерфейсов часто требуется визуально отображать прогресс с помощью границы блока. Например, часть рамки должна быть сплошной (solid), а остальная - пунктирной (dashed). Стандартное свойство border не позволяет комбинировать разные стили в одной линии. Однако эту задачу можно решить с помощью CSS-градиентов и псевдоэлементов. Рассмотрим рабочий способ.
Проблема комбинирования стилей границы
Свойство border-style принимает только одно значение для каждой стороны. Нельзя напрямую указать, что левая половина верхней границы - solid, а правая - dashed. Это ограничение обходят с помощью наложения слоёв: один элемент отвечает за сплошную часть, другой - за пунктирную.
Решение: CSS-градиент + маска
Используем background-image с линейным градиентом и свойство mask для создания составной рамки. Алгоритм:
- Создаём сплошную границу через
border: solidна самом блоке. - Накладываем пунктирную границу через псевдоэлемент
::afterили::beforeсborder-style: dashed. - Обрезаем пунктирную часть с помощью
mask-imageс градиентом, который скрывает её в области, где уже есть solid.
Пример кода
.progress-border {
position: relative;
width: 300px;
height: 200px;
border: 4px solid #3498db; /* сплошная граница по умолчанию */
}
.progress-border::after {
content: '';
position: absolute;
top: -4px; left: -4px;
width: 100%; height: 100%;
border: 4px dashed #3498db; /* пунктирная граница */
pointer-events: none;
mask-image: linear-gradient(to right, transparent 50%, black 50%);
mask-size: 100% 100%;
-webkit-mask-image: linear-gradient(to right, transparent 50%, black 50%);
}В этом примере пунктирная граница видна только на правой половине блока (начиная с 50% ширины). Меняя процент в градиенте, вы управляете точкой перехода от solid к dashed.
Динамическое заполнение в зависимости от шага
Чтобы обновлять границу при изменении шага, используйте JavaScript для изменения значения в маске. Например, сохраняйте процент прогресса в CSS-переменной --progress и обновляйте её:
.progress-border::after {
mask-image: linear-gradient(to right, transparent var(--progress), black var(--progress));
-webkit-mask-image: linear-gradient(to right, transparent var(--progress), black var(--progress));
}Теперь вы можете задавать --progress: 30% для отображения 30% сплошной границы и 70% пунктирной.
Альтернативный подход: два вложенных блока
Если нужно поддерживать более старые браузеры без mask, используйте вложенные элементы:
- Внешний блок имеет пунктирную границу.
- Внутренний блок - сплошную, ширина которого равна проценту прогресса.
- Внутренний блок перекрывает часть пунктира, создавая иллюзию составной границы.
Этот метод проще, но требует дополнительной разметки.
Заключение
Составная граница из solid и dashed реализуется с помощью CSS-масок или наложения блоков. Выберите способ в зависимости от требуемой поддержки браузеров. Для современных проектов используйте mask-image - он гибкий и не загромождает HTML.