我试图了解在渐变边框图像的情况下border-image-slice的工作方式。规范中写道,border-image-slice的值可以是一个数字,
表示光栅图像的边缘偏移量(像素)和矢量图像的坐标。对于矢量图像,数字是相对于元素的大小,而不是源图像的大小,因此在这种情况下,通常最好使用百分比。
在examples中,来自CSS技巧article的边框图像设置如下:
border-image: repeating-linear-gradient(45deg,
#000, #000 1.5%,
transparent 1.5%, transparent 5%) 80;
因此,根据规范80是相对于div的大小(宽度:26em;高度:23em;)。但是我还是不明白这是什么意思。当我更改div的宽度或高度时,边框图像不会改变其外观。但是,当我更改border-image-slice或border宽度时,外观会发生很大变化。所以看起来数字80与5em的边框宽度之间存在相关性。 (数字40的边框看起来相同,边框宽度为2.5em,1em的边框宽度为16等)。
我的问题是,如何计算数字80,这意味着给定div和渐变的切片过程是什么? (草图将不胜感激) 似乎80不在px,em或%中,因为当我添加这些单位时,外观会发生变化。
完整代码在这里:
div {
box-sizing: border-box;
position: relative;
border: solid 5em #000;
border-image: repeating-linear-gradient(45deg,
#000, #000 1.5%,
transparent 1.5%, transparent 5%) 80;
padding: 2em;
width: 26em; height: 23em;
background: linear-gradient(to right bottom,
#e18728, #4472b9);
background-size: 50% 50%;
}
<div></div>
答案 0 :(得分:1)
在下一个示例中,我使用px而不是em,因为我认为更清楚。
这是用于边框图像的图像。
div{ width: 416px; height: 368px;
background:repeating-linear-gradient(45deg,
#000, #000 1.5%,
transparent 1.5%, transparent 5%);
}
<div></div>
此图像将被切成9个正方形,类似于网格。
图片来自本文:border-image-slice
如果border-image-slice
的值是80,则表示偏移量是80,即C1,C2,C3和C4的大小是80/80。所有C切片都用于边框图像的角。 E1,E2,E3和E4用于绘制边缘。
如果您使用的是208或50%,而不是80,则边框图像将出现角但没有边缘,因为边缘没有剩余。
接下来是一个演示,您可以在其中查看用于绘制边框图像的图像上切片的演变。我将div的宽度更改为300,因为我想同时看到 div带有边框图像和用于边框的图像一个接一个。在这种情况下,边框图像的边缘在border-image-slice:150;
itr.addEventListener("input",()=>{
let v = itr.value;
border.style.borderImageSlice = v;
itrspan.innerHTML = v;
let d = `M${v},0v300M${300-v},300v-300M0,${v}h300M300,${300-v}h-300`
thePath.setAttributeNS(null,"d",d)
})
div{display:inline-block;}
#border {
box-sizing: border-box;
position: relative;
border: solid 5em #000;
border-image: repeating-linear-gradient(45deg,
#000, #000 1.5%,
transparent 1.5%, transparent 5%);
border-image-slice:80;
padding: 2em;
width: 300px; height: 300px;
}
#image{
width: 300px; height: 300px;
background: repeating-linear-gradient(45deg,
#000, #000 1.5%,
transparent 1.5%, transparent 5%);}
input{width:300px;}
<input id="itr" type="range" min="0" max="300" value="80" ><span id="itrspan">80</span>
<br>
<div id="border"></div>
<svg id="image" viewBox="0 0 300 300">
<path id="thePath" fill="none" stroke="red" d="M80,0v300M220,300v-300M0,80h300M300,220h-300" />
</svg>
答案 1 :(得分:1)
使用渐变时,图像的大小就是元素的大小。 border-width-image
将定义我们将放置切片的9个区域(如果未定义,则使用border-width
)。 border-image-slice
将考虑使用初始图像来创建切片。将无单位值视为像素值,并根据元素的大小解析百分比值。
要获得完美的结果,我们应该等于区域的切片,为此,我们需要使border-slice-image
等于border-width-image
(或border-width
)(不带单位使用)时。使用百分比,计算值应该相同。
在您的情况下,切片中的80
意味着80px
,并且您有5em
的边界,即5x16px = 80px
让我们举一个简单的例子。
div {
width: 100px;
height: 100px;
display: inline-block;
border: 10px solid transparent;
}
div.box {
background: repeating-linear-gradient(45deg, #000, #000 5px, transparent 5px, transparent 10px) border-box, red;
}
div.border {
border-image: repeating-linear-gradient(45deg, #000, #000 5px, transparent 5px, transparent 10px) 50 fill;
border-image-width: 50px;
background: red;
}
<div class="box"></div>
<div class="border"></div>
在上面,我尝试使用不同的技术(背景和边框)使用相同的输出创建两个div。请注意,在第二个示例中,我如何使用关键字fill
并指定与边界宽度不同的border-width-image
并使用等于该边界宽度的切片。
请注意,由于我们处理非矢量图像(渐变),因此切片中的50
被视为像素。
数字表示图像中的像素(如果图像是光栅图像)或矢量坐标(如果图像是矢量图像)。 ref
让我们删除fill属性:
div {
width: 100px;
height: 100px;
display: inline-block;
border: 10px solid transparent;
}
div.box {
background: repeating-linear-gradient(45deg, #000, #000 5px, transparent 5px, transparent 10px) border-box, red;
}
div.border {
border-image: repeating-linear-gradient(45deg, #000, #000 5px, transparent 5px, transparent 10px) 50;
border-image-width: 50px;
background: red;
}
<div class="box"></div>
<div class="border"></div>
如果使用fill关键字,则将保留边框图像的中间部分。 (默认情况下将其丢弃,即被视为空。) ref
默认情况下,边框图像不会绘制在中间,而只会绘制在边框中。我们可以从示例中清楚地看到,在每边都有50px
,并且自定义边框如border-image-width
如果我们未指定border-image-width
,则默认值为1
,这意味着
数字代表相应的计算出的
border-width
的倍数。
因此,我们要么明确指定border-image-width
,要么简单地使用border-width
作为参考。在大多数情况下,只需要border-width
,因为在大多数情况下,我们只希望覆盖边界区域,而无需覆盖更多内容。
现在切片将图像分成9个部分
此属性指定距图像的顶部,右侧,底部和左侧边缘的向内偏移,将其分为9个区域:四个角,四个边缘和一个中
下面的步骤将更好地说明我们的示例是如何完成的:
div {
width: 100px;
height: 100px;
border: solid 10px transparent;
display: inline-block;
position: relative;
}
div:before {
content: "";
position: absolute;
top: -10px;
left: -10px;
right: -10px;
bottom: -10px;
background:
linear-gradient(green,green) left 0 top 50px/100% 1px no-repeat,
linear-gradient(green,green) left 0 bottom 50px/100% 1px no-repeat,
linear-gradient(green,green) top 0 left 50px/1px 100% no-repeat,
linear-gradient(green,green) top 0 right 50px/1px 100% no-repeat;
}
div.box {
background: repeating-linear-gradient(45deg, #000, #000 5px, transparent 5px, transparent 10px) border-box, red;
}
div.border {
border-image: repeating-linear-gradient(45deg, #000, #000 5px, transparent 5px, transparent 10px) 50;
border-image-width: 50px;
background: red;
}
<div class="box"></div>
<div class="border"></div>
左图是原始图像,我们将其分为9个部分,然后将每个图像放置在右图像的9个区域中。中间一个是空的,因为我们没有使用填充。在此示例中,由于切片适合区域,因此我们什么也没注意到。
现在让我们将切片缩小为25
:
div {
width: 100px;
height: 100px;
border: solid 10px transparent;
display: inline-block;
position: relative;
}
div.box:before {
content: "";
position: absolute;
top: -10px;
left: -10px;
right: -10px;
bottom: -10px;
background:
linear-gradient(blue,blue) left 0 top 25px/100% 1px no-repeat,
linear-gradient(blue,blue) left 0 bottom 25px/100% 1px no-repeat,
linear-gradient(blue,blue) top 0 left 25px/1px 100% no-repeat,
linear-gradient(blue,blue) top 0 right 25px/1px 100% no-repeat;
}
div.border:before {
content: "";
position: absolute;
top: -10px;
left: -10px;
right: -10px;
bottom: -10px;
background:
linear-gradient(green, green) left 0 top 50px/100% 1px no-repeat,
linear-gradient(green, green) left 0 bottom 50px/100% 1px no-repeat,
linear-gradient(green, green) top 0 left 50px/1px 100% no-repeat,
linear-gradient(green, green) top 0 right 50px/1px 100% no-repeat;
}
div.box {
background: repeating-linear-gradient(45deg, #000, #000 5px, transparent 5px, transparent 10px) border-box, red;
}
div.border {
border-image: repeating-linear-gradient(45deg, #000, #000 5px, transparent 5px, transparent 10px) 25;
border-image-width: 50px;
background: red;
}
<div class="box"></div>
<div class="border"></div>
这有点棘手,但适用相同的逻辑。从左边的图像开始,我们使用25px
切割每侧,以得到我们的9部分,我们将把它放在边框宽度仍然相同的右侧部分(50px
)中。您可以清楚地注意到角落中的零件是如何简单缩放和边缘变形的。
在每个角落,我们在25px 25px
区域内使用50px 50px
图像,例如,在上边缘,我们在60px 25px
区域内使用10px 50px
图像。
您还可以为每一面定义不同的值,如下所示:
div {
width: 100px;
height: 100px;
border: solid 10px transparent;
display: inline-block;
position: relative;
}
div.box:before {
content: "";
position: absolute;
top: -10px;
left: -10px;
right: -10px;
bottom: -10px;
background:
linear-gradient(blue, blue) left 0 top 20px/100% 1px no-repeat,
linear-gradient(blue, blue) left 0 bottom 30px/100% 1px no-repeat,
linear-gradient(blue, blue) top 0 left 20px/1px 100% no-repeat,
linear-gradient(blue, blue) top 0 right 60px/1px 100% no-repeat;
}
div.border:before {
content: "";
position: absolute;
top: -10px;
left: -10px;
right: -10px;
bottom: -10px;
background:
linear-gradient(green, green) left 0 top 50px/100% 1px no-repeat,
linear-gradient(green, green) left 0 bottom 50px/100% 1px no-repeat,
linear-gradient(green, green) top 0 left 50px/1px 100% no-repeat,
linear-gradient(green, green) top 0 right 50px/1px 100% no-repeat;
}
div.box {
background: repeating-linear-gradient(45deg, #000, #000 5px, transparent 5px, transparent 10px) border-box, red;
}
div.border {
border-image: repeating-linear-gradient(45deg, #000, #000 5px, transparent 5px, transparent 10px);
border-image-slice: 20 60 20 30;
border-image-width: 50px;
background: red;
}
<div class="box"></div>
<div class="border"></div>
现在,我们更加清楚如何对图像进行切片,然后通过缩放拉伸将它们放置在不同的区域中。显然,最好的值是使所有侧面的切片都等于边框宽度,在您的示例中就是这样,因为5em
为5x16px = 80px
,因此是80
的切片
从规范中我们还可以阅读:
border-image-slice值给定的区域可能重叠。但是,如果左右宽度的总和等于或大于图像的宽度,则顶部和底部边缘以及中间部分的图像为空,其效果与非空透明图像相同。为这些零件指定。类似地,用于顶部和底部值。
如果您指定的左切片和右切片大于图像宽度,那么从逻辑上讲,您将什么都不放在顶部/底部/中间部分:
div {
width: 100px;
height: 100px;
border: solid 10px transparent;
display: inline-block;
position: relative;
}
div.box:before {
content: "";
position: absolute;
top: -10px;
left: -10px;
right: -10px;
bottom: -10px;
background:
linear-gradient(blue, blue) left 0 top 20px/100% 1px no-repeat,
linear-gradient(blue, blue) left 0 bottom 30px/100% 1px no-repeat,
linear-gradient(blue, blue) top 0 left 60px/1px 100% no-repeat,
linear-gradient(blue, blue) top 0 right 60px/1px 100% no-repeat;
}
div.border:before {
content: "";
position: absolute;
top: -10px;
left: -10px;
right: -10px;
bottom: -10px;
background:
linear-gradient(green, green) left 0 top 50px/100% 1px no-repeat,
linear-gradient(green, green) left 0 bottom 50px/100% 1px no-repeat,
linear-gradient(green, green) top 0 left 50px/1px 100% no-repeat,
linear-gradient(green, green) top 0 right 50px/1px 100% no-repeat;
}
div.box {
background: repeating-linear-gradient(45deg, #000, #000 5px, transparent 5px, transparent 10px) border-box, red;
}
div.border {
border-image: repeating-linear-gradient(45deg, #000, #000 5px, transparent 5px, transparent 10px);
border-image-slice: 20 60 20 60;
border-image-width: 50px;
background: red;
}
<div class="box"></div>
<div class="border"></div>
相同的逻辑也适用于顶部/底部。
这是一个例子,其中我们只有拐角处
div {
width: 100px;
height: 100px;
border: solid 10px transparent;
display: inline-block;
position: relative;
}
div.box:before {
content: "";
position: absolute;
top: -10px;
left: -10px;
right: -10px;
bottom: -10px;
background:
linear-gradient(blue, blue) left 0 top 20px/100% 1px no-repeat,
linear-gradient(blue, blue) left 0 bottom 100px/100% 1px no-repeat,
linear-gradient(blue, blue) top 0 left 60px/1px 100% no-repeat,
linear-gradient(blue, blue) top 0 right 60px/1px 100% no-repeat;
}
div.border:before {
content: "";
position: absolute;
top: -10px;
left: -10px;
right: -10px;
bottom: -10px;
background:
linear-gradient(green, green) left 0 top 50px/100% 1px no-repeat,
linear-gradient(green, green) left 0 bottom 50px/100% 1px no-repeat,
linear-gradient(green, green) top 0 left 50px/1px 100% no-repeat,
linear-gradient(green, green) top 0 right 50px/1px 100% no-repeat;
}
div.box {
background: repeating-linear-gradient(45deg, #000, #000 5px, transparent 5px, transparent 10px) border-box, red;
}
div.border {
border-image: repeating-linear-gradient(45deg, #000, #000 5px, transparent 5px, transparent 10px);
border-image-slice: 20 60 100 60;
border-image-width: 50px;
background: red;
}
<div class="box"></div>
<div class="border"></div>
使用百分比值也将得到相同的结果。我们只需要查找参考,并且由于我们正在处理渐变,因此渐变的大小就是元素的大小。在我们的示例中,一片50
等于41.666%
,因为宽度/高度等于100px 2 * 10px = 120px
div {
width: 100px;
height: 100px;
border: solid 10px transparent;
display: inline-block;
position: relative;
}
div:before {
content: "";
position: absolute;
top: -10px;
left: -10px;
right: -10px;
bottom: -10px;
background:
linear-gradient(blue, blue) left 0 top 50px/100% 1px no-repeat,
linear-gradient(blue, blue) left 0 bottom 50px/100% 1px no-repeat,
linear-gradient(blue, blue) top 0 left 50px/1px 100% no-repeat,
linear-gradient(blue, blue) top 0 right 50px/1px 100% no-repeat;
}
div.box {
background: repeating-linear-gradient(45deg, #000, #000 5px, transparent 5px, transparent 10px) border-box, red;
}
div.border {
border-image: repeating-linear-gradient(45deg, #000, #000 5px, transparent 5px, transparent 10px) 41.666%;
border-image-width: 50px;
background: red;
}
<div class="box"></div>
<div class="border"></div>