CSS之背景与边框

作者: hcxowe | 来源:发表于2016-06-26 21:20 被阅读752次

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

    半透明边框

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

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

    显示结果如下:


    Paste_Image.png

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

    • 原因:其实我们的边框是存在的,只是背景会侵透到边框,而上层我们设置的也是白色实线半透明边框,故看上去好像边框不见了,可以换个虚线边框加以验证:


      Paste_Image.png

      这个表现即是CSS2的背景工作原理,我们只能接受它。

    • 解决方法:好在CSSb3可以通过background-clip属性来调整背景范围,默认值为border-box,意味着背景会侵透到边框的外沿框,我们只要把值设置为padding-box,背景就会被内边距的外沿剪切掉

    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-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);
    

    效果如下:

    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方式

    • 如果通过border-radius设置了圆角,outline并不会贴这边框,还是直角的。
    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

    上边不完全边框效果

    以上就是本文所有内容

    相关文章

      网友评论

        本文标题:CSS之背景与边框

        本文链接:https://www.haomeiwen.com/subject/qcczdttx.html