【问题标题】:Control the dashed border stroke length and distance between strokes控制虚线边框笔划长度和笔划之间的距离
【发布时间】:2011-02-15 19:16:20
【问题描述】:

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

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

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

重大差异:IE 11 / Firefox / Chrome

是否有任何方法可以更好地控制虚线边框的外观?

【问题讨论】:

    标签: css border css-shapes


    【解决方案1】:

    原生虚线边框属性值不提供对虚线本身的控制...所以请使用border-image 属性!

    border-image 打造你自己的边框

    兼容性:它提供great browser support(IE 11 和所有现代浏览器)。可以将普通边框设置为旧浏览器的后备。

    让我们创建这些

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

    第 1 步 - 创建合适的图像

    此示例为 15 像素宽 x 15 像素高,间隙当前为 5 像素宽。它是一个具有透明度的 .png。

    这是放大后在 Photoshop 中的样子:

    这是缩放的样子:

    控制间隙和行程长度

    要创建更宽/更短的间隙或笔触,请加宽/缩短图像中的间隙或笔触。

    这是一张宽 10 像素间隙的图片:

    正确缩放 =

    第 2 步 - 创建 CSS - 此示例需要 4 个基本步骤

    1. 定义border-image-source

      border-image-source:url("http://i.stack.imgur.com/wLdVc.png");  
      
    2. 可选 - 定义border-image-width

      border-image-width: 1;
      

      默认值为 1。也可以设置为像素值、百分比值或其他倍数(1x、2x、3x 等)。这会覆盖任何 border-width 集。

    3. 定义border-image-slice

      在这个例子中,图片上下左右边框的粗细都是2px,它们之间没有间隙,所以我们的slice值是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>

    【讨论】:

    • 请注意,如果省略回退,则需要指定 border-style: solid(或类似名称)。
    • 此解决方案不适用于 'border-color' 属性
    • @MichaelRovinsky 当然。如果你想要其他颜色,你需要用你想要的颜色制作另一个图像。 border-color从不更改边框图像的颜色。
    【解决方案2】:

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

    方法一:使用 SVG

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

    优点:

    1. SVG 本质上是可缩放的图形,可以适应任何容器尺寸。
    2. 即使有border-radius 也能很好地工作。我们只需将path 替换为circle 就像在this answer 中一样(或)将path 转换为一个圆圈。
    3. Browser support for SVG 非常好,可以使用 VML for IE8 提供回退。

    缺点:

    1. 当容器的尺寸没有按比例变化时,路径往往会缩放,从而导致破折号的大小和它们之间的空间发生变化(尝试将鼠标悬停在 sn-p 中的第一个框上)。这可以通过添加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. Browser support for linear gradients 相对较低,如果您想支持 IE 9-,这是不行的。即使像 CSS3 PIE 这样的库也不支持在 IE8 中创建渐变模式。
    2. 在涉及border-radius 时不能使用,因为背景不会基于border-radius 弯曲。相反,它们会被剪掉。

    方法 3:盒子阴影

    我们可以使用伪元素创建一个小条(以破折号的形状),然后创建多个box-shadow 版本来创建一个边框,如下面的sn-p。

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

    优点:

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

    缺点:

    1. 由于我们必须手动设置破折号的尺寸和间距,因此当父框的尺寸是动态的时,这种方法就不好用了。
    2. IE8 及更低版本不支持support box shadow。不过,这可以通过使用 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 */
    }
    &lt;div class='dashed-box-shadow'&gt;Some content&lt;/div&gt;

    【讨论】:

    • 如果您要使用 svg 解决方案,我建议将 pointer-events:none 添加到 svg 以便能够与内容进行交互。
    【解决方案3】:

    @kovart 制作了一个很酷的工具,叫做dashed border generator

    它使用 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;
    }
    

    【讨论】:

    • 这是一个简单、简单、快速的解决方案
    【解决方案4】:

    Css 渲染是特定于浏览器的,我不知道对其进行任何微调,您应该按照 Ham 的建议使用图像。 参考:http://www.w3.org/TR/CSS2/box.html#border-style-properties

    【讨论】:

      【解决方案5】:

      简短的:不,不是。您将不得不使用图像。

      【讨论】:

      • 这个答案在 2018 年已经过时了
      • @WilliamHampshire 我会采用这种技术youtu.be/vs34f9FiHps?t=779 但请检查接受的答案,您可能更喜欢其他解决方案
      • @godblessstrawberry 谢谢!!但那是在使用 SVG,所以仍然不只使用 css...
      • @WilliamHampshire 在我的意思是 Harry 回答的线程中有 box-shadow 解决方案
      • @godblessstrawberry 你试过解决方案了吗?该解决方案逐段绘制虚线。这只是一个 POC,在实践中毫无用处!
      【解决方案6】:

      笔画长度取决于笔画宽度。您可以通过增加宽度来增加长度,并通过内部元素隐藏部分边框。

      编辑:感谢 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/

      【讨论】:

      • 但是这样你将无法点击原始元素的内容,因为“after”伪元素会覆盖它。所以最好的方法是使用 SVG。
      • 您可以添加pointer-events: none以防止覆盖问题。
      【解决方案7】:

      更新 感谢 kovart 提供了这个很棒的工具,试试吧 https://kovart.github.io/dashed-border-generator/

      我的回答是:

      我最近遇到了同样的问题。 我已经解决了这个问题,希望它对某人有所帮助。

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

      【讨论】:

        【解决方案8】:
        .outline {
            outline: 48px dashed #d5fb62;
            outline-offset: -4px;
            overflow:hidden;
        }
        

        如果溢出隐藏没有问题,否则轮廓 4 而不是 48。

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

        【讨论】:

        • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
        【解决方案9】:

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

        我设法通过两个带有边框的绝对定位的 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>
        

        注意:我在这个例子中使用了快子,但我想这些类是不言自明的。

        【讨论】:

          【解决方案10】:

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

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

          【讨论】:

          • 通过“提供对虚线边框外观的更大控制”,OP(原始海报)意味着他想要控制每个虚线的长度,如问题开头所述。很抱歉有任何混淆。
          猜你喜欢
          • 2021-04-18
          • 2011-06-02
          • 1970-01-01
          • 1970-01-01
          • 2012-06-14
          • 1970-01-01
          • 2013-08-02
          相关资源
          最近更新 更多