Кастомная пунктирная граница в CSS: SVG и градиенты
Как сделать кастомную пунктирную границу в CSS: толщина 12px, длина штриха 90px и удлинённые штрихи в углах. Варианты: SVG, border-image и CSS-градиенты.
Как создать кастомную пунктирную границу для блока в CSS?
Мне нужно реализовать блок с пунктирной обводкой, где:
- Ширина штриха составляет 12 пикселей
- Длина штриха равна 90 пикселям
- В углах блока должен быть более длинный штрих, плавно переходящий с верхней границы на боковую
Какие CSS-свойства и техники можно использовать для создания такой кастомной пунктирной обводки?
Самый надёжный способ получить точную, pixel‑perfect пунктирную обводку — использовать SVG (как background-image или border-image), где можно задать stroke-width: 12px и stroke-dasharray: 90, <gap>, а плавный длинный штрих в углах сделать отдельными SVG‑траекториями или накладываемыми элементами. Если нужна чисто CSS‑реализация — можно использовать несколько linear-gradient/repeating-* на псевдоэлементе и дополнительный оверлей для углов; border-image с SVG даёт гибридный вариант (border image css) между точностью и простотой. Ниже — проверенные шаблоны и пояснения, как настроить длину штриха, толщину и поведение в углах.
Содержание
- Коротко о вариантах
- SVG как background / точный контроль штриха и углов
- Чистый CSS: градиенты + псевдоэлементы (responsive, без файлов)
- border-image css: использовать SVG как border-image (срезы и углы)
- Практические замечания: адаптивность, retina, совместимость
- Источники
- Заключение
CSS кастомная пунктирная граница: обзор методов
Коротко — какие варианты есть и за что они отвечают:
- SVG (inline / data-URL) — максимально гибкий: задаёте
stroke-width:12px,stroke-dasharray:90, <gap>и рисуете отдельные paths для длинных штрихов в углах. Лучший выбор для pixel‑perfect и сложных углов. Пример идеи — генератор и трюки с SVG: https://kovart.github.io/dashed-border-generator/ - Чистый CSS (несколько градиентов на ::before/::after) — удобно и без ресурсов; точно контролирует длину штриха в px, хорошо для адаптивных блоков; углы делаете оверлеями (диагональные градиенты или маленькие SVG в фоне). Смотреть подходы с repeating-conic-gradient/масками: https://css-tip.com/css-dashed-border/
- border-image с SVG — гибрид: даёт контроль и использует стандартный border-API (
border-image-slice,border-image-repeat) — удобно, если хотите, чтобы браузер «рисовал» рамку как border. Документация: https://developer.mozilla.org/ru/docs/Web/CSS/border-image
Дальше — рабочие примеры для ваших требований: толщина штриха 12px, длина штриха 90px, в углах — длинный плавный штрих.
SVG как border-image — точный контроль штриха и углов
Когда нужна точность (12px, 90px) — лучше делать SVG, где вы контролируете каждую траекторию. Ниже — пример для фиксированного блока (проще для точных пикселей). Идея: основной прямоугольник рисуем с stroke-dasharray="90 30", а в местах углов накладываем отдельные paths — длинные штрихи, идущие из верхней границы на боковую.
HTML
<div class="card svg-border">Контент</div>
CSS (пример для блока 400×200px)
.card {
width: 400px;
height: 200px;
padding: 20px;
background: #fff;
box-sizing: border-box;
}
/* SVG в background: stroke-width = 12, dash = 90px, gap = 30px */
.svg-border {
background-image: url("data:image/svg+xml;utf8,\
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 200' preserveAspectRatio='none'>\
<rect x='6' y='6' width='388' height='188' fill='none' \
stroke='%23333' stroke-width='12' stroke-linecap='butt' stroke-linejoin='round' stroke-dasharray='90 30' vector-effect='non-scaling-stroke'/>\
<!-- corner overlays: каждый path — единый штрих, проходящий через угол -->\
<path d='M360 6 L394 6 L394 54' fill='none' stroke='%23333' stroke-width='12' stroke-linecap='round' stroke-linejoin='round' stroke-dasharray='120 999' vector-effect='non-scaling-stroke'/>\
<path d='M6 6 L44 6 L6 44' fill='none' stroke='%23333' stroke-width='12' stroke-linecap='round' stroke-linejoin='round' stroke-dasharray='120 999' vector-effect='non-scaling-stroke'/>\
<path d='M360 194 L394 194 L394 146' fill='none' stroke='%23333' stroke-width='12' stroke-linecap='round' stroke-linejoin='round' stroke-dasharray='120 999' vector-effect='non-scaling-stroke'/>\
<path d='M6 194 L44 194 L6 146' fill='none' stroke='%23333' stroke-width='12' stroke-linecap='round' stroke-linejoin='round' stroke-dasharray='120 999' vector-effect='non-scaling-stroke'/>\
</svg>");
background-repeat: no-repeat;
background-size: 100% 100%;
}
Пояснения и советы:
- В data URI цвета
#закодированы как%23(см.%23333). Это нужно для корректной вставки в CSS. stroke-dasharray="90 30"— задаёт длину штриха 90px и промежуток 30px (подставьте желаемый gap).- Для длинного штриха в углу я добавил отдельные
<path>с большой первой частью dasharray (120 999), чтобы этот путь отрисовывался как единый длинный штрих, проходящий через угол. Такой трюк даёт плавный переход с верхней границы на боковую. - Если блок не фиксированного размера, используйте один из вариантов: генерировать SVG динамически с JS под размеры элемента, либо применять
viewBoxв тех же пикселях, что и размер блока, либо принимать небольшую погрешность. vector-effect="non-scaling-stroke"позволяет сохранять толщину штриха (12px) при масштабировании SVG; без него при растяжении stroke тоже масштабируется.
Плюсы SVG: абсолютный контроль за stroke-width, stroke-dasharray, stroke-linecap, stroke-linejoin. Минусы: чуть больше работы при адаптивной верстке (или требуется генерировать SVG в зависимости от размеров).
См. практику с SVG и dash-параметрами: https://kovart.github.io/dashed-border-generator/ и базовую теорию border-image/SVG: https://developer.mozilla.org/ru/docs/Web/CSS/border-image
Чистый CSS: градиенты + псевдоэлементы (responsive, без файлов)
Если вы хотите обойтись без SVG/файлов — используйте псевдоэлемент с четырьмя линейными градиентами для сторон (точный контроль длины штриха в px) и дополнительным оверлеем для вырезания центра. Для длинного штриха в углах добавьте четыре небольших диагональных градиента, позиционированных в углах.
HTML
<div class="box css-dashed">Контент</div>
CSS
.box {
position: relative;
background: #fff;
padding: 20px;
box-sizing: border-box;
}
/* ::before — рисует даши по всем сторонам + corner overlays */
.box::before{
content: "";
position: absolute;
inset: 0;
pointer-events: none;
/* параметры */
--thick: 12px; /* толщина штриха */
--dash: 90px; /* длина штриха */
--gap: 30px; /* промежуток */
/* 4 стороны (top, right, bottom, left) */
background:
linear-gradient(90deg, #333 0 calc(var(--dash)), transparent calc(var(--dash)) calc(var(--dash) + var(--gap))) top/100% var(--thick) repeat-x,
linear-gradient(0deg, #333 0 calc(var(--dash)), transparent calc(var(--dash)) calc(var(--dash) + var(--gap))) right/var(--thick) 100% repeat-y,
linear-gradient(270deg,#333 0 calc(var(--dash)), transparent calc(var(--dash)) calc(var(--dash) + var(--gap))) bottom/100% var(--thick) repeat-x,
linear-gradient(180deg,#333 0 calc(var(--dash)), transparent calc(var(--dash)) calc(var(--dash) + var(--gap))) left/var(--thick) 100% repeat-y,
/* corner overlays: диагональные полосы, длину можно подгонять (здесь 140px) */
linear-gradient(135deg, #333 0 140px, transparent 140px) top left/140px 140px no-repeat,
linear-gradient(45deg, #333 0 140px, transparent 140px) top right/140px 140px no-repeat,
linear-gradient(225deg, #333 0 140px, transparent 140px) bottom right/140px 140px no-repeat,
linear-gradient(315deg, #333 0 140px, transparent 140px) bottom left/140px 140px no-repeat;
background-repeat: repeat;
}
/* ::after — «маска» (вырезает центр, оставляя только рамку толщиной --thick) */
.box::after{
content: "";
position: absolute;
top: var(--thick);
left: var(--thick);
right: var(--thick);
bottom: var(--thick);
background: #fff; /* тот же цвет, что и у блока (или transparent, если нужно) */
pointer-events: none;
}
Пояснения:
- Длина штриха
--dashи толщина--thickзаданы в пикселях — вы получаете точные 12px и 90px. ::beforeрисует все стороны с повторяющимися градиентами;::afterзакрывает внутреннюю область, оставляя только «рамку» заданной толщины.- Для длинного штриха в углах я добавил диагональные градиенты, размер и угол которых можно подогнать (значение 140px — ориентир). Это даёт плавный визуальный переход сверху на боковую грань.
- Подстройка: при скруглённых углах (
border-radius) диагональные накладки нужно корректировать (или заменить SVG).
Плюсы: полностью на CSS, responsive, легко менять --dash/--thick. Минусы: сложнее добиться абсолютно ровной векторной кривизны в углах — для идеального результата лучше SVG.
Более продвинутые CSS‑подходы используют repeating-conic-gradient + маски, см. практику: https://css-tip.com/css-dashed-border/
border-image css: использовать SVG как border-image (срезы и углы)
Если хотите, чтобы рамка обрабатывалась браузером как border, используйте border-image с SVG. Идея: подготовить маленький SVG-шаблон (3×3 срезы), где центральные части повторяются вдоль сторон, а уголовые срезы содержат «удлинённые» штрихи.
Пример (упрощённый):
.box {
border: 12px solid transparent; /* ширина рамки = толщина штриха */
border-image-source: url("data:image/svg+xml;utf8,\
<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120' viewBox='0 0 120 120'>\
<!-- в центре стороны делаем повторяющуюся полосу с dash 90 -->
<g fill='none' stroke='%23333' stroke-width='12' stroke-linecap='butt'>\
<line x1='0' y1='6' x2='120' y2='6' stroke-dasharray='90 30'/>\
<line x1='6' y1='0' x2='6' y2='120' stroke-dasharray='90 30'/>\
</g>\
<!-- в углах — нарисовать большие штрихи в срезах -->\
</svg>");
border-image-slice: 12; /* отступ для срезов = толщина */
border-image-repeat: round; /* repeat / round / stretch по вкусу */
border-image-width: 12;
}
Плюсы:
- Рамка ведёт себя как
border(вёрстка, box-model), вы легко задаётеborder-radiusи т. п. - Corner‑tiles (угловые куски) позволяют держать «длинный» штрих именно в углу.
Минусы:
- Нужно подготовить корректный SVG‑тайл и правильно установить
border-image-sliceтак, чтобы углы не искажались. - Нюансы при масштабировании; иногда удобнее использовать
border-image-repeat: roundилиspace.
Документация и разъяснения по свойствам: https://developer.mozilla.org/ru/docs/Web/CSS/border-image
Практические замечания: адаптивность, pixel‑perfect, производительность
- Pixel‑perfect (точно 90px): проще при фиксированных размерах блока или при генерации SVG под размеры (через JS). В адаптивных макетах либо допускайте относительную длину, либо пересчитывайте dash в runtime.
- Retina / масштабирование: SVG (вектор) масштабируется чётко; если вы хотите фиксированную толщину в px при масштабировании, используйте
vector-effect="non-scaling-stroke". - Corner smoothing: для «плавного» перехода штриха на угол удобнее рисовать отдельный path в SVG, который идёт через угол — так вы гарантируете один непрерывный штрих. В чистом CSS чаще делают диагональные/угловые оверлеи.
- Поддержка браузеров: все современные браузеры понимают градиенты и inline SVG в data-URI; но свойства маски/композитинга (
mask-composite) имеют особенности в поддержке (-webkit- префиксы). Всегда делайте fallback:border: 12px dashed #333;. - Производительность: inline SVG в background хорошо кешируется, но большие или генерируемые SVG лучше хранить отдельно. Чистый CSS — без сетевых запросов, но с большим количеством градиентов может чуть «нагружать» рендер для сложных страниц.
- Доступность: рамка остаётся декоративной; если вы используете цвет для состояния (focus) — дополнительно добавьте видимый фокус для клавиатуры (outline или box-shadow), чтобы не полагаться только на цвет.
Источники
- https://kovart.github.io/dashed-border-generator/
- https://css-tip.com/css-dashed-border/
- https://stackoverflow.com/questions/2771171/control-the-dashed-border-stroke-length-and-distance-between-strokes
- https://www.w3schools.com/css/css_border.asp
- https://developer.mozilla.org/ru/docs/Web/CSS/border-image
- https://smarative.com/blog/how-to-change-spacing-and-length-of-dashed-border-strokes-from-css
- https://htmlbook.ru/css/border-bottom-style
- https://sky.pro/wiki/html/sozdanie-punktirnoy-linii-css-primer-koda-i-obyasnenie/
Заключение
Для точного контроля толщины (12px), длины штриха (90px) и плавного длинного штриха в углах самый надёжный путь — SVG (использовать как background-image или border-image), где вы явно задаёте stroke-width, stroke-dasharray и дорисовываете corner‑paths. Если нужен чисто CSS‑подход — делайте повторяющиеся линейные градиенты на псевдоэлементе и добавляйте уголковые оверлеи; это гибко и responsive. Выберите SVG для pixel‑perfect и сложных углов, или CSS‑градиенты для простоты и адаптивности.