CSS之背景与边框

所有图都在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

上边不完全边框效果

以上就是本文所有内容

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,311评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,339评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,671评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,252评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,253评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,031评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,340评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,973评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,466评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,937评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,039评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,701评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,254评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,259评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,497评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,786评论 2 345

推荐阅读更多精彩内容