背景与边框
1 半透明边框
我们的预期是给box
容器设置一个白色背景以及一个半透明的边框,但是box
的背景色会从它的半透明边框上面透上来
默认情况下,背景会延伸到边框所在的区域
<style>
.wrap {
height: 300px;
position: relative;
background: #409eff;
}
.box {
border: 10px solid hsla(0, 0%, 100%, .5);
background: white;
}
</style>
<body>
<div class="wrap">
<div class="box">
</div>
</div>
</body>
效果显示如下:
可以清晰的看到box
的背景色白色已经拓展到了border
上面,页面没有显示出半透明边框的效果
加入background-clip
属性
.box {
border: 10px solid hsla(0, 0%, 100%, .5);
background: white;
background-clip: padding-box;
}
效果如下:
可以清晰的看到,box
区域,显示出了半透明的border
边框,使用该属性,浏览器会用内边距的外沿把背景裁切掉
2 多重边框
box-shadow
方案
box-shadow
生成投影,其中第四个参数称作“扩张半径”,通过指定正值或复制,可以让投影的面积加大或者减小。
一个正值的扩张半径加上两个为零的偏移量以及为零的模糊值,得到的“投影”就像是一道实线边框,代码如下:
.wrap {
height: 600px;
position: relative;
display: flex;
justify-content: center;
align-items: center;
}
.box {
height: 300px;
width: 300px;
position: relative;
/* background: #409eff; */
background: yellowgreen;
box-shadow: 0 0 0 10px #655;
}
box-shadow
的属性值
/* x 偏移量 | y 偏移量 | 阴影模糊半径 | 阴影扩散半径 | 阴影颜色 */
box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.2);
效果如图:
此类效果,用border
同样可以实现,但是 box=shadow
的属性在于,它支持逗号分隔语法。我们可以创建任意数量的投影。因此,在上面的实力上再加上一道边框
代码如下:
.wrap {
height: 600px;
position: relative;
display: flex;
justify-content: center;
align-items: center;
}
.box {
height: 300px;
width: 300px;
position: relative;
/* background: #409eff; */
background: yellowgreen;
box-shadow: 0 0 0 10px #655, 0 0 0 15px deeppink;
}
效果如图:
box-shadow
是层层叠加的,第一层投影位于最顶层,以此类推,我们想要显示颜色为deeppink
的外框,需要指定扩张半径的值为15px,必须比第一层颜色#655
的外框再大5px
,以次类推,想要继续增加投影
background:yellowgreen;
box-shadow:0 0 0 10px #655,
0 0 0 15px deeppink,
0 2px 5px 15px rgba(0,0,0,.6);
多重投影可以解决大多数情境下的问题,但有以下注意事项:
- 投影的行为与边框不完全一致,因为投影不影响布局,也不会受到
box-sizing
属性的影响。但是仍然可以通过内边距或外边距(这取决于投影是内嵌的还是外扩的)进行模拟边框所需要占据的空间 - 以上方法创建出的假”边框“出现在元素的外圈,但是他们不会响应鼠标的点击事件(例如,鼠标的悬停或者点击)。如果该事件是必要的,那么可以在
box-shadow
属性上加上insert
关键字,促使投影绘制在元素的内圈。注意,此时需要增加额外的内边距来腾出足够的空间
outline
方案
某些情况下,两层边框即可满足需求,那么就可以先设置一层常规边框,再加上ouline
属性产生外层的边框。该种方式的优点:边框的样式十分的灵活,比起box-shadow
方案只能实现实线边框,使用ouline
可以实现虚线边框的效果。
代码实现:
.box {
height: 300px;
width: 300px;
position: relative;
background: yellowgreen;
border: 10px solid #655;
outline: 5px dashed deeppink;
}
outline特点:
- 只适用于双层“边框”的场景,无法接受用逗号分隔的多个值
- 边框不一定贴合
border-radius
属性产生的圆角。例如,元素是圆角的,但是它的描边可能仍旧是直角的。
3 灵活的背景定位
难题
场景:针对容器某个角对背景图片做偏移定位
例如,图片和容器的边角之间能留出一定的空隙(类似于内边距效果)。
对于有固定尺寸的容器来说,可以通过计算距离,使用固定值达到目的。但是容器的尺寸不固定时,这就无法做到了。
background-position
扩展语法方案
background-position
属性允许我们指定背景图片距离任意角的偏移量,只要在偏移量前面指定关键字。
例如,背景图片和右边缘保持20px的偏移量,同时和底部保持10px的偏移量
代码如下:
.box {
height: 300px;
width: 300px;
position: relative;
background: url(http://csssecrets.io/images/code-pirate.svg) no-repeat #58a;
background-position: right 20px bottom 10px;
}
效果如图:
background-origin
方案
background-position:top left
中top left
是以哪个为基准,每个元素都存在三个矩形框:border box(边框的外沿框)、padding box(内边距的外沿框)以及content box(内容区的外沿框)
默认情况下,background-position
属性是以 padding box
为准的,这样边框才能布遮住背景图片。
background-origin
可以改变基准,例如,background-origin:content-box
calc()
解决方案
将背景图片定位到距离底部10px,距离右侧20px,等价于一个100% -20px的水平偏移量,以及100% -10px的垂直偏移量。
background-position:calc(100% -20px) calc(100% -10px)
4 边框内圆角
场景
一个容器,内侧有圆角,但是边框的四个角在外部仍然保持直角的形状。
代码实现:
<style>
.something-meaningful {
background: #655;
padding: .8em;
}
.something-meaningful>div {
background: tan;
border-radius: .8em;
padding: 1em;
}
</style>
<body>
<div class="something-meaningful">
<div>
I have a nice subtle inner rounding,
don't I look pretty?
</div>
</div>
</body>
效果如图:
该方法可以实现上图效果,但是需要两个元素,那么,如何使用一个元素进行实现呢?
解决方案
使用ouline
属性和box-shadow
相结合的方式
代码如下:
.something-meaningful {
/* background: #655;
padding: .8em; */
background: tan;
border-radius: .8em;
padding: 1em;
box-shadow: 0 0 0 .6em #655;
outline: .6em solid #655;
}
注意
该种解决方案仅在IE浏览器内会得到预期效果
Chrome浏览器中无法实现边框内圆角
综上,不建议使用该种方式。
5 条纹背景
场景
使用css
创建条纹图案
解决方案
假设有一条垂直线性渐变,颜色变化如下
<style>
.box {
background: linear-gradient(#fb3, #58a);
width: 600px;
height: 800px;
}
</style>
<body>
<div class="box">
</div>
</body>
效果如图:
我们可以看到在最上面的一部分和下面的一部分是实色,中间部分才开始渐变
现在将渐变色拉近:
.box {
background: linear-gradient(#fb3 20%, #58a 80%);
width: 600px;
height: 800px;
}
效果如图
现在可以发现,上部的实色占比更大,渐变色的区域变小,接下来继续将两个色标拉近,渐变区域会变得更窄。
那么,如果把两个颜色重合,各占50%,会发生什么?
.box {
background: linear-gradient(#fb3 50%, #58a 50%);
width: 600px;
height: 800px;
}
我们发现,此时已经没有渐变的效果了,只有两块实色,分别占据一半。
渐变是一种通过代码生成的图像,所以可以对其设置背景图像的相关属性,例如,使用background-size
来进行调整尺寸
.box {
background: linear-gradient(#fb3 50%, #58a 50%);
background-size: 100% 30px;
width: 600px;
height: 800px;
}
我们发现,此时这两条条纹的高度都是15px.背景默认情况下会重复平铺,整个容器都充满了水平条纹。
此外,我们可以使用相同的方法创建不等宽的条纹,调整色块的位置。
.box {
background: linear-gradient(#fb3 30%, #58a 30%);
background-size: 100% 30px;
width: 600px;
height: 800px;
}
如果我们把第二个色块的位置值设置为0,那么会在前一个色块占比完成后,剩下的颜色会以前一个色块相同的占比完成背景颜色的填充
如果需要创建超过两种颜色的条纹,下面的代码可以实现:
.box {
background: linear-gradient(#fb3 33.3%,
#58a 0, #58a 66.6%, yellowgreen 0);
background-size: 100% 45px;
width: 600px;
height: 800px;
}
注意:第二个区域#58a
,设置为0是为了和前一个颜色#fb3
有相同的占比,设置为66.6%
是为了能和后面的颜色yellowgreen
平分,如果不设置第二个值,那么最后一个颜色yellowgreen
将会覆盖前一个颜色。
垂直条纹
垂直条纹和水平条纹的差别:需要在开头指定一个额外的参数确定渐变的方向
.box {
background: linear-gradient(to right,
/* 或 90deg */
#fb3 50%, #58a 0);
background-size: 30px 100%;
width: 600px;
height: 800px;
}
我们可以看到条纹是从左至右排列,设置了以宽度30px
,高度100%
的大小进行背景的填充。
斜向条纹
我们可以看到垂直条纹是可以通过设置角度得到的,如果我们将角度设置为倾斜,是否就可以得到斜向的条纹了?
.box {
background: linear-gradient(45deg, #fb3 50%, #58a 0);
background-size: 30px 30px;
width: 600px;
height: 800px;
}
设置一个正方形大小的背景填充,同时将其旋转45°
,我们得到如上图的实现效果。
观察上述结果,对比真正的斜向条纹实现,可以发现,正确的表现形式应该是一个方块内四个条纹,而不是两条。
联想上述的三色条纹设置,这一次需要设置两组重复的颜色,同时设置角度旋转
.box {
background: linear-gradient(45deg,
#fb3 25%, #58a 0, #58a 50%,
#fb3 0, #fb3 75%, #58a 0);
background-size: 30px 30px;
width: 600px;
height: 800px;
}
观察发现,这些斜向条纹比上面的条纹要细,这是因为我们指定的长度会直接决定直角三角形的斜边长度,但是条纹的宽度实际上是直角三角形的高
根据勾股定理以及直角三角形的特点,我们假设直角边为a,那么斜边的长度就是
(
a
2
+
a
2
)
=
2
a
\sqrt(a^2+a^2)=\sqrt2a
(a2+a2)=2a
因此,想要得到宽度为15px的条纹,background-size
的大小为:
15
2
∗
2
15\sqrt2*2
152∗2
代码做如下更改:
.box {
background: linear-gradient(45deg,
#fb3 25%, #58a 0, #58a 50%,
#fb3 0, #fb3 75%, #58a 0);
background-size: 42.426406871px 42.426406871px;
width: 600px;
height: 800px;
}
实现效果:
更好的斜向条纹
场景:更改条纹的角度,例如,将条纹的角度改为60或是30,此时如果只是更改渐变的角度,没有办法实现想要的效果
linear-gradient()
和radial-gradient()
各有一个支持循环的属性:repeating-linear-gradient()
和repeating-radial-gradient()
示例如下:
.box {
background: repeating-linear-gradient(45deg,
#fb3, #58a 30px);
width: 600px;
height: 800px;
}
效果如图:
可以看到,一个渐变团,可以通过自动重复,充满整个背景
例如,60°的条纹背景可简单实现:
.box {
background: repeating-linear-gradient(60deg,
#fb3, #fb3 15px, #58a 0, #58a 30px);
width: 600px;
height: 800px;
}
.box {
background: repeating-linear-gradient(45deg,
#fb3 0, #fb3 25%, #58a 0, #58a 50%);
background-size: 42.426406871px 42.426406871px;
width: 600px;
height: 800px;
}
灵活的同色系条纹
场景
多数情况下,我们想要的条纹图案不是由差异较大的几种颜色组成的,往往他们属于同一色系,只是在明度方面有着轻微的差异。
.box {
background: repeating-linear-gradient(30deg,
#79b, #79b 15px, #58a 0, #58a 30px);
width: 600px;
height: 800px;
}
可以看到,条纹的组成是由一个主色调和他的浅色变体组成的。但是代码中没有体现这种关系,如果改变了主色调,需要在代码中修改四处。
更好的实现方式:将最深的颜色设为背景色,同事将半透明白色的条纹叠加在背景色上面得到浅色条纹
.box {
background: #58a;
background-image: repeating-linear-gradient(30deg,
hsla(0, 0%, 100%, .1),
hsla(0, 0%, 100%, .1)15px,
transparent 0, transparent 30px);
width: 600px;
height: 800px;
}
6 复杂的背景图案
场景
如何创建简单常用的图案
网格
.box {
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;
width: 600px;
height: 800px;
}
重新复习一下linear-gradient
知识点
linear-gradient(red 10%, 30%, blue 90%);
默认情况下,从一个颜色的终止点平滑的过渡到另一个颜色的终止点,两个颜色之间的重点是两个颜色转换的中点。
但是这个转换的点可以平移,方法就是在两个颜色之间增加%,指示颜色的中转位置。
例如,上述的示例,从起点到10%是红色,从90%到结束是蓝色,在10%到90%之间是红色和蓝色的渐变色。
linear-gradient(90deg,rgba(200, 0, 0, .5)50%, transparent 0)
该代码的显示含义就是旋转90°,默认是从上到下的,顺时针旋转90°,变为从左至右,rgba(200, 0, 0, .5)
占据50%,剩下的由transparent
填充,
显示效果如下:
linear-gradient(rgba(200, 0, 0, .5)50%, transparent 0)
含义:从上到下,水平进行渐变
水平和垂直组合即可实现网格效果。
蓝图网格
.box {
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;
width: 600px;
height: 800px;
}
波点
网格属于线性渐变的生成的图案,但是还有一种径向渐变,用来创建原型、椭圆、或是他们当中的一部分。
圆点阵列
.box {
background: #655;
background-image: radial-gradient(tan 30%, transparent 0);
background-size: 30px 30px;
width: 600px;
height: 800px;
}
两层圆点,背景错开
.box {
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;
width: 600px;
height: 800px;
}
可以使用scss
增强代码的可维护性
@mixinpolka($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;
}
调用
@includepolka(30px,30%,#655,tan);
棋盘
直角三角形的实现方式
.box {
background: #eee;
background-image:
linear-gradient(45deg, #bbb 50%, transparent 0);
background-size: 30px 30px;
width: 600px;
height: 800px;
}
.box {
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;
width: 600px;
height: 800px;
}
通过两组重复的渐变就可以实现
使用预处理器简化代码:
@mixincheckerboard($size,$base,
$accent:rgba(0,0,0,.25)) {
background:$base;
background-image:
linear-gradient(45deg,
7 伪随机背景
场景
如何使用css
模仿随机性
示例
.box {
background: linear-gradient(90deg,
#fb3 15%, #655 0, #655 40%,
#ab4 0, #ab4 65%, hsl(20, 40%, 90%)0);
background-size: 80px 100%;
width: 600px;
height: 800px;
}
我们可以看到条纹仍旧是按照规律的间隔进行排列的,那么如何模仿随机排布
解决方案
1.把这组条纹从一个平面拆散为多个图层,一种颜色作为底色,另三种颜色作为条纹,再让条纹以不同的间隔进行重复平埔。
.box {
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%;
width: 600px;
height: 800px;
}
2.使用质数指定各组条纹的宽度
.box {
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%;
width: 600px;
height: 800px;
}
8 连续的图像边框
场景
如何将一个图片或是图案作为边框,而不是背景。
最简单的办法:使用两个HTML元素,一个元素用来把我们的图片设为背景,另一个元素用来存放内容,并设置纯白背景,覆盖在前面的元素上
<body>
<div class="something-meaningful">
<div>
我有一个边框
</div>
</div>
</body>
<style>
.something-meaningful {
background: url(http://csssecrets.io/images/stone-art.jpg);
background-size: cover;
padding: 1em;
}
.something-meaningful>div {
background: white;
padding: 1em;
}
</style>
但是为了寻找最优解,如何使用一个元素实现?
解决方案
在多重背景的最底层设置背景色,因此需要使用一道从白色过渡到白色的CSS渐变来模拟出纯白实色的背景
<div class="something-meaningful">
我有一个边框
</div>
.something-meaningful {
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
默认值是padding-box
,因此我们改变一下background-origin
属性设置为border-box
针对
background-origin
属性的演示可以参看这个网址https://www.w3school.com.cn/tiy/c.asp?f=css_background-origin
.something-meaningful {
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;
}
属性整合,减少代码量
.something-meaningful {
padding: 1em;
border: 1em solid transparent;
background:
linear-gradient(white, white)padding-box,
url(http://csssecrets.io/images/stone-art.jpg)border-box 0 /cover;
}
该技巧还可以用在渐变图案上,例如,生成老式信封样式的边框
.something-meaningful {
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
也可以实现
.something-meaningful {
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-slice
时,需要同时修改border-width
让他们进行互相的匹配 border-image-slice
属性不能使用em
做单位,只能将边框厚度指定为像素单位- 条纹的款大夫休要再位置信息中写好,因此每当修改条纹宽度时,需要修改四处
border-image搭配渐变图案。例如,制作一个顶部边框被裁剪的效果。
做法:border-image
属性加上一条由渐变生成的垂直条纹,写好裁切长度,粗细使用border-width
控制
.something-meaningful {
padding: 1em;
border-top: .2em solid transparent;
border-image: 100% 0 0 linear-gradient(90deg,
currentColor 4em,
transparent 0);
padding-top: 1em;
}
{
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-slice`时,需要同时修改`border-width`让他们进行互相的匹配
- `border-image-slice`属性不能使用`em`做单位,只能将边框厚度指定为像素单位
- 条纹的款大夫休要再位置信息中写好,因此每当修改条纹宽度时,需要修改四处
border-image搭配渐变图案。例如,制作一个顶部边框被裁剪的效果。
做法:`border-image`属性加上一条由渐变生成的垂直条纹,写好裁切长度,粗细使用`border-width`控制
.something-meaningful {
padding: 1em;
border-top: .2em solid transparent;
border-image: 100% 0 0 linear-gradient(90deg,
currentColor 4em,
transparent 0);
padding-top: 1em;
}
``
currentColor
可以根据color
属性的变化自动适应