【问题标题】:svg border corners with inner bordersvg 带内边框的边框角
【发布时间】:2019-04-22 21:06:43
【问题描述】:

我有一些街区,有一些设计:

我有一些 svg 代码:

.box {
	position: relative;
	margin: .75em auto 0;
	max-width: 255px;
	min-height: 56px;
}

svg {
	position: absolute;
	width: 100%; height: 100%;
}
<div class='box'>
	<svg>
		<mask id='m' fill='#fff'>
			<rect id='r' width='256' height='56'/>
			<circle id='c' r='10' fill='#000'/>
			<use xlink:href='#c' x='100%'/>
			<use xlink:href='#c' y='100%'/>
			<use xlink:href='#c' x='100%' y='100%'/>
		</mask>
		
		<mask id='m2' fill='#fff'>
			<rect id='r2' width='248' height='50' x="4" y="4" />
			<circle id='c2' r='14' fill='#000' stroke='#000'/>
			<use xlink:href='#c2' x='100%' />
			<use xlink:href='#c2' y='100%'/>
			<use xlink:href='#c2' x='100%' y='100%'/>
		</mask>
		
		<use xlink:href='#r' fill='red' mask='url(#m)'/>
		<use xlink:href='#r2' fill='none' stroke="#000" mask='url(#m2)'/>
	</svg>
</div>

问题:如何在块内制作具有相同圆角切角,但不使用实心填充和描边?

P.S:它应该保留编辑圆角半径的能力,缩进vn。块。或许在css上有一个简单的实现(最大跨浏览器),也可以。

【问题讨论】:

    标签: html css svg css-shapes


    【解决方案1】:

    我会选择使用多个背景的纯 CSS 解决方案。操作起来有点小技巧,但使用一些 CSS 变量可以轻松调整:

    .box {
      --th:2px; /*thickness of the transparent part*/
      --l:4px; /*height of border*/
      --r:25px; /*radius*/
      
      
      --rad:transparent calc(103% - var(--th) - var(--l) - 1px), 
             #000 calc(103% - var(--th) - var(--l))  
                  calc(103% - var(--th) - 1px),
             transparent calc(103% - var(--th)) 103%,
             #000 103%;
      --rad-s:var(--r) var(--r);
      --border:#000 calc(var(--l)),transparent calc(var(--l)),transparent calc(var(--l) + var(--th));
      --w:calc(100% - 2*var(--r) + 2*var(--th));
      --h:calc(var(--l) + var(--th));
      margin:10px;
      display:inline-block;
      padding:40px 20px;
      background:
        /*The 4 borders*/
        linear-gradient(to bottom,var(--border)) top   /var(--w) var(--h),
        linear-gradient(to top   ,var(--border)) bottom/var(--w) var(--h),
        linear-gradient(to right ,var(--border)) left  /var(--h) var(--w),
        linear-gradient(to left  ,var(--border)) right /var(--h) var(--w),
        /*The 4 corners */
        radial-gradient(farthest-side at top    right,var(--rad)) top    right/var(--rad-s),
        radial-gradient(farthest-side at top    left ,var(--rad)) top    left /var(--rad-s),
        radial-gradient(farthest-side at bottom right,var(--rad)) bottom right/var(--rad-s),
        radial-gradient(farthest-side at bottom left ,var(--rad)) bottom left /var(--rad-s),
        /*The main background*/
        linear-gradient(#000,#000) center/calc(100% - 2*var(--r)) calc(100% - 2*var(--h)),
        linear-gradient(#000,#000) center/calc(100% - 2*var(--h)) calc(100% - 2*var(--r));
        
     background-repeat:no-repeat;
     
     color:#fff;
     text-align:center;
    }
    
    body {
     background:pink;
    }
    <div class="box">
      Some text inside
    </div>
    
    <div class="box" style="--th:3px;--r:20px">
      Some text inside
    </div>
    
    <div class="box" style="--th:4px;--r:40px;--l:8px">
      Some text inside
    </div>
    
    <div class="box" style="--th:5px;--r:30px">
      Some text inside
    </div>
    
    <div class="box" style="--th:1px;--r:15px;--l:3px">
      Some text inside
    </div>

    【讨论】:

    • @HamSter 是的...再次检查,我添加了几个像素来纠正这个问题
    • @HamSter 不是那样......你需要调整所有的值,而不仅仅是其中的几个:jsfiddle.net/nb3ph59a
    • @HamSter 将尝试编辑以使其更易于调整,但是如果您找到好方法,SVG 会更好
    • @HamSter 做了一些修改,但仍然不完美,但现在更容易处理
    【解决方案2】:

    这个怎么样?只需更改&lt;div class="box"&gt; 的尺寸,它就可以适用于任何尺寸。

    .box {
    	position: relative;
    	margin: .75em auto 0;
    	width: 255px;
    	height: 56px;
    }
    
    .box svg {
    	position: absolute;
    	width: 100%;
      height: 100%;
    }
    
    .size2 {
    	width: 455px;
    	height: 256px;
    }
    <div class="box">
      <svg width="100%" height="100%">
        <mask id="m" fill="#fff">
          <rect width="100%" height="100%"/>
    
          <rect width="100%" height="100%" fill="none" stroke="#000" stroke-width="12"/>
          <circle r="16" fill="#000"/>
          <circle cx="100%" r="16" fill="#000"/>
          <circle cy="100%" r="16" fill="#000"/>
          <circle cx="100%" cy="100%" r="16" fill="#000"/>
    
          <rect width="100%" height="100%" fill="none" stroke="#fff" stroke-width="8"/>
          <circle r="14" fill="#fff"/>
          <circle cx="100%" r="14" fill="#fff"/>
          <circle cy="100%" r="14" fill="#fff"/>
          <circle cx="100%" cy="100%" r="14" fill="#fff"/>
    
          <circle r="10" fill="#000"/>
          <circle cx="100%" r="10" fill="#000"/>
          <circle cy="100%" r="10" fill="#000"/>
          <circle cx="100%" cy="100%" r="10" fill="#000"/>
        </mask>
    		
        <rect width="100%" height="100%" mask="url(#m)"/>
      </svg>
    </div>

    【讨论】:

    • 有没有办法包含一种变量来一次调整所有相同的值?
    • SVG2 允许您使用 CSS 设置 r。所以你可以使用 CSS 变量和 calc() ,就像 Afif 的回答一样。但是,到目前为止,只有 Chrome 支持 SVG2 的那部分。或者,您可以使用 Javascript 来调整所有半径和笔划宽度。
    • 你的回答比其他人更能帮助我codepen.io/semenchenko/pen/BGJaVx,谢谢!
    【解决方案3】:

    这是我的回答:我正在使用文本边界框的大小,因此您可以随意更改文本。 对于切出的角落,我使用的是弧线。 您还可以更改“填充”,即文本和边框之间的距离。

    let bb = txt.getBBox();
    
    
    function drawShape(path, padding){
    let d = `M${bb.x},${bb.y - padding}
             L${bb.x + bb.width},${bb.y - padding}
    A${padding}, ${padding} 0 0 0 ${bb.x + bb.width + padding},${bb.y}
             L${bb.x + bb.width + padding},${bb.y + bb.height}
    A${padding}, ${padding} 0 0 0 ${bb.x + bb.width},${bb.y + bb.height + padding}
             L${bb.x},${bb.y + bb.height + padding}
    A${padding}, ${padding} 0 0 0 ${bb.x  - padding},${bb.y + bb.height}
             L${bb.x  - padding},${bb.y}
    A${padding}, ${padding} 0 0 0 ${bb.x},${bb.y - padding}z
    `
    path.setAttributeNS(null,"d",d)
    }
    drawShape(pth, 10);
    drawShape(pth1, 10);
    <svg viewBox="0 0 200 100">
      <path id="pth" fill="black" stroke="black" stroke-width="4" d="" />
      <path id="pth1" stroke="white" stroke-width="2" d="" />
      <text id="txt" fill="white" dominant-baseline="central" text-anchor="middle" x="100" y="50">
        some text inside
      </text>
      </svg>

    【讨论】:

    • 如果内边框(白边框)应该是1px2px,我应该怎么改?
    • 在 SVG 中,您需要使用 stroke-width 对应 #pth#pth1,记住黑色笔划 (#pth) 应该比白色笔划 ( #pth1)。
    猜你喜欢
    • 1970-01-01
    • 2013-04-06
    • 1970-01-01
    • 2020-12-02
    • 2023-03-30
    • 2015-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多