css揭秘 - 背景与边框

半透明边框

RGBA/HSLA颜色
H:Hue(色调)。0(或360)表示红色,120表示绿色,240表示蓝色,也可取其他数值来指定颜色。取值为:0 - 360
S:Saturation(饱和度)。取值为:0.0% - 100.0%
L:Lightness(亮度)。取值为:0.0% - 100.0%
A:Alpha透明度。取值0~1之间。

border: 10px solid hsla(0,0%,100%,0.5);
background: white;
background-clip: padding-box; // 浏览器会用内边距的外沿来把背景裁切掉

多重边框

box-shadow接受第四个参数(称作“扩张半径”),通过指定正值或负值,可以让投影面积加大或者减小。一个正值的扩张半径加上两个为零的偏移量以及为零的模糊值,得到的“投影”其实就像一道实现边框。

background: yellowgreen;
box-shadow: 0 0 0 10px #655;

不过 box-shadow 的好处在于, 它支持逗号分隔语法, 我们可以创建任意数量的投影。因此, 我们可以非常轻松地在上面的示例中再加上一道 deeppink 颜色的“边框”

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

注:box-shadow是层层叠加的,第一层投影位于最顶层,以此类推,因此需要按照此规律调整扩张半径。比如说, 在前面的代码中, 我们想在外圈再加一道 5px 的外框, 那就需要指定扩张半径的值15px(10px+5px)
加投影的box-shadow

background: yellowgreen;
box-shadow: 0 0 0 10px #655,
            0 0 0 15px deeppink,
            0 2px 5px 15px rgba(0,0,0,.6);

outline(描边)方案

background: yellowgreen;
border: 10px solid #655;
outline: 5px solid deeppink;

可以通过 outline-offset 属性来控制它跟元素边缘之间的间距, 这个属性甚至可以接受负值。只适用于双层“边框”的场景(若多层边框则使用box-shadow),边框不一定会贴合 border-radius 属性产生的圆角。

background: yellowgreen;
border: 10px solid #655;
border-radius: 10px;
outline: 1px dashed white;
outline-offset: -5px;

灵活的背景定位

background-position的扩展
允许指定背景图片距离任意角的偏移量,只要在偏移量前面指定关键字。跟右侧保持20px的偏移量同时跟底部保持10px的偏移量如下:

background: url(code-pirate.svg) no-repeat #58a;
background-position: right 20px bottom 10px;

回退方案

background: url(code-pirate.svg)
            no-repeat bottom right #58a;
background-position: right 20px bottom 10px;

background-origin方案
将background-origin设置为content-box,会使偏移量跟padding的值相同。若有不同的,可以配合background-position的扩展语法来设置额外的偏移量。

padding: 10px;
background: url("code-pirate.svg") no-repeat #58a bottom right; /* 或 100% 100% */
background-origin: content-box;

calc()方案
按照左上角思路来想,需要计算对左上角的偏移量,可以使用calc()计算相对于左上角的偏移量。

background: url("code-pirate.svg") no-repeat;
background-position: calc(100% - 20px) calc(100% - 10px);

注:请不要忘记在calc()函数内部的 - 和 + 运算符的两侧各加一个空白符,否则会产生解析错误!

边框内圆角

难题
一个容器,只在内侧有圆角,而边框或描边的四个角在外部仍然保持直角的形状。用两个元素可以实现此效果。

<div class="something-meaningful"><div>
    I have a nice subtle inner rounding,
    don't I look pretty?
</div></div>

.something-meaningful {
    background: #655;
    padding: .8em;
}
.something-meaningful > div {
    background: tan;
    border-radius: .8em;
    padding: 1em;
}

将box-shadow和outline结合使用,可以实现边框内圆角的效果。box-shadow的扩张半径要比描边的宽度值小,但同时又要比(根号2-1)r大(r表示border-radius)

background: tan;
border-radius: .8em;
padding: 1em;
box-shadow: 0 0 0 .6em #655;
outline: .6em solid #655;

条纹背景

横向条纹

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

垂直条纹

// to right 或者 90deg
background: linear-gradient(to right, #fb3 50%, #58a 0);
background-size: 30px 100%;

斜向条纹

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

更好的斜向条纹

background: repeating-linear-gradient(60deg,
                      #fb3, #fb3 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: #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: 50px 50px, 50px 50px,
                 10px 10px, 10px 10px;

波点

background: #655;
background-image: radial-gradient(tan 20%, transparent 0),
                  radial-gradient(tan 20%, transparent 0);
background-size: 30px 30px;
background-position: 0 0, 15px 15px;

波点的mixin代码 -- SCSS

@mixin polka($size, $dot, $base, $accent) { 
    background: $base;
    background-image:
    radial-gradient($accent $dot, transparent 0),
    radial-gradient($accent $dot, transparent 0);
    background-size: $size $size;
    background-position: 0 0, $size/2 $size/2;
}

// 调用
@include polka(30px, 30%, #655, tan);

棋盘

background: #eee;
background-image:
    linear-gradient(45deg,
        rgba(0,0,0,.25) 25%, transparent 0,
        transparent 75%, rgba(0,0,0,.25) 0),
    linear-gradient(45deg,
        rgba(0,0,0,.25) 25%, transparent 0,
        transparent 75%, rgba(0,0,0,.25) 0);
background-position: 0 0, 15px 15px;
background-size: 30px 30px;

棋盘的mixin代码 -- scss

@mixin checkerboard($size, $base,
            $accent: rgba(0,0,0,.25)) {
    background: $base;
    background-image:
        linear-gradient(45deg,
            $accent 25%, transparent 0,
            transparent 75%, $accent 0),
        linear-gradient(45deg,
            $accent 25%, transparent 0,
            transparent 75%, $accent 0);
    background-position: 0 0, $size $size,
    background-size: 2*$size 2*$size;
}
/* 调用时是这样的…… */
@include checkerboard(15px, #58a, tan);

棋盘的svg实现代码

<svg xmlns="http://www.w3.org/2000/svg"
    width="100" height="100" fill-opacity=".25" >
    <rect x="50" width="50" height="50" />
    <rect y="50" width="50" height="50" />
</svg>
<!-- 调用 -->
background: #eee url('data:image/svg+xml,\
            <svg xmlns="http://www.w3.org/2000/svg" \
            width="100" height="100" \
            fill-opacity=".25">\
            <rect x="50" width="50" height="50" /> \
            <rect y="50" width="50" height="50" /> \
            </svg>');
background-size: 30px 30px;

请注意,如果你出于可读性的考虑,需要把一句CSS代码打断为多行,只需要用反斜杠(\)来转义每行末尾的换行就可以了。

伪随机背景

解决方案

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 23px, transparent 0);
background-size: 83px 100%, 61px 100%, 41px 100%;

使用质数来指定各组条纹的宽度,增加各组条纹宽度的随机真实性。相对质数是一种数字之间的关系, 而不是单个数字自身的属性。 构成相对质数的这些数字没有公约数, 但它们自己是可以有多个约数的( 比如说, 10 和 27 是相对质数, 但它们都不是质数)。 很显然, 一个质数跟其他所有数字都可以构成相对质数。

连续的图像边框

border-image的工作原理
基本上就是九宫格伸缩法: 把图片切割成九块, 然后把它们应用到元素边框相应的边和角。
解决方案

padding: 1em;
border: 1em solid transparent;
background: linear-gradient(white, white),
    url(stone-art.jpg);
background-size: cover;
background-clip: padding-box, border-box;
background-origin: border-box;

合并简写为:

padding: 1em;
border: 1em solid transparent;
background:
    linear-gradient(white, white) padding-box,
    url(stone-art.jpg) border-box 0 / cover;

也适用于渐变图案,下面的可以实现一种老式信封样式的边框。

padding: 1em;
border: 1em solid transparent;
background: linear-gradient(white, white) 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;

也可以使用border-image来实现。

padding: 1em;
border: 16px 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);

不过 border-image 方法存在一些问题。

  • 每当我们改变 border-image-slice时,都需要同时修改borderwidth来让它们相互匹配。
  • 由于我们不能在 border-image-slice 属性中使用 em 单位, 只能把边框厚度指定为像素单位。
  • 条纹的宽度需要在色标的位置信息中写好,因此我们在改变条纹宽度时, 需要修改四处。

    蚂蚁行军效果
@keyframes ants { to { background-position: 100% } }
.marching-ants {
    padding: 1em;
    border: 1px solid transparent;
    background:
        linear-gradient(white, white) padding-box,
        repeating-linear-gradient(-45deg,
            black 0, black 25%, white 0, white 50%) 0 / .6em .6em;
    animation: ants 12s linear infinite;
}

顶部边框的裁切效果,用来模拟传统的脚注

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

推荐阅读更多精彩内容