所有图都在body背景设置为green下的截图,请不要把最外层的绿色当成边框
半透明边框
如果我们想给一个容器设置一层白色背景和一道半透明的白色边框,使容器后面的容器背景透上来,一般我们会这样子尝试:
border: 10px solid hsla(0, 0%, 100%, .5);background: white;
显示结果如下:
你会发现边框不知道那里去了,这是为何,还有什么办法?
-
原因:其实我们的边框是存在的,只是背景会侵透到边框,而上层我们设置的也是白色实线半透明边框,故看上去好像边框不见了,可以换个虚线边框加以验证:
这个表现即是CSS2的背景工作原理,我们只能接受它。
解决方法:好在CSSb3可以通过
background-clip
属性来调整背景范围,默认值为border-box
,意味着背景会侵透到边框的外沿框,我们只要把值设置为padding-box
,背景就会被内边距的外沿剪切掉
border: 10px solid hsla(0, 0%, 100%, .5);background: white;background-clip: padding-box;
这样就达到我们预想的效果。
注:IE8以下需要使用滤镜来达到半透明效果,或者准备一张半透明的图片充当背景。
多重边框
如何实现多重边框,或许你会想到使用多个元素来模拟多重边框,不过这样子会需要额外的元素来实现,有没有其他办法叻?
解决方法-box-shadow
box-shadow即投影,通过设置两个偏移,一个模糊量值,一个扩张半径来控制投影。box-shadow: 0 0 0 10px #655
只设置一个10px的扩张半径来模拟边框:
它支持逗号分隔,来创建多个投影,因此我们可以在加上一条边框:
background-color: yellowgreen;
box-shadow: 0 0 0 10px #655, 0 0 0 20px deeppink;
效果如下:
- 投影跟边框不完全一致,投影不影响布局,也不受box-sizing属性的控制。投影占据的空间需要通过设置margin||padding腾出来。
- 投影不会响应鼠标事件,为了解决这问题,可以通过给投影添加关键字
inset
,控制向元素内投影,对应的需要padding提供足够的空间
box-shadow: 0 0 0 10px #655 inset,
0 0 0 20px deeppink inset,
2px 2px 5px 5px rgba(0, 0, 0, 0.6);
效果如下:
注意:投影是按照顺序层层叠加,第一层位于最顶层
解决方案二-outline
如果只需要实现二层边框,可以使用outline来实现,并且这种方法可以实现不同样式的边框,box-shadow
只能实现实线边框,如果要实现虚线就不行了。
border: 10px solid #655;
outline:10px solid deeppink;
效果如下:
通过设置outline-offset可以设置outline(描边)与border(边框)之间的间隔
border: 10px solid #655;
outline:10px solid deeppink;
outline-offset: 10px;
注意:- outline方式只能实现双重边框,如果要实现多重只能选择box-shadow方式
- 如果通过border-radius设置了圆角,outline并不会贴这边框,还是直角的。
明显看到了边框与描边四角之间的空隙
灵活的背景定位
如何实现相对容器某个角对背景图片做偏移定位?
CSS2只能设置背景图片相对于左上角进行偏移或者固定在其他三个角,那如何让背景图片相对某个角留出一定的空隙叻?
CSS2要实现只能计算背景图片距离左上角的偏移来实现,如果容器尺寸不固定,这样的方法就失效了。
解决方法-background-position扩展
background: url(img/3_0.png) no-repeat #58a;
background-position: right 20px bottom 20px;
只需在偏移量之前设置指定关键字,效果如下:
背景图距离右下各20px
注:老版浏览器不支持扩展的话,背景图片会显示在左上角,所以需要设置background:url(img/3-0.png) no-repeat right bottom
来实现回退方案。
解决方法-background-origin
如何设置偏移量与内边距一致?
用上面的方法:
pading: 10px;
background: url(img/3_0.png) no-repeat #58a;
background-position: right 10px bottom 10px;
这样可以实现,不过在修改padding之后,其他几处的偏移量也需要修改。
有方法实现偏移跟着内边距变化吗?
首先我们需要确认background-position
设置的偏移是相对于那个左上角,每个元素都有三个矩形,border(边框的外沿框),padding(内边距的外沿框),content(内容区的外沿框)?
默认情况下,偏移是以padding为准的,在CSS2是不能修改的,CSS3中我们可以通过background-origin
来改变这种行为,通过变更这个属性值可以设置相对于那个边框进行偏移。
padding:10px;
background: url(img/3_0.png) no-repeat #58a;
background-position: right 10px bottom 10px;
background-origin: content-box;
效果如下:
距离右下角20px,10px是padding值,10px是偏移量
解决方案-calc()方案
background: url(img/3_0.png) no-repeat #58a;
background-position: calc(100% - 20px) calc(100% - 20px);
效果如下:
是不是跟上一个一样,不过这个是相对于padding外沿框的偏移
注意:calc函数内部的 - + 运算符左右都需要一个空格,否则是解析出错。
边框内圆角
想想如何实现一下效果:
一个容器有内侧圆角,但是边框或者描边是直角
解决方法-多元素
<style>
.container{
padding: 1em; background: red;
}
.container > div {
padding: .8em;
background: tan;
border-radius: .4em;
}
</style>
<div class='container'>
<div> </div>
</div>
效果如下:
这个方法需要两个元素,是否可以通过一个元素实现叻?
解决方法-box-shadow&outline
上一小节得知,outline
描边并不会受到border-radius
的影响而表现为直角。box-shadow
会受到border-radius
的影响而表现为圆角。
所以本方法即用阴影去填充描边已边框之间的空隙
padding: 1em;
border-radius: .8em;
box-shadow: 0 0 0 .4em #655;
outline: .4em solid #655;
效果如下:
成功实现
考虑下阴影需要设置为多大才能刚好填充空隙叻?
由勾股定律得知阴影的扩张值应该为 (a^2 + b^2 开根)- 圆角圆心到边框的距离,当直角两边相等时,这个值为(2a^2开根)-a。
因为所以得出结论:要覆盖掉描边与边框之间的空隙,阴影的值需要大于某个值,如果圆角两边相等,这个值小于0.4, 为了好记,避免每次都需要计算,可以把这个值设定为圆角半径的一半。但是这个值不能没有上限,当值超过描边的宽度时候,就会出现以下情况:
border-radius: .8em;
box-shadow: 0 0 0 .5em #655;
outline: .4em solid #655;
条纹背景
网页中我们经常使用条纹背景图案,通常我们的解决方法是创建一个单独的图片。但是它并不是最理想的,每次调整都需要图像编辑器来进行修改图片。如何使用CSS创建条纹背景叻?
解决方法-linear-gradient
水平条纹
background: linear-gradient(#fb3, #58a);
可以看到实现的是一条垂直方向上的颜色渐变背景。通过调整色标来对渐变区域进行调整
background: linear-gradient(#fb3 30%, #58a 70%);
可以看到背景只有中间40%的区域是渐变,上下两边各30%都是纯色。
如果把色标重合在一起也就是设置为50%,有何效果?
没错,就是两条具大的条纹出现了.
渐变是由代码生成的图片,可以像对待图片一样对待渐变,通过设置background-size
可调整渐变图案的尺寸
background: linear-gradient(#fb3 50%, #58a 50%);
background-size: 100% 30px;
因为默认背景图案会进行平铺,所以得到了如上两色的条纹背景。如果想实现不等宽条纹,只需要调整色标的位置值
background: linear-gradient(#fb3 30%, #58a 30%);
background-size: 100% 30px;
如果一个色标值比之前设置的色标值都小,该色标值会设置成前面所有色标值中的最大值,所以可这样设置
background: linear-gradient(#fb3 30%, #58a 0);
background-size: 100% 30px;
两种都将得到上图,因为后一种只需修改一个地方。所以也算是写代码的捷径吧。
此外还可以设置超过两种颜色的条纹,以三色为例
background: linear-gradient(#fb3 33.3%, #58a 0, #58a 66.6%, yellowgreen 0);
background-size: 100% 45px;
效果如下:
垂直条纹
实现了水平条纹,垂直条纹如何实现叻?
垂直条纹只需要在开头添加一个额外的参数来指定渐变方向,默认值是to bottom,我们只需要设置为 to right即可
background: linear-gradient(to right,
#fb3 25%, #58a 0,
#58a 50%, yellowgreen 0,
yellowgreen 75%, black 0);
background-size: 60px 100%;
效果如下:
斜向条纹
实现了水平与垂直条纹,顺下想,如果实现一个斜向的条纹叻?
比如斜向45°
尝试如下实现方式:
background: linear-gradient(45deg, #fb3 50%, #58a 0);
background-size: 30px 30px;
失败了,这样只是把背景图案中每个贴片旋转了45°,根据用图片实现斜向条纹的经验,我们需要在每个贴片中包含四条条纹才能做到无缝拼接,在次尝试如下方式:
background: linear-gradient(45deg,
#fb3 25%, #58a 0,
#58a 50%, #fb3 0,
#fb3 75%, #58a 0);
background-size: 30px 30px;
成功拼接成了斜向的条纹图案,不过变成四条条纹之后对应的每条条纹的宽度变窄了,如何才能扩大到指定宽度的条纹图案叻?
根据勾股定理,当设置背景尺寸为30px时,条纹的宽度为15/(2开根),约为10.6px。所以通过增加背景尺寸可以增加条纹宽度,这个值大约为42.4大小的时候得到的宽度近似为15px。
background: linear-gradient(45deg,
#fb3 25%, #58a 0,
#58a 50%, #fb3 0,
#fb3 75%, #58a 0);
background-size: 42.426406871px 42.426406871px;
得到了如上背景,不过上面的方法得到的也只是近似为指定宽度的条纹。有没有更好的方法叻?
更好的斜向条纹
之前的斜向条纹只能在斜向45°,如果要实现其他角度的时候,之前的方法就显得不好了,其实linear-gradient
和radial-gradient
还各有一个循环式加强版:repeating-linear-gradient
和repeating-radial-gradient
,加强版色标是无限循环重复的,直到填满整个背景。
background: repeating-linear-gradient(45deg,
#fb3, #fb3 15px,
#58a 0, #58a 30px);
这样可以实现任意角度,任意宽度条纹的背景。我们再也不需要算什么勾股定理了。
变更60°试试:
注意:该方法需要设置四个色标,所以要实现水平或者垂直条纹还是用上一种方法
同色系条纹
background: repeating-linear-gradient(30deg,
#79b, #79b 15px,
#58a 0, #58a 30px);
对于这种同一色系,不同色调组成的条纹,我们可以换一种实现方式,把最深的颜色指定为背景色,同时在背景色之上添加半透明白色条纹来得到浅色的条纹。
background: #58a;
background-image: repeating-linear-gradient(30deg,
hsla(0, 0%, 100%, .1), hsla(0, 0%, 100%, .1) 15px,
transparent 0, transparent 30px);
这样的好处就是可以变更背景颜色,达到实现不同颜色的同系条纹背景。
复杂的背景图案
通过组合对个渐变图案我们可以得到一些列神奇的背景
background: white;
background-image: linear-gradient(90deg,
rgba(200, 0, 0, 0.5) 50%, transparent 0),
linear-gradient(rgba(200, 0, 0, 0.5) 50%, transparent 0);
background-size: 30px 30px;
桌布效果
background: #58a;
background-image:
linear-gradient(90deg, white 1px, transparent 0),
linear-gradient(white 1px, transparent 0););
background-size: 30px 30px;
网格效果
background: #58a;
background-image:
linear-gradient(white 2px, transparent 0),
linear-gradient(90deg, white 2px, transparent 0),
linear-gradient(hsla(0,0%,100%,.3) 1px, transparent 0),
linear-gradient(90deg, hsla(0,0%,100%,.3) 1px, transparent 0);
background-size: 75px 75px, 75px 75px,
15px 15px, 15px 15px;
蓝图网格
background: #655;
background-image:
radial-gradient(tan 30%, transparent 0),
radial-gradient(tan 30%, transparent 0);
background-size: 30px 30px;
background-position: 0 0, 15px 15px;
波点效果
background: #eee;
background-image:
linear-gradient(45deg, #bbb 25%, transparent 0),
linear-gradient(45deg, transparent 75%, #bbb 0),
linear-gradient(45deg, #bbb 25%, transparent 0),
linear-gradient(45deg, transparent 75%, #bbb 0);
background-position: 0 0, 15px 15px, 15px 15px, 30px 30px;
background-size: 30px 30px;
棋盘效果
注意:遇到复杂的图案,还可以选择SVG的方式来实现。
更多css背景图案可以参见 http://bennettfeely.com/gradients
background: hsl(20, 40%, 90%);
background-image: linear-gradient(90deg, #fb3 11px, transparent 0),
linear-gradient(90deg, #ab4 23px, transparent 0),
linear-gradient(90deg, #655 41px, transparent 0);
background-size: 41px 100%, 61px 100%, 83px 100%;
伪随机背景图案
连续的图像边框信封边框
padding: 1em;
border: 1em solid transparent;
background:
linear-gradient(green, green) padding-box,
repeating-linear-gradient(-45deg,
red 0,red 12.5%,
transparent 0, transparent 25%,
#58a 0, #58a 37.5%,
transparent 0, transparent 50%) 0 / 5em 5em;
padding: 1em;
border: 1em solid transparent;
border-image: 16 repeating-linear-gradient(-45deg,
red 0, red 1em,
transparent 0, transparent 2em,
#58a 0, #58a 3em,
transparent 0, transparent 4em);
以上两种方式掘客实现这种信封式的边框
@keyframes ants {
to {
background-position: 100%;
}
}
.ant{
padding: 1em;
border: 1px solid transparent;
background: linear-gradient(green, green) padding-box,
repeating-linear-gradient(-45deg,
black 0, black 25%,
white 0, white 50%) 0 / .6em .6em;
animation: ants 12s linear infinite;}
实现PS选区出现的动画边框效果
padding:1em;
border-top: .2em solid transparent;
border-image: 100% 0 0 linear-gradient(90deg, currentColor 4em, transparent 0);
上边不完全边框效果
以上就是本文所有内容