控制虚线边框的笔画长度和笔画之间的距离

是否可以在 CSS 中控制虚线边框笔画之间的长度和距离?

下面的示例在不同浏览器之间显示不同:

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

Big differences: IE 11 / Firefox / Chrome

IE 11 borderFirefox BorderChrome border

Are there any methods that can provide greater control of the dashed borders appearance?

274704 次浏览

简短的一句: 不,不是这样的。你将不得不使用图像来代替。

CSS 渲染是浏览器特有的,我不知道对它进行任何微调,你应该按照 Ham 的建议使用图像。 参考文献: < a href = “ http://www.w3.org/TR/css2/box.html # orders-style-properties”rel = “ norefrer”> http://www.w3.org/tr/css2/box.html#border-style-properties

本地虚线边界属性值不提供对虚线本身的控制... ... 因此使用 border-image属性!

border-image酿造你自己的边界

兼容性 : 它提供 很好的浏览器支持(IE11和所有现代浏览器)。可以将普通边框设置为旧版浏览器的备用边框。

让我们创建这些

这些边框将显示完全相同的跨浏览器!

Goal exampleGoal example with wider gaps

步骤1-创建一个合适的图像

这个例子是15像素宽15像素高,目前的差距是5像素宽。这是一个。透明的 png。

这是放大后在 Photoshop 中的效果:

Example Border Image Background Blown Up

这就是它看起来的规模:

Example Border Image Background Actual Size

控制间隙和行程长度

要创建更宽/更短的间隙或笔画,请扩大/缩短图像中的间隙或笔画。

下面是一张10像素宽的图片:

Larger gaps正确缩放 = Larger gaps to scale

步骤2-创建 CSS & mash; 这个例子需要4个基本步骤

  1. 定义 边界-图像-来源:

    border-image-source:url("http://i.stack.imgur.com/wLdVc.png");
    
  2. Optional - Define the border-image-width:

    border-image-width: 1;
    

    默认值为1。它也可以设置为一个像素值,百分比值,或作为另一个倍数(1 x,2 x,3 x 等)。这将覆盖任何 border-width集。

  3. 定义 边框-图像-切片:

    在这个例子中,顶部、右边、底部和左边边框的厚度是2px,并且在它们之外没有间隙,所以我们的切片值是2:

    border-image-slice: 2;
    

    这些切片看起来像这样,上下左右各2个像素:

    Slices example

  4. 定义 边框-图像-重复:

    在这个例子中,我们希望模式在 div 周围均匀地重复,所以我们选择:

    border-image-repeat: round;
    

Writing shorthand

The properties above can be set individually, or in shorthand using 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>

除了 border-image属性之外,还有其他一些方法可以创建虚线边框,控制中风的长度和它们之间的距离。他们的描述如下:

方法1: 使用 SVG

我们可以通过使用 pathpolygon元素并设置 stroke-dasharray属性来创建虚线边界。该属性接受两个参数,其中一个定义破折号的大小,另一个确定它们之间的空间。

优点:

  1. SVG 本质上是可伸缩的图形,可以适应任何容器尺寸。
  2. 即使有 border-radius参与,也能很好地工作。我们只需要用 circle代替 path,就像在 这个答案中一样(或者)把 path转换成一个圆。
  3. 对 SVG 的浏览器支持非常好,可以使用针对 IE8-的 VML 提供备份。

缺点:

  1. 当容器的尺寸不成比例地变化时,路径趋向于缩放,导致破折号的大小和它们之间的空间发生变化(尝试将鼠标悬停在代码片段中的第一个框上)。这可以通过添加 vector-effect='non-scaling-stroke'(如第二个框中所示)来控制,但是 IE 中对此属性的浏览器支持为空。

.dashed-vector {
position: relative;
height: 100px;
width: 300px;
}
svg {
position: absolute;
top: 0px;
left: 0px;
height: 100%;
width: 100%;
}
path{
fill: none;
stroke: blue;
stroke-width: 5;
stroke-dasharray: 10, 10;
}
span {
position: absolute;
top: 0px;
left: 0px;
padding: 10px;
}




/* just for demo */


div{
margin-bottom: 10px;
transition: all 1s;
}
div:hover{
height: 100px;
width: 400px;
}
<div class='dashed-vector'>
<svg viewBox='0 0 300 100' preserveAspectRatio='none'>
<path d='M0,0 300,0 300,100 0,100z' />
</svg>
<span>Some content</span>
</div>


<div class='dashed-vector'>
<svg viewBox='0 0 300 100' preserveAspectRatio='none'>
<path d='M0,0 300,0 300,100 0,100z' vector-effect='non-scaling-stroke'/>
</svg>
<span>Some content</span>
</div>


方法2: 使用渐变

我们可以使用多个 linear-gradient背景图像和位置适当创建一个虚线边界效果。这也可以做一个 repeating-linear-gradient,但没有太多的改进,因为使用重复梯度,因为我们需要每个梯度重复只有一个方向。

.dashed-gradient{
height: 100px;
width: 200px;
padding: 10px;
background-image: linear-gradient(to right, blue 50%, transparent 50%), linear-gradient(to right, blue 50%, transparent 50%), linear-gradient(to bottom, blue 50%, transparent 50%), linear-gradient(to bottom, blue 50%, transparent 50%);
background-position: left top, left bottom, left top, right top;
background-repeat: repeat-x, repeat-x, repeat-y, repeat-y;
background-size: 20px 3px, 20px 3px, 3px 20px, 3px 20px;
}


.dashed-repeating-gradient {
height: 100px;
width: 200px;
padding: 10px;
background-image: repeating-linear-gradient(to right, blue 0%, blue 50%, transparent 50%, transparent 100%), repeating-linear-gradient(to right, blue 0%, blue 50%, transparent 50%, transparent 100%), repeating-linear-gradient(to bottom, blue 0%, blue 50%, transparent 50%, transparent 100%), repeating-linear-gradient(to bottom, blue 0%, blue 50%, transparent 50%, transparent 100%);
background-position: left top, left bottom, left top, right top;
background-repeat: repeat-x, repeat-x, repeat-y, repeat-y;
background-size: 20px 3px, 20px 3px, 3px 20px, 3px 20px;
}


/* just for demo */


div {
margin: 10px;
transition: all 1s;
}
div:hover {
height: 150px;
width: 300px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class='dashed-gradient'>Some content</div>
<div class='dashed-repeating-gradient'>Some content</div>

优点:

  1. 可伸缩,即使容器的尺寸是动态的,也能适应。
  2. 不使用任何额外的伪元素,这意味着它们可以留作其他潜在用途。

缺点:

  1. 浏览器对线性渐变 的支持相对较低,如果你想支持 IE9-,这是不可行的。即使像 CSS3 PIE 这样的库也不支持在 IE8-中创建渐变模式。
  2. 当涉及到 border-radius时不能使用,因为背景不是基于 border-radius的曲线,而是被剪切。

方法3: 盒子阴影

我们可以使用伪元素创建一个小条(以破折号的形状) ,然后创建它的多个 box-shadow版本,以创建一个边框,如下面的代码片段所示。

如果破折号是一个正方形,那么一个伪元素就足够了,但如果它是一个矩形,我们需要一个伪元素用于顶部 + 底部边框,另一个用于左边 + 右边框。这是因为顶部边框上的破折号的高度和宽度将与左边的不同。

优点:

  1. 破折号的尺寸可以通过改变伪元素的尺寸来控制。间距可以通过修改每个阴影之间的空间来控制。
  2. 通过为每个盒子阴影添加不同的颜色,可以产生非常独特的效果。

缺点:

  1. 因为我们必须手动设置破折号和间距的尺寸,所以当父盒子的尺寸是动态的时候,这种方法是不好的。
  2. IE8和更低的版本不能使用 支撑箱阴影支撑箱阴影。但是,这可以通过使用像 CSS3 PIE 这样的库来克服。
  3. 可以使用与 border-radius,但定位他们将是非常棘手的,必须找到一个圆点(甚至可能是 transform)。

.dashed-box-shadow{
position: relative;
height: 120px;
width: 120px;
padding: 10px;
}
.dashed-box-shadow:before{ /* for border top and bottom */
position: absolute;
content: '';
top: 0px;
left: 0px;
height: 3px; /* height of the border top and bottom */
width: 10px; /* width of the border top and bottom */
background: blue; /* border color */
box-shadow: 20px 0px 0px blue, 40px 0px 0px blue, 60px 0px 0px blue, 80px 0px 0px blue, 100px 0px 0px blue, /* top border */
0px 110px 0px blue, 20px 110px 0px blue, 40px 110px 0px blue, 60px 110px 0px blue, 80px 110px 0px blue, 100px 110px 0px blue; /* bottom border */
}
.dashed-box-shadow:after{ /* for border left and right */
position: absolute;
content: '';
top: 0px;
left: 0px;
height: 10px; /* height of the border left and right */
width: 3px; /* width of the border left and right */
background: blue; /* border color */
box-shadow: 0px 20px 0px blue, 0px 40px 0px blue, 0px 60px 0px blue, 0px 80px 0px blue, 0px 100px 0px blue, /* left border */
110px 0px 0px blue, 110px 20px 0px blue, 110px 40px 0px blue, 110px 60px 0px blue, 110px 80px 0px blue, 110px 100px 0px blue; /* right border */
}
<div class='dashed-box-shadow'>Some content</div>

这将使用 div 上的 class = “ myclass”创建橙色和灰色的边框。

.myclass {
outline:dashed darkorange  12px;
border:solid slategray  14px;
outline-offset:-14px;
}

行程长度取决于行程宽度。可以通过增加宽度来增加长度,并通过内部元素隐藏边框的一部分。

编辑: 由于 benJ,增加了 pointer-events: none;

.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;
pointer-events: none;
}

Https://jsfiddle.net/ksf9zolh/

我最近也遇到了同样的问题。

我设法用两个绝对定位的 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>

注意: 我在这个例子中使用了超光速粒子,但是我想这些类是不言而喻的。

@ 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;
}

更新 感谢 Kovart 这个伟大的工具,试试看 Https://kovart.github.io/dashed-border-generator/

 a tool to generate dashed custom borders

我的回答是:

我最近也遇到了同样的问题。 我已经解决了这个问题,希望它能帮到别人。

HTML + 顺风

<div class="dashed-border h-14 w-full relative rounded-lg">
<div class="w-full h-full rounded-lg bg-page z-10 relative">
Content goes here...
<div>
</div>

CSS

.dashed-border::before {
content: '';
position: absolute;
top: 50%;
left: 0;
width: 100%;
height: calc(100% + 4px);
transform: translateY(-50%);
background-image: linear-gradient(to right, #333 50%, transparent 50%);
background-size: 16px;
z-index: 0;
border-radius: 0.5rem;
}
.dashed-border::after {
content: '';
position: absolute;
left: 50%;
top: 0;
height: 100%;
width: calc(100% + 4px);
transform: translateX(-50%);
background-image: linear-gradient(to bottom, #333 50%, transparent 50%);
background-size: 4px 16px;
z-index: 1;
border-radius: 0.5rem;
}
.outline {
outline: 48px dashed #d5fb62;
outline-offset: -4px;
overflow:hidden;
}

如果溢出隐藏不问题其他大纲4而不是48。

<div class="outline"></div>

我想我已经找到了这个问题的最终解决方案与使用 clip-path属性。基本上只需要添加一个虚线边框,然后掩盖多余的部分。

clip-path属性还支持圆角,所以你可以匹配它与 border-radius和有自定义虚线边界和圆角!

.demo {
display: inline-flex;
width: 200px;
height: 100px;
position: relative;
clip-path: inset(0 round 30px 0 30px 0);
}


.demo::before {
content: '';
position: absolute;
left: -7px;
top: -7px;
right: -7px;
bottom: -7px;
border: 8px dashed rgba(0, 0, 255, 0.3);
border-radius: 37px 0 37px 0;
box-sizing: border-box;
}
<div class="demo"></div>

You could do this directly on the div itself of course without using the ::after pseudo element. But this would mean you have to clip into the div and it would end up smaller than it's initial size.