[TOC]
背景知识:
rgba/hsla
,在rgb/hsl
的基础长增加了Alpha通道,用于设置颜色的不透明度(就是能透过多少背景)
-
rgba
接受四个数值,即rgba(red, green, blue,a)
,rgb
可以为数值(0 ~ 255),也可以为百分比(0 ~ 100%),a表示不透明度(0~1),1为完全不透明,0表示完全透明。rgba(0,255,0,1)
表示纯绿色,完全不透明rgba(100%,0,0,0.5)
表示纯红色,半透明 -
hsla(色相, 饱和度%, 亮度%,透明度),格式为hsla(0, 0%,0%,0) hsla的第一个值表示色相,也就是一个实际的颜色,比如红色或者绿色。所有的颜色绕色相环(色轮)一周,色相值以圆周上的度数表示。
红色是0或360,青色是180.以下是彩虹七色在色轮中的大致色相值。 红:0;橙:35;黄:60;绿:125;蓝:230;靛:280;紫:305;
-
饱和度设定有多少颜色,灰色的饱和度低,而强烈的色彩饱和度高
-
亮度设定颜色的明暗,0%就是黑色,100%就是白色
难题
设计一个带有半透明边框的容器,可能很多人会这样写
border: 10px solid hsla(0, 0%, 100%, 0.5);
background: white;
但是实际情况,半透明的边框并不会显现出来。在边框中使用半透明并没有想象中的那么容易
解决方案
出现这种情况是,背景会默认延伸到边框所在的区域下面。可以使用background-clip
属性来处理。
background-clip 设置元素的背景(背景图片或颜色)是否延伸到边框下面,有三个可选值,默认为border-box
-
border-box
背景延伸到边框外沿(但是在边框之下)。 -
padding-box
边框下面没有背景,即背景延伸到内边距外沿。 -
content-box
背景裁剪到内容区 (content-box) 外沿。
有了这个属性可以很快解决这个问题了
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,
0 0 0 15px deeppink,
0 2px 5px 15px rgba(0, 0, 0, .6)
- 第一个length参数设置水平偏移量,如果是负值则阴影位于元素左边;
- 第二个设置垂直偏移量,如果是负值则阴影位于元素上面。
- 第三个值越大,模糊面积越大,阴影就越大越淡。 不能为负值。
- 第四个取正值时,阴影扩大;取负值时,阴影.收缩
- 第五个参数为颜色
- 还有一个参数用来设置阴影位置,默认在边框外,在最前面设置inset让阴影在边框内
用border同样可以达到此效果,只不过更麻烦。用box-shadow通过逗号分隔可以创建任意数量的投影。
使用下面代码同样可以实现
background: yellowgreen;
border: 10px solid #655;
outline: 5px solid deeppink;
outline还可以有一个好处就是可以制作虚线边框,还可以通过outline-offset属性来控制它跟元素边缘之间的距离,接受负值。
background: black;
outline: 1px dashed white;
outline-offset: -10px;
以往针对容器某个角对背景图片做偏移定位的时候,一般是这样写
background-position:bottom right
或者使用百分比数值代替bottom和right,但是还有更好的方案
允许我们指定背景图片距离任意角的偏移量,只要在偏移量前面指定关键字
background: url(http://csssecrets.io/images/code-pirate.svg)
no-repeat bottom right #58a;
background-position: right 20px bottom 10px;
上面的代码表示背景图片跟右边缘保持20px,同时跟底部保持10px;background属性里面的设置用于回退。
此方案用于更好的解决背景图片偏移量和容器的内边距一样时的问题。
-
border-box 背景将会延伸到延伸到外边界的边框
-
padding-box 背景描绘在padding盒子,边框里不会有背景出现。同样,背景将会延伸到最外边界的padding.
-
content-box 背景描绘在内容区范围.
将background-origin
设置成content-box
即可
padding: 10px;
background: url(http://csssecrets.io/images/code-pirate.svg)
no-repeat bottom right #58a;
background-origin: content-box;
background-position: calc(100% - 20px) calc(100% - 10px)
这个效果按自己的思路都可以实现。我的第一反应也是使用两个元素实现。
<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;
}
当然这本书上肯定要讲述比较独特的方法实现。利用outline和box-shadow属性,只需写一个html属性即可
outline: .6em solid #655;
box-shadow: 0 0 0 .4em #655;
border-radius: .8em;
padding: 1em;
background: tan;
分析其原理:
- outline描边并不会跟着圆角走,当只是用outline的时候,圆角跟直角处有空隙
- box-shadow会跟着圆角走,当只是用box-shadow的时候没有直角
于是正好可以使用box-shadow来填充那部分空隙
背景知识: 线性渐变
linear-gradient
、background-size
background-size
设置背景图片大小,有多种写法- 使用关键字:
background-size: cover
,表示缩放背景图片以完全覆盖背景区,可能背景图片部分看不见。还有background-size: contain
,缩放背景图片以完全装入背景区,可能背景区部分空白。 - 使用一个值:
background-size: 3em
;这个值指定图片的宽度,图片的高度隐式的为auto,还可以使用百分比。 - 两个值:
background-size: 3em 25%
,第一个值指定图片的宽度,第二个值指定图片的高度。可为数值,可为百分比。 - 逗号分隔的多个值:设置多重背景
- 使用关键字:
尝试一个基本线性渐变
background: linear-gradient(#fb3, #58a);
最终效果是从上到下,第一个颜色渐变到第二个颜色
添加数值,指定被填充的区域
background: linear-gradient(#fb3 20%, #58a 80%);
可以看到渐变的区域变小了
把区域设为50%
background: linear-gradient(#fb3 50%, #58a 50%)
发现已经看不到渐变区域了,如果多个色标具有相同的位置,它们会产生一个无限小的过渡区域,过度的起止变化分别是第一个和最后一个指定值,从效果上看,颜色会在那突然变化,而不是一个平滑的过度。
那么知道这个就可以配合background-size
了
background: linear-gradient(#fb3 50%, #58a 50%);
background-size: 100% 30px;
我们把两条条纹的高度设置成15px,由于背景默认是平铺的,整个容器也被填满了。
还可以创建不等宽的条纹
background: linear-gradient(#fb3 30%, #58a 30%);
background-size: 100% 30px;
如果某个色标的位置值比整个列表中在它之前的色标的位置的值都要小,则该色标的位置值会被设置为它前面所有色标位置的最大值。所以利用这个特性,可以不用每次都修改两个数
background: linear-gradient(#fb3 30%, #58a 0);
background-size: 100% 30px;
创建超过两种颜色的条纹
background: linear-gradient(#fb3 33.3%, #58a 0, #58a 66.6%, yellowgreen 0);
background-size: 45px;
原理一样,稍微调整即可
background: linear-gradient(to right, #fb3 50%, #58a 0);
background-size: 30px 100%;
通过 to right
改变渐变的起始位置,也可以写成角度,这里可以写90deg
。
另外background-size
的数值也要调换
使用repeating-linear-gradient
快速构建
background: repeating-linear-gradient(45deg, #fb3, #58a 30px);
可以很方便的变换想要的图形
background: repeating-linear-gradient(60deg, #fb3, #fb3 15px, #58a 0, #58a 30px);
很多情况下,我们想要的条纹图案是由同一系色组成,只是在明暗方面有些差异。
background: repeating-linear-gradient(30deg, #79b, #79b 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);
这里把最深的颜色作为背景色,同时把半透明白色的条纹叠加在背景之上来得到浅色条纹。这样每次只要修改背景色就可以了。
背景知识:css渐变, "条纹背景"
把多个渐变图案组合起来,让它们透过彼此的透明区域显现时,就会得到意想不到的图案。
background: white;
background-image: linear-gradient(90deg, rgba(200,0,0,.5), 50%, transparent 0),
linear-gradient(rgba(200,0,0,.5) 50%, transparent 0);
background-size: 30px 30px;
有些时候我们希望网格中每个格子的大小可以调整,而网格线条的粗细同时保持固定。下面展示了使用长度而不是百分比作为色标的场景
background: #58a;
background-image: linear-gradient(white 1px, transparent 0),
linear-gradient(90deg, white 1px, transparent 0);
background-size: 30px 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: 75px 75px, 75px 75px,15px 15px, 15px 15px;
波点是利用径向渐变知识。下面是一个简单的径向渐变
background: #655;
background-image: radial-gradient(tan 30%, transparent 0);
background-size: 30px 30px;
这里的径向渐变由每个小方块的中心向四周渐变,也就是background-size
指定的大小。
下面是一种更加使用的图案:
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;
使用background-position
属性将两个背景位置错开,第一个值表示水平位置,第二个表示垂直位置,用逗号分隔设置多重。
因为为了达到效果,第二层背景的偏移定位值必须是平铺图案中的每个基本单元宽高的一半,每次修改要修改多处尺寸,可以使用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, #bbb 50%, transparent 0);
background-size: 30px 30px;
每个三角形占据每个单元的一般,修改色标位置为25%。
我们把色标的顺序反转,便可以创建相反方向的三角形了
background: #eee;
background-image: linear-gradient(45deg, transparent 75%, #bbb 0);
background-size: 30px 30px;
组合起来的图形
background: #eee;
background-image: linear-gradient(45deg, transparent 75%, #bbb 0),
linear-gradient(45deg, #bbb 25%, transparent 0);
background-size: 30px 30px;
现在只需要把第二层渐变在水平和垂直方向均移动每个单元的一半,就可以拼接起来。
background: #eee;
background-image: linear-gradient(45deg, #bbb 25%, transparent 0),
linear-gradient(45deg, transparent 75%, #bbb 0);
background-size: 30px 30px;
background-position: 0 0, 15px 15px;
产生出了一个正方形,本质上是棋盘的一半,复制一份再创建出另一组正方形。
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-size: 30px 30px;
background-position: 0 0, 15px 15px,15px 15px, 30px 30px;
代码进行优化,可以把这些处在单元顶角的三角形两两组合起来(即把第一组和第二组并为一层渐变,第三组和第四组为一层渐变)
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;
使用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: $size*2 $size*2;
}
@include checkerboard(15px, #58a, tan);
重复平铺的几何图案很美观,但是看起来和你呆板。用css实现图案的随机平铺。
background: linear-gradient(90deg, #fb3 15%, #655 0, #655 40%,
#ab4 0, #ab4 65%, hsl(20, 40%, 90%) 0);
background-size: 80px 100%;
上面通过background-size
来控制图案每隔80px重复一次。规律比较明显,并不是真实的随机平铺。
接下来,把这组条纹从一个平面拆散为多个层面:一种颜色作为底色,另外三种颜色作为条纹,然后再让条纹以不同的间隔进行重复平铺。在色标中定好边框的宽度,用background-siz
e来控制条纹的间距
background: hsl(20, 40%, 90%);
background-image:
linear-gradient(90deg, #fb3 10px, transparent 0),
linear-gradient(90deg, #ab4 20px, transparent 0),
linear-gradient(90deg, #655 20px, transparent 0);
background-size: 80px 100%, 60px 100%, 40px 100%;
但是这里还有一个问题,每隔240px还是会重复一次,红色箭头处。这里每次重复单元正好是background-size
的最小公倍数,而40、60、80的最小公倍数就是240。
根据这个逻辑,可以把每个重复单元的尺寸最大化,也就是最小公倍数最大化。为了让最小公倍数最大化,这些数字最好是相对质数(比如,10和27不是质数,但他们是相对质数,最小公倍数为10乘以27)。要达成相对质数,尽量选择质数,于是下面代码
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%;
再想让它重复,早就超出屏幕的分辨率了。
这个技巧被Alex Walker定名为“蝉原则”,通过质数来增加随机真实性。还可以用于其他涉及有规律重复的情况
- 在图片库中,为每幅图片用细微的伪随机旋转效果时,可以使用
:neth-child(a)
选择符,且让a
是质数。 - 如果要生成一个动画,而且让它看起来不是按照明显的规律在循环时,可以应用多个时长为质数的动画。
背景知识:css渐变、border-image、条纹背景、基本的css动画
border-image
:指定作为元素周围边框的图像。基本原理就是九宫格伸缩法,把图片切割成九块,然后把它们应用到边框相应的边和角。结合实例继续说明
有时候我们想把一幅图案或图片应用为边框,而不是背景。一个元素有一圈装饰性的边框,基本上就是一张图片被裁剪进了边框所在的方环区域,不仅如此,还希望这个元素的尺寸在扩大或缩小的时候,这幅图片都可以自动延伸并覆盖完整的边框区域。
最简单的办法就是使用连个HTML元素,一个元素用来把图片设为背景,另一个元素存放内容
<div class="something">
<div>I have a nice stone art border,
don't I look pertty?
</div>
</div>
.something {
background: url('http://csssecrets.io/images/stone-art.jpg');
background-size: cover;
padding: 1em;
}
.something > div {
background: white;
padding: 1em;
}
如何改进,使用一个元素?
思路:在背景图片之上,再叠加一层纯白的实色背景,为了让下层的图片背景透过边框区域显现出来,需要给两层背景指定不同的background-clip
值,最后一个要点在于,我们只能在多重背景的最底层设置背景色,因此需要一道从白色过渡到白色的css渐变来模拟纯白实色背景的效果
padding: 1em;
border: 1em solid transparent;
background: linear-gradient(white, white),
url('http://csssecrets.io/images/stone-art.jpg');
background-size: cover;
background-clip: padding-box, border-box;
发现效果很接近,但是边框的图片有一种怪异的拼接效果。原因是background-origin
的默认值是paddin-box
,因此,图片的显示尺寸不仅取决于padding box的尺寸,而且被放置在了padding box的原点(左上角)。我们看到的实际上就是背景图片以平铺的方式蔓延到border box区域的效果。修改即可
padding: 1em;
border: 1em solid transparent;
background: linear-gradient(white, white),
url('http://csssecrets.io/images/stone-art.jpg');
background-size: cover;
background-clip: padding-box, border-box;
background-origin:border-box;
简写属性
background:
linear-gradient(white, white) padding-box,
url('http://csssecrets.io/images/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;
上面例子可以很容易的通过background-size
属性来改变条纹的宽度,通过border属性来改变整个边框的厚度。还可以用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-source
:用在边框的图片的路径border-image-slice
:图片边框向内偏移border-image-width
:图片边框的宽度border-image-outset
:边框图像区域超出边框的量border-image-repeat
:图像边框是否应平铺(repeated)、铺满(rounded)或拉伸(stretched)
上面例子使用border-image实现,存在一些问题
- 每当我们改变
border-image-slice
时,都要同时修改border-width
来让它们匹配 - 由于不能在
border-image-slice
属性中使用em单位,只能把边框厚度指定为像素单位 - 条纹的宽度需要在色标的位置信息中写好。
制作蚂蚁行军边框
将边框的宽度减少至1px,修改条纹颜色,便可以出现虚线边框,然后background-size
改为某个合适的值。添加动画
@keyframes ants { to {background-position: 100%} }
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-image
也有它强大之处,尤其是在搭配渐变图案时。比如我们需要一个顶部边框被裁切的效果,就像一般的脚注一样。我们所需要的就是在border-image
属性再加上一条由渐变生成的垂直条纹,并把要裁剪的长度在渐变中写好,边框的粗细由border-width
来控制。
border-top: .15em solid transparent;
border-image: 100% 0 0 linear-gradient(90deg, currentColor 4em, transparent 0);
padding-top: .5em;
使用了currentColor
属性,会根据color属性的变化而自动适应(假设我们希望这条边框跟文字保持相同颜色)
correntColor:这是css3中一个颜色的关键字,这个关键字并没有绑定到一个固定的颜色,而是一直被解析为color。
假如我们想要所有水平割线自动与文本颜色保持一致。可以这么写
hr {
height: .5em;
background: currentColor;
}
很多已有的属性也具有类似的行为。如果你没有给边框指定颜色,它会自动从文本颜色那里得到颜色。