Reputation: 1655
I have a some block, with some design:
And I have some svg code:
.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>
Question: how to make inside a block with the same rounded cut corners, but not with a solid fill and stroke?
P.S: it should remain the ability to edit the radius of the rounding corners, indents vn. blocks. Perhaps there is a simple implementation on css (maximum cross-browser), would also be suitable.
Upvotes: 3
Views: 792
Reputation: 272752
I would go with a pure CSS solution using multiple background. It's a bit trick to manipulate but using some CSS variable you can make it easy to adjust:
.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>
Upvotes: 5
Reputation: 33034
This is my answer: I'm using the size of the bounding box of the text so you can change the text as you like. For the cut out corners I'm using arcs. Also you can change the "padding" i.e. the distance between the text and the border.
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>
Upvotes: 2
Reputation: 101800
How about this? It should work for any size by just changing the dimensions of <div class="box">
.
.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>
Upvotes: 5