半透明边框
- 假设我们想给一个容器设置一层白色背景和一道半透明白色边框,body 的背景会从它的半透明边框透上来。我们最开始的尝试可能是这样的:
border: 10px solid hsla(0,0%,100%,.5);
background: white;
效果图发现边框不见了?
默认情况下,背景会延伸到边框所在的区域下层。我们可以通过 background-clip 属性来调整上述默认行为所带来的不便。这个属性的初始值是 border-box ,意味着背景会被元素的 border box(边框的外沿框)裁切掉。如果不希望背景侵入边框所在的范围,我们要做
的就是把它的值设为 padding-box ,这样浏览器就会用内边距的外沿来把背景裁切掉。
border: 10px solid hsla(0,0%,100%,.5);
background: white;
background-clip:padding-box;
得到我们想要的效果:
多重边框
box-shadow方案
background: yellowgreen;
box-shadow: 0 0 0 10px #655;
效果图:
这个效果完全可以用 border 属性来生成完全一
样的边框效果。不过 box-shadow 的好处在于,它支持逗号分隔语法,我们
可以创建任意数量的投影。因此,我们可以非常轻松地在上面的示例中再加
上一道 deeppink 颜色的“边框”
background: yellowgreen;
box-shadow: 0 0 0 10px #655, 0 0 0 15px deeppink;
注意:
- box-shadow 是层层叠加的,第一层投影位于最顶 层,依次类推。因此,你需要按此规律调整扩张半径。比如说,在前面的代 码中,我们想在外圈再加一道 5px 的外框,那就需要指定扩张半径的值为 15px ( 10px+5px );
- 投影的行为跟边框不完全一致,因为它不会影响布局,而且也不会 受到 box-sizing 属性的影响。不过,你还是可以通过内边距或外边 距(这取决于投影是内嵌和还是外扩的)来额外模拟出边框所需要 占据的空间;
- 上述方法所创建出的假“边框”出现在元素的外圈。它们并不会响 应鼠标事件,比如悬停或点击。如果这一点非常重要,你可以给 box-shadow 属性加上 inset 关键字,来使投影绘制在元素的内圈。 请注意,此时你需要增加额外的内边距来腾出足够的空隙;
outline 方案
在某些情况下,你可能只需要两层边框,那就可以先设置一层常规边框,再加上 outline (描边)属性来产生外层的边框。这种方法的一大优 点在于边框样式十分灵活,不像上面的 box-shadow 方案只能模拟实线边框(假设我们需要产生虚线边框效果, box-shadow 就没辙了)。如果要得到上图相同的效果,代码可以这样写:
background: yellowgreen;
border: 10px solid #655;
outline: 5px solid deeppink;
描边的另一个好处在于,你可以通过 outline-offset 属性来控制它跟元素边缘之间的间距,这个属性甚至可以接受负值。这对于某些效果来说非常有用。举个例子,下图就实现了简单的缝边效果
outline:pink dashed;
outline-offset:-15px;
注意:
- 它只适用于双层“边框”的场景,因为 outline 并不能接受用逗号分隔的多个值。如果我们需要获得更多层的边框,box-shadow就是我们唯一的选择了;
- 边框不一定会贴合 border-radius 属性产生的圆角,因此如果元素是圆角的,它的描边可能还是直角的,下图可见效果。请注意,这种行 为被 CSS 工作组认为是一个 bug,因此未来可能会改为贴合 border-radius 圆角;
- 根据 CSS 基本 UI 特性(第三版)规范(w3.org/TR/css3-ui )所述,“描边可以不是矩形”。尽管在绝大多数情况下,描边都是矩形的,但如果你想使用这个方法,请切记:最好在不同浏览器中完整地测试最终效果;
灵活的背景定位
background-position 的扩展语法方案
在 CSS 背景与边框(第三版)(w3.org/TR/css3-bac… )中,background-position 属性已经得到扩展,它允许我们指定背景图片距离任意角的偏移量,只要我们在偏移量前面指定关键字。举例来说,如果想让背景图片跟右边缘保持 20px 的偏移量,同时跟底边保持 10px 的偏移量,可以这样做:
background: url(code-pirate.svg) no-repeat #58a;
background-position: right 20px bottom 10px;
最后一步,我们还需要提供一个合适的回退方案。因为对上述方案来说,在不支持 background-position 扩展语法的浏览器中,背景图片会紧贴在左上角(背景图片的默认位置)。这看起来会很奇怪,而且它会干扰到文字的可读性。提供一个回退方案也很简单,就是把老套的
bottom right 定位值写进 background 的简写属性中:
background: url(./boy.png)no-repeat bottom right #58a;
background-position: right 20px bottom 10px;
background-origin 方案
在给背景图片设置距离某个角的偏移量时,有一种情况极其常见:偏移量与容器的内边距一致。如果采用上面提到的 background-position 的扩展语法方案,代码看起来会是这样的:
padding: 10px;
background: url(./boy.png) no-repeat #58a;
background-position: right 10px bottom 10px;
这种写法起作用了,但代码不够DRY:每次改动内边距的值时,我们都需要在三个地方更新这个值!有一个更简单的办法可以实现这个需求:让它自动地跟着我们设定的内边距走,不用另外声明偏移量的值。
在网页开发生涯中,你很可能多次写过类似 background-position:top left; 这样的代码。你是否曾经有过疑惑:这个 top left 到底是哪个左上角?你可能知道,每个元素身上都存在三个矩形框:border box(边框的外沿框)、padding box(内边距的外沿框)和 content box(内容区的外沿框)。那 background-position 这个属性指定的到底是哪个矩形框的左上角?默认情况下, background-position 是以 padding box 为准的,这样边框才不会遮住背景图片。因此, top left 默认指的是 padding box 的左上角。不过,在背景与边框(第三版)(w3.org/TR/css3-bac… )中,我们得到了一个新的属性 background-origin ,可以用它来改变这种行为。
在默认情况下,它的值是 padding-box 。如果把它的值改成 content-box ,我们在 background-position 属性中使用的边角关键字将会以内容区的边缘作为基准(也就是说,此时背景图片距离边角的偏移量就跟内边距保持一致了):
padding: 10px;
background: url("./boy.png") no-repeat #58a
bottom right; /* 或 100% 100% */
background-origin: content-box;
它的视觉效果跟上面完全一样的,但我们的代码变得更加 DRY了。另外别忘了,在必要时可以把这两种技巧组合起来!如果你想让偏
移量与内边距稍稍有些不同(比如稍微收敛或超出),那么可以在使用background-origin: content-box 的同时,再通过 background-position的扩展语法来设置这些额外的偏移量。
calc() 方案
让我们回顾一下本节开头的挑战:把背景图片定位到距离底边 10px 且距离右边 20px 的位置。如果我们仍然以左上角偏移的思路来考虑,其实就是希望它有一个 100% - 20px 的水平偏移量,以及 100% - 10px 的垂直偏移量。calc() 函数允许我们执行此类运算,它可以完美地在
background-position 属性中使用:
注意:calc中计算的符号左右一定要留空格
background: url("./boy.png") no-repeat #58a;
background-position:calc(100% - 20px) calc(100% - 10px);
边框内圆角
难题
有时我们需要一个容器,只在内侧有圆角,而边框或描边的四个角在外部仍然保持直角的形状,用两个元素可以实现这个效果,这并没有什么特别的:
<div id="container">
<div id="container1">
My name is anna
</div>
</div>
#container1{
background: tan;
border-radius: .8em;
padding: 1em;
height:200px;
}
#container{
width:200px;
margin:100px 100px;
background: #655;
padding: .8em;
}
这个方法很好,但要求我们使用两个元素,而我们只需要一个元素。有没有办法可以只用一个元素达成同样的效果呢?
解决办法
background: tan;
border-radius: .8em;
padding: 1em;
box-shadow: 0 0 0 .6em #655;
outline: .6em solid #655;
它产生的效果和上面用两个元素一样的。我们基本上受益于两个事实:描边并不会跟着元素的圆角走(因而显示出直角),但 box-shadow 却是会的。因此,如果我们把这两者叠加到一起, box-shadow 会刚好填补描边和容器圆角之间的空隙,这两者的组合达成了我们想要的效果。
条纹背景
水平条纹
background: linear-gradient(#fb3 33.3%,#58a 0, #58a 66.6%, yellowgreen 0);
background-size: 100% 45px;
垂直条纹
background: linear-gradient(to right,#fb3 33.3%,#58a 0, #58a 66.6%, yellowgreen 0);
background-size: 100% 45px;
斜向条纹
background: linear-gradient(45deg,
#fb3 25%, #58a 0, #58a 50%,
#fb3 0, #fb3 75%, #58a 0);
background-size: 30px 30px;
关注
- background-origin和background-clip的区别?