深入理解web前端前端开发

CSS之背景与边框

2016-06-26  本文已影响752人  hcxowe

所有图都在body背景设置为green下的截图,请不要把最外层的绿色当成边框

半透明边框

如果我们想给一个容器设置一层白色背景和一道半透明的白色边框,使容器后面的容器背景透上来,一般我们会这样子尝试:

border: 10px solid hsla(0, 0%, 100%, .5);background: white;

显示结果如下:


Paste_Image.png

你会发现边框不知道那里去了,这是为何,还有什么办法?

border: 10px solid hsla(0, 0%, 100%, .5);background: white;background-clip: padding-box;
Paste_Image.png

这样就达到我们预想的效果。
注:IE8以下需要使用滤镜来达到半透明效果,或者准备一张半透明的图片充当背景。

多重边框

如何实现多重边框,或许你会想到使用多个元素来模拟多重边框,不过这样子会需要额外的元素来实现,有没有其他办法叻?

解决方法-box-shadow

box-shadow即投影,通过设置两个偏移,一个模糊量值,一个扩张半径来控制投影。box-shadow: 0 0 0 10px #655 只设置一个10px的扩张半径来模拟边框:

Paste_Image.png

它支持逗号分隔,来创建多个投影,因此我们可以在加上一条边框:

background-color: yellowgreen;
box-shadow: 0 0 0 10px #655, 0 0 0 20px deeppink;

效果如下:

Paste_Image.png
box-shadow: 0 0 0 10px #655 inset,
              0 0 0 20px deeppink inset, 
              2px 2px 5px 5px rgba(0, 0, 0, 0.6);

效果如下:

Paste_Image.png

注意:投影是按照顺序层层叠加,第一层位于最顶层

解决方案二-outline

如果只需要实现二层边框,可以使用outline来实现,并且这种方法可以实现不同样式的边框,box-shadow只能实现实线边框,如果要实现虚线就不行了。

border: 10px solid #655;
outline:10px solid deeppink;

效果如下:

Paste_Image.png

通过设置outline-offset可以设置outline(描边)与border(边框)之间的间隔

border: 10px solid #655;
outline:10px solid deeppink;
outline-offset: 10px;
Paste_Image.png

注意:- outline方式只能实现双重边框,如果要实现多重只能选择box-shadow方式

Paste_Image.png

明显看到了边框与描边四角之间的空隙

灵活的背景定位

如何实现相对容器某个角对背景图片做偏移定位?
CSS2只能设置背景图片相对于左上角进行偏移或者固定在其他三个角,那如何让背景图片相对某个角留出一定的空隙叻?
CSS2要实现只能计算背景图片距离左上角的偏移来实现,如果容器尺寸不固定,这样的方法就失效了。

解决方法-background-position扩展

background: url(img/3_0.png) no-repeat #58a;
background-position: right 20px bottom 20px;

只需在偏移量之前设置指定关键字,效果如下:

Paste_Image.png

背景图距离右下各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;

效果如下:

Paste_Image.png

距离右下角20px,10px是padding值,10px是偏移量

解决方案-calc()方案

background: url(img/3_0.png) no-repeat #58a;
background-position: calc(100% - 20px) calc(100% - 20px);

效果如下:

Paste_Image.png

是不是跟上一个一样,不过这个是相对于padding外沿框的偏移
注意:calc函数内部的 - + 运算符左右都需要一个空格,否则是解析出错。

边框内圆角

想想如何实现一下效果:

Paste_Image.png

一个容器有内侧圆角,但是边框或者描边是直角

解决方法-多元素

<style>
.container{ 
    padding: 1em; background: red; 
} 
.container > div {
    padding: .8em; 
    background: tan; 
    border-radius: .4em; 
}
</style>
<div class='container'> 
    <div> </div>
</div>

效果如下:

Paste_Image.png

这个方法需要两个元素,是否可以通过一个元素实现叻?

解决方法-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;

效果如下:

Paste_Image.png

成功实现
考虑下阴影需要设置为多大才能刚好填充空隙叻?

由勾股定律得知阴影的扩张值应该为 (a^2 + b^2 开根)- 圆角圆心到边框的距离,当直角两边相等时,这个值为(2a^2开根)-a。

因为所以得出结论:要覆盖掉描边与边框之间的空隙,阴影的值需要大于某个值,如果圆角两边相等,这个值小于0.4, 为了好记,避免每次都需要计算,可以把这个值设定为圆角半径的一半。但是这个值不能没有上限,当值超过描边的宽度时候,就会出现以下情况:

border-radius: .8em;
box-shadow: 0 0 0 .5em #655;
outline: .4em solid #655;
Paste_Image.png

条纹背景

网页中我们经常使用条纹背景图案,通常我们的解决方法是创建一个单独的图片。但是它并不是最理想的,每次调整都需要图像编辑器来进行修改图片。如何使用CSS创建条纹背景叻?

解决方法-linear-gradient

水平条纹
background: linear-gradient(#fb3, #58a);
Paste_Image.png

可以看到实现的是一条垂直方向上的颜色渐变背景。通过调整色标来对渐变区域进行调整

background: linear-gradient(#fb3 30%, #58a 70%);
Paste_Image.png

可以看到背景只有中间40%的区域是渐变,上下两边各30%都是纯色。
如果把色标重合在一起也就是设置为50%,有何效果?

Paste_Image.png

没错,就是两条具大的条纹出现了.

渐变是由代码生成的图片,可以像对待图片一样对待渐变,通过设置background-size可调整渐变图案的尺寸

background: linear-gradient(#fb3 50%, #58a 50%);
background-size: 100% 30px;
Paste_Image.png

因为默认背景图案会进行平铺,所以得到了如上两色的条纹背景。如果想实现不等宽条纹,只需要调整色标的位置值

background: linear-gradient(#fb3 30%, #58a 30%);
background-size: 100% 30px;

如果一个色标值比之前设置的色标值都小,该色标值会设置成前面所有色标值中的最大值,所以可这样设置

background: linear-gradient(#fb3 30%, #58a 0);
background-size: 100% 30px;
Paste_Image.png

两种都将得到上图,因为后一种只需修改一个地方。所以也算是写代码的捷径吧。
此外还可以设置超过两种颜色的条纹,以三色为例

background: linear-gradient(#fb3 33.3%, #58a 0, #58a 66.6%, yellowgreen 0);
background-size: 100% 45px;

效果如下:

Paste_Image.png
垂直条纹

实现了水平条纹,垂直条纹如何实现叻?
垂直条纹只需要在开头添加一个额外的参数来指定渐变方向,默认值是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%;

效果如下:

Paste_Image.png
斜向条纹

实现了水平与垂直条纹,顺下想,如果实现一个斜向的条纹叻?
比如斜向45°
尝试如下实现方式:

background: linear-gradient(45deg, #fb3 50%, #58a 0);
background-size: 30px 30px;
Paste_Image.png

失败了,这样只是把背景图案中每个贴片旋转了45°,根据用图片实现斜向条纹的经验,我们需要在每个贴片中包含四条条纹才能做到无缝拼接,在次尝试如下方式:

background: linear-gradient(45deg, 
                            #fb3 25%, #58a 0, 
                            #58a 50%, #fb3 0, 
                            #fb3 75%, #58a 0);
background-size: 30px 30px;
Paste_Image.png

成功拼接成了斜向的条纹图案,不过变成四条条纹之后对应的每条条纹的宽度变窄了,如何才能扩大到指定宽度的条纹图案叻?
根据勾股定理,当设置背景尺寸为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;
Paste_Image.png

得到了如上背景,不过上面的方法得到的也只是近似为指定宽度的条纹。有没有更好的方法叻?

更好的斜向条纹

之前的斜向条纹只能在斜向45°,如果要实现其他角度的时候,之前的方法就显得不好了,其实linear-gradientradial-gradient还各有一个循环式加强版:repeating-linear-gradientrepeating-radial-gradient,加强版色标是无限循环重复的,直到填满整个背景。

background: repeating-linear-gradient(45deg, 
                                      #fb3, #fb3 15px,
                                      #58a 0, #58a 30px);
Paste_Image.png

这样可以实现任意角度,任意宽度条纹的背景。我们再也不需要算什么勾股定理了。
变更60°试试:

Paste_Image.png

注意:该方法需要设置四个色标,所以要实现水平或者垂直条纹还是用上一种方法

同色系条纹
background: repeating-linear-gradient(30deg, 
                                      #79b, #79b 15px, 
                                      #58a 0, #58a 30px);
Paste_Image.png

对于这种同一色系,不同色调组成的条纹,我们可以换一种实现方式,把最深的颜色指定为背景色,同时在背景色之上添加半透明白色条纹来得到浅色的条纹。

background: #58a;
background-image: repeating-linear-gradient(30deg, 
                                            hsla(0, 0%, 100%, .1), hsla(0, 0%, 100%, .1) 15px, 
                                            transparent 0, transparent 30px);
Paste_Image.png

这样的好处就是可以变更背景颜色,达到实现不同颜色的同系条纹背景。

复杂的背景图案

通过组合对个渐变图案我们可以得到一些列神奇的背景

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;
Paste_Image.png

桌布效果

background: #58a;
background-image: 
            linear-gradient(90deg, white 1px, transparent 0), 
            linear-gradient(white 1px, transparent 0););
background-size: 30px 30px;
Paste_Image.png

网格效果

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;
Paste_Image.png

蓝图网格

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;
Paste_Image.png

波点效果

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;
Paste_Image.png

棋盘效果
注意:遇到复杂的图案,还可以选择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%;
Paste_Image.png

伪随机背景图案

连续的图像边框信封边框

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;
Paste_Image.png
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);
Paste_Image.png

以上两种方式掘客实现这种信封式的边框

@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;}
Paste_Image.png

实现PS选区出现的动画边框效果

padding:1em;
border-top: .2em solid transparent;
border-image: 100% 0 0 linear-gradient(90deg, currentColor 4em, transparent 0);
Paste_Image.png

上边不完全边框效果

以上就是本文所有内容

上一篇下一篇

猜你喜欢

热点阅读