Контроль длины штрихов пунктирной границы и расстояния между штрихами

124

Можно ли в CSS контролировать длину и расстояние между штрихами пунктирной границы?

Этот пример ниже отображается по-разному в разных браузерах:

div {
  border: dashed 4px #000;
  padding: 20px;
  display: inline-block;
}
<div>I have a dashed border!</div>

Большие различия: IE 11 / Firefox / Chrome

IE 11 границаГраница FirefoxРамка Chrome

Существуют ли какие-либо методы, позволяющие лучше контролировать появление пунктирных границ?

AntonAL
источник

Ответы:

157

Исходное значение свойства пунктирной границы не предлагает управления самими пунктирными линиями ... так что используйте border-imageсвойство!

Заварите свою собственную границу с border-image

Совместимость : он предлагает отличную поддержку браузера (IE 11 и все современные браузеры). Обычную рамку можно установить в качестве альтернативы для старых браузеров.

Создадим эти

Эти границы будут отображаться в одном и том же кросс-браузере!

Пример цели Пример цели с большими промежутками

Шаг 1 - Создайте подходящий образ

Этот пример имеет ширину 15 пикселей на высоту 15 пикселей, а ширина зазоров в настоящее время составляет 5 пикселей. Это прозрачный файл .png.

Вот как это выглядит в фотошопе при увеличении:

Пример увеличенного фона изображения границы

Вот как это выглядит в масштабе:

Пример фактического размера фона изображения границы

Контроль зазора и длины хода

Чтобы создать более широкие / короткие промежутки или штрихи, увеличивайте / сокращайте промежутки или штрихи в изображении.

Вот изображение с более широкими промежутками в 10 пикселей:

Большие зазоры правильно масштабировано = Большие зазоры в масштабе

Шаг 2 - Создайте CSS - для этого примера требуется 4 основных шага

  1. Определите источник изображения границы :

    border-image-source:url("http://i.stack.imgur.com/wLdVc.png");  
  2. Необязательно - Определите ширину изображения границы :

    border-image-width: 1;

    Значение по умолчанию - 1. Его также можно установить с помощью значения пикселя, процентного значения или другого кратного значения (1x, 2x, 3x и т. Д.). Это отменяет любой border-widthнабор.

  3. Определите срез изображения границы :

    В этом примере толщина верхней, правой, нижней и левой границ изображений составляет 2 пикселя, и за их пределами нет зазора, поэтому значение нашего среза равно 2:

    border-image-slice: 2; 

    Срезы выглядят следующим образом: 2 пикселя сверху, справа, снизу и слева:

    Пример срезов

  4. Определите border-image-repeat :

    В этом примере мы хотим, чтобы шаблон равномерно повторялся вокруг нашего div. Итак, выбираем:

    border-image-repeat: round;

Написание стенографии

Вышеуказанные свойства могут быть установлены индивидуально или сокращенно с помощью border-image :

border-image: url("http://i.stack.imgur.com/wLdVc.png") 2 round;

Полный пример

Обратите внимание на border: dashed 4px #000запасной вариант. Не поддерживающие браузеры получат эту границу.

.bordered {
  display: inline-block;
  padding: 20px;
  /* Fallback dashed border
     - the 4px width here is overwritten with the border-image-width (if set)
     - the border-image-width can be omitted below if it is the same as the 4px here
  */
  border: dashed 4px #000;
  
  /* Individual border image properties */
  border-image-source: url("http://i.stack.imgur.com/wLdVc.png");
  border-image-slice: 2;
  border-image-repeat: round;  
  
  /* or use the shorthand border-image */
  border-image: url("http://i.stack.imgur.com/wLdVc.png") 2 round;
}


/*The border image of this one creates wider gaps*/
.largeGaps {
  border-image-source: url("http://i.stack.imgur.com/LKclP.png");
  margin: 0 20px;
}
<div class="bordered">This is bordered!</div>

<div class="bordered largeGaps">This is bordered and has larger gaps!</div>

misterManSam
источник
Обратите внимание, что вам нужно указать border-style: solid(или что-то подобное), если вы опускаете откат.
Robbendebiene 06
Это решение не работает с атрибутом 'border-color'
Михаил Ровинский,
102

В дополнение к border-imageсвойству существует несколько других способов создания пунктирной границы с контролем длины штриха и расстояния между ними. Они описаны ниже:

Метод 1: использование SVG

Мы можем создать пунктирную границу, используя элемент pathили polygonэлемент и задав stroke-dasharrayсвойство. Свойство принимает два параметра, один из которых определяет размер тире, а другой - расстояние между ними.

Плюсы:

  1. SVG по своей природе являются масштабируемой графикой и могут адаптироваться к любым размерам контейнера.
  2. Может работать очень хорошо, даже если есть border-radiusзадействованный. Мы бы просто заменить pathс circleкак в этом ответе (или) преобразовать pathв круг.
  3. Браузер поддерживает SVG довольно хорошо, и резервное копирование может быть предоставлено с помощью VML для IE8-.

Минусы:

  1. Когда размеры контейнера изменяются непропорционально, пути имеют тенденцию к масштабированию, что приводит к изменению размера тире и расстояния между ними (попробуйте навести курсор на первое поле во фрагменте). Этим можно управлять, добавляя vector-effect='non-scaling-stroke'(как во втором поле), но поддержка этого свойства браузером в IE равна нулю.


Метод 2: Использование градиентов

Мы можем использовать несколько linear-gradientфоновых изображений и расположить их соответствующим образом, чтобы создать эффект пунктирной границы. Это также можно сделать с помощью a, repeating-linear-gradientно особого улучшения не происходит из-за использования повторяющегося градиента, поскольку нам нужно, чтобы каждый градиент повторялся только в одном направлении.

Плюсы:

  1. Масштабируемость и возможность адаптации, даже если размеры контейнера динамические.
  2. Не использует никаких дополнительных псевдоэлементов, что означает, что они могут быть отложены для любого другого потенциального использования.

Минусы:

  1. Браузер поддерживает линейные градиенты сравнительно меньше, и это не проблема, если вы хотите поддерживать IE 9-. Даже библиотеки, такие как CSS3 PIE, не поддерживают создание шаблонов градиента в IE8-.
  2. Невозможно использовать, когда border-radiusзадействовано, потому что фон не изгибается на основе border-radius. Вместо этого они обрезаются.

Метод 3: Тени коробки

Мы можем создать небольшую полосу (в форме тире), используя псевдоэлементы, а затем создать несколько ее box-shadowверсий, чтобы создать границу, как в приведенном ниже фрагменте.

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

Плюсы:

  1. Размеры тире можно контролировать, изменяя размеры псевдоэлемента. Интервал можно контролировать, изменяя расстояние между каждой тенью.
  2. Уникальный эффект можно получить, добавив разные цвета для каждой тени блока.

Минусы:

  1. Поскольку мы должны вручную установить размеры тире и интервал, этот подход бесполезен, когда размеры родительского блока являются динамическими.
  2. IE8 и ниже не поддерживают тень блока . Однако это можно преодолеть с помощью таких библиотек, как CSS3 PIE.
  3. Может использоваться с, border-radiusно их расположение было бы очень сложным, поскольку приходилось находить точки на окружности (и, возможно, даже transform).

Гарри
источник
Если вы собираетесь использовать решение svg, я советую добавить pointer-events:noneв svg inorder, чтобы иметь возможность взаимодействовать с контентом.
Sodj 06
Замечательный ответ.
Deviance
22

Короткий: Нет, это не так. Вместо этого вам придется работать с изображениями.

Хэм Воке
источник
5
этот ответ устарел по состоянию на 2018 год
godblessstrawberry
2
@WilliamHampshire Я бы пошел с этой техникой youtu.be/vs34f9FiHps?t=779, но проверьте принятый ответ, возможно, вам больше понравятся другие решения
godblessstrawberry
1
@godblessstrawberry Спасибо !! Но здесь используется SVG, так что все еще не используется только css ...
Кайл Кшески
1
@WilliamHampshire в ветке есть решение box-shadow, я имел в виду ответ Гарри
godblessstrawberry
@godblessstrawberry Вы пробовали решение? Решение нарисовано пунктирной линией сегмент за сегментом. Это просто POC и бесполезно на практике!
Ю
6

Там очень крутой инструмент сделал @kovart называется пунктирная граница генератора .

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

Затем вы могли бы просто использовать его как свойство фона в вашем элементе вместо границы:

div {
  background-image: url("data:image/svg+xml,%3csvg width='100%25' height='100%25' xmlns='http://www.w3.org/2000/svg'%3e%3crect width='100%25' height='100%25' fill='none' stroke='black' stroke-width='4' stroke-dasharray='6%2c 14' stroke-dashoffset='0' stroke-linecap='square'/%3e%3c/svg%3e");
  padding: 20px;
  display: inline-block;
}
Бальтазар
источник
Это простое, легкое и быстрое решение
jamesioppolo
Это сработало!
Кевин Раффей,
3

Длина штриха зависит от ширины штриха. Вы можете увеличить длину, увеличив ширину, и скрыть часть границы внутренним элементом.

.thin {
    background: #F4FFF3;
    border: 2px dashed #3FA535;  
    position: relative;
}

.thin:after {
    content: '';
    position: absolute;
    left: -1px;
    top: -1px;
    right: -1px;
    bottom: -1px;
    border: 1px solid #F4FFF3;
}

https://jsfiddle.net/ok6srt2z/

ili4
источник
Но таким образом вы не сможете щелкнуть по содержимому исходного элемента, потому что псевдоэлемент «после» его покроет. Итак, лучший способ - использовать SVG.
ili4
Вы можете добавить, pointer-events: noneчтобы предотвратить проблему наложения.
BenJ
0

У меня совсем недавно была такая же проблема.

Мне удалось решить эту проблему с двумя абсолютно позиционированными div, несущими границу (один для горизонтального и один для вертикального), а затем преобразовав их. Внешний бокс просто нужно расположить относительно друг друга.

<div class="relative">
    <div class="absolute absolute--fill overflow-hidden">
        <div class="absolute absolute--fill b--dashed b--red"
            style="
                border-width: 4px 0px 4px 0px;
                transform: scaleX(2);
        "></div>
        <div class="absolute absolute--fill b--dashed b--red"
            style="
                border-width: 0px 4px 0px 4px;
                transform: scaleY(2);
        "></div>
    </div>

    <div> {{Box content goes here}} </div>
</div>

Примечание: в этом примере я использовал тахионы, но я думаю, что классы не требуют пояснений.

razzz
источник
-1

Это создаст оранжево-серую границу, используя class = "myclass" в div.

.myclass {
    outline:dashed darkorange  12px;
    border:solid slategray  14px;
    outline-offset:-14px;
}
BJC
источник
Под «обеспечить больший контроль внешнего вида пунктирных границ» OP (оригинальный плакат) означает, что он хочет контролировать длину каждого тире, как указано в начале вопроса. Извините за путаницу.
Skylar