第2章:背景与边框
1.半透明边框
- 背景知识:RGBA/HSLA颜色
-给一个容器设置白色背景和一道半透明白色边框,body的背景会从他的半透明框上透上去
background:white;
border: 10px solid hsla(0,0,100%,0.5)
结果却不是我们想要的。为什么呢
因为背景色渗透到边框下的区域了。需要更改一下默认值(默认是border-box)
background:white;
border: 10px solid hsla(0,0,100%,0.5);
background-clip:padding-box;
2. 多重边框
- box-shadow的基本用法
box-shadow方案
box-shadow方案还能接受第四个参数(称作扩张半径),通过指定正值或者负值,可以让投影面积加大或者减少。一个正确的扩展半径加上俩个为0的偏移量以及0 的模糊值,得到的投影其实就像是一道实线边框。
background:yellowgreen;
box-shadow:0 0 10px #655;
另外,他还支持逗号,我们可以创建任何数量的投影。
background:yellowgreen;
box-shadow:0 0 0 10px #655, 0 0 0 15px deeplink;
唯一需要注意的就是,box-shadow是层层叠加的,第一层投影位于顶层,以此类推。因此你需要按照这个规律来调整扩展半径。
-注意事项:
- 1:投影的行为跟边框不一致,因为他不会影响布局,而且也不会收到box-sizing的影响
- 2:上述方法创建的假的边框出现在元素的外圈。他们并不会响应鼠标事件,比如悬停或者点击。如果这一点非常重要,你可以给box-shadow属性加上inset关键字,来使投影绘制在元素的内圈,请注意,此时你需要增加额外的内边距来腾出足够的空隙。
3:outline方案
在某些情况下,你可能只需要两层边框,那就可以先设置一层常规边框,再加上outline(描边)属性来产生外层的边框。这种方式一大优点就是在于边框样式十分灵活,不像box-shadow只能模拟实现边距。(假如我们需要产生虚线边距效果,box-shadow就没辙了)如果想得到上图2-6的效果,代码可以这样写;
background:yellowgreen;
border: 10px solid #655;
outline: 5px solid deeppink;
描边的另外一个好处就是你可以通过outline-offset属性来控制他跟元素边缘之间的间距,这个属性甚至可以接受负值。
注意事项:
- 他只适用于双层边框的场景,因为outline并不能接受逗号分割的多个值,如果我们需要获取更多层的边框,前一种方案是我们唯一的选择。
- 边框不一定会贴合border-radius属性产生的圆角,如果此元素是圆角的,他的描边可能还是直角的(这种行为呗css工作组认为是一个bug,因此未来可能会改为贴合border-radius圆角)
- 根据css基本ui特性规范所述,“描边可以不是矩形”,但如果你想适应这个方法,请切记最好在不同浏览器中完整的测试最终效果。
3:灵活的背景定位
1: background-position的扩展语法方案
background-position已经得到扩展,它允许我们指定背景图片距离任意角的偏移量,只要我们在偏移量前面指定关键字。举个例子,如果想让背景图片跟右边距保持20px的偏移量,同时跟底边保持10px的偏移量,可以这样做。
background:url(code-priate.svg) no-repeat #58a;
background-pistion: right 20px bottom 10px;
但是,在不支持background-position扩展语法的浏览器中,背景图片会紧贴左上角,如图所示。
提供一个会退方案,就是把老套的bottom right 定位值写进background的简写属性中。
background: url(code-private.svg) no-repeat bottom right #58a;
background-position: right 20px bottom 10px;
2:background-origin方案
在给背景图片设置距离某个角的偏移量时候,有一种情况及其常见:偏移量与容器的内边距一致,如果采用上面提到的background-position的扩展语法方案,代码看起来是这样的:
padding: 10px;
background:url(code-private.svg) no-repeat #58a;
background-position: right 10px bottom 10px;
这样就可以看到,他虽然起作用了,但是代码不够DRY, 每次改动内边距的值时,我们都需要在其他三个地方更新这个值。
所以还有一个更简单的办法实现这个需求:
题外话---默认情况下,background-position是以padding box 为准的,这样边距才不会遮住背景图片,因此top left 默认指的就是padding box 的左上角。background-position属性默认值也是padding-box,如果把他的属性改为content-box,我们在background-postion属性中使用的边角关键字将会以内容区的边缘作为基准(也就是说,此时背景图片距离边角的偏移量就跟内边距保持一致了)
padding: 10px;
backgroung: url("code-private.svg") no-repeat #58a bottom right ; /*或100%100%*/
backgroung-origin: content-box;
他的效果同上。另外如果你想让偏移量与内边距稍微有些不同,那么可以使用background-origin: content-box的同时,再通过background-position的扩展语法来设置这些额外的偏移量
3: calc()方案
上述问题我们可以通过这个函数轻而易举的解决:
background:url('code-private.svg') no-repeat;
background-position: calc(100% - 20px) calc(100% - 10px)
注意:两边各有一个空白符
4: 边框内圆角
背景知识: box-shadow, outline“多重边框”
要实现如下效果,我们通常用两个元素来实现
但是我们如果只使用一个元素可以达到吗?
解决方案
background:tan;
border-radius: .8em;
padding: 1em;
box-shadow: 0 0 0 .6em #655;
outline: .6em solid #655;
5: 条纹背景
- 背景知识:css线性渐变,background-size
width:100px;
height:100px;
background: linear-gradient(#fb3 40%, #58a 80%);
效果如图:
如果两个距离过近甚至相等,渐变就会越来越小。直至没有。
例如
width:100px;
height:100px;
background: linear-gradient(#fb3 450%, #58a 50%);
i因为渐变是一种由代码生成的图像,所以我们可以像对待其他背景一样的方式对待他们,而且还可以通过background-size来调整他的尺寸。
background: linear-gradient(#fb3 50%, #58a 50%);
width: 100px;
height: 100px;
background-size: 100% 20px;
效果如下:
由于背景方式默认是重复的,所以效果如上图,如果要创建不等宽的条纹,只需要调整色标的位置值即可。
background: linear-gradient(#fb3 30%, #58a 30%);
width: 100px;
height: 100px;
background-size: 100% 30px;
效果图如下
注意:如果某个色标的位置值比整个列表中他之前的色标的位置值都要小,则该色标的位置值将会被设置为它前面所有色标的位置值的最大值。这意味着,如果我们把第二个色标的位置值设置为0,那它的位置就总会被浏览器调整为前一个色标的位置值,这个结果正是我们想要的。
background: linear-gradient(#fb3 30%, #58a 0);
width: 100px;
height: 100px;
background-size: 100% 30px;
效果如图:
如果要创建超过两种的条纹也是很容易的举例子
background: linear-gradient(#fb3 30%, #58a 0, #58a 66.6%, yellow 0);
width: 100px;
height: 100px;
background-size: 100% 30px;
如图:
垂直条纹
和水平条纹代码基本一致,差别在于我们需要在开头添加一个额外参数来指定渐变的方向。
background: linear-gradient(to right, #fb3 30%, #58a 0, #58a 66.6%, yellow 0);
width: 100px;
height: 100px;
background-size: 30px 100%;
效果如下:
斜向条纹
background: linear-gradient(45deg, #fb3 30%, #58a 0, #58a 66.6%, yellow 0);
width: 100px;
height: 100px;
background-size: 30px 30px;
结果如图,并不是我们想要的效果:
为什么,因为背景是重复的,相当于我们把每一个贴片的内部渐变旋转了45度,而不是把整个重复的背景都旋转了。
思考一下,一个小贴片中包含了四种颜色,如下图
只有这样才能做到无缝贴合。
因此代码需要更改为如下代码:
background: linear-gradient(45deg, #fb3 25%, #58a 0, #58a 50%, #fb3 0, #fb3 75%, #58a 0);
width: 100px;
height: 100px;
background-size: 30px 30px;
如图:
根据勾股定理,如果想要产生等宽的渐变效果,需要做如下计算
background: linear-gradient(45deg, #fb3 25%, #58a 0, #58a 50%, #fb3 0, #fb3 75%, #58a 0);
width: 100px;
height: 100px;
background-size: 42.42px 42.42px;
更好的斜向条纹
做一个对比,上述斜条纹可以通过如下代码进行实现
width: 100px;
height: 100px;
background-size: 42.42px 42.42px;
background: repeating-linear-gradient(45deg, #fb3 0, #fb3 14px, #58a 0, #58a 28px)
效果如下:
这种方式的好处就是修改颜色时候只需要修改两处而不是原来的三处,最大的好处就是可以随意指定角度了。需要注意的是,这里在创建双条纹时候,仍然需要指定四个色标值,意味着我们最好用前面的方法实现水平或者垂直条纹,而用这种方式来实现斜条纹。
灵活的同色系条纹
日常应用中,我们想要的条纹图案并不是由差异极大的几种颜色组成的,这些颜色往往属于同一个色系。只是在明度方面有着轻微的差异,这样在实际应用中对于这样的案例,可以通过代码体现出主色调和副色调之间的关系还可以在修改时候只用修改一处。代码如下
width: 100px;
height: 100px;
background-size: 42.42px 42.42px;
background: #58a;
background-image: repeating-linear-gradient(30deg, hsla(0, 0%, 100%, 0.1), hsla(0, 0%, 100%, 0.1) 14px, transparent 0, transparent 28px)
效果如下图:
6:复杂的背景图案,
- 渐变知识:css渐变,条纹背景
7:伪随机背景
8:连续的图像边框
9:自适应的椭圆
border-radius是用空格分开多个值,四个值是从左上角开始以顺时针顺序应用到元素的各个拐角。另外他也提供了完全不同的水平和垂直半径。通过斜扛 / 来区分的。
四分之一椭圆
- 无非就是一个角的水平和垂直半径都需要是100%,而其他三个角都不能设置为圆角。
border-radius: 100% 0 0 0 ;
10平行四边形
-背景知识:基本的CSS变形
margin: 0 auto;
width: 200px;
height: 200px;
background: #58a;
transform: skewX(45deg)
注意:这个属性对属性为行内的元素是不生效的,所以最好更改为其他的属性
你会发现,文本内容也发生变化了,显然这是我们不想要的,解决方法如下
1. 嵌套元素方案
- 我们可以对容器在进行一次反向的skew变形,从而抵消容器的变形效果。
2. 伪元素方案
另一种思路就是把所有的样式(背景,边框等)应用到伪元素上面,然后在对伪元素进行变形
.btn {
position: relative;
background: none;
border: none;
}
.btn::before {
content: '';
position: absolute;
background: #58a;
transform: skewX(45deg);
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: -1;
}
这个思路适用于其他任何样式,当我们想变形一个元素而不变形他的内容的时候就可以用到他。
11 菱形图片
基于变形的方案
<div class="outer">
<div class="inner">菱形文本</div>
</div>
.outer {
margin: 100px auto;
width: 100px;
height: 100px;
border: 1px solid green;
transform: rotate(45deg);
overflow: hidden;
}
.inner {
max-width: 100%;
height: 100%;
background: gray;
transform: rotate(-45deg);
line-height: 100px;
text-align: center;
}
效果如图:
但是我们想让图片的宽度于外框对角线的长度相等,而不是与边长相等。这里又要用到勾股定理了。边长 * 1.414。如果用sale放大1.414倍会更改合理,因为宽度变宽是以左上角为中心点,而scale等默认是以中心点进行缩放的,前者需要在变换位移,后者不用,所以代码改为如此,
.outer {
margin: 100px auto;
width: 100px;
height: 100px;
border: 1px solid green;
transform: rotate(45deg);
overflow: hidden;
}
.inner {
max-width: 100%;
height: 100%;
background: gray;
transform: rotate(-45deg) scale(1.42);
line-height: 100px;
text-align: center;
}
效果如下:
裁切路径方案
上述方法对图片宽高有要求,假如图片不符合要求,上述方案就会出现bug,可见这种方式是由一种hack处理方式------------不够简洁,不够直观,也不够健壮。
clip-path: polygon(...) // 多边形
<img class="img" src="https://upload.jianshu.io/admin_banners/web_images/4609/5c252cdb56c9924a035c052cf56753f096a1d6e8.jpg"
alt="">
.img {
width: 200px;
height: 200px;
clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%)
}
效果如图:
还可以参与动画实现
.img {
width: 200px;
height: 200px;
clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
transition: 1s clip-path;
}
.img:hover {
clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%)
}
12. 切角效果
解决方案
- css背景渐变
.third {
width: 100px;
height: 100px;
background: #58a;
background: linear-gradient(-45deg, transparent 15px, #58a 0);
margin: 0 auto;
}
效果如图:
如果想要两个角被切掉的效果,最初的想法是这样的
.third {
width: 100px;
height: 100px;
background: #58a;
background: linear-gradient(-45deg, transparent 15px, #58a 0), linear-gradient(45deg transparent 15px, #655, 0);
margin: 0 auto;
}
发现行不通,原因:默认情况下,这两层渐变都会调填满整个元素,因此他们会相互覆盖。需要让他们都缩小一半,于时我们用background-size来让每个渐变只占元素背景的一般
弧形切角
13 梯形标签页
生成梯形
.thirteen {
transform: perspective(.5rem) rotateX(5deg);
width: 100px;
height: 100px;
margin: 0 auto;
background: #58a;
}
效果如下
由于这里我们是对整个元素进行3d变形的,因此上面的文字也是变形的。并且对元素采用3d变形以后,元素的内部变形是“不可逆转”的。所以我们可以采用利用伪类的方式来实现生成梯形。有些类似于上面的平行四边形。
.thirteen {
position: relative;
color: white;
padding: 0.5em 1em .35em;
display: inline-block;
}
.thirteen::before {
content: '';
background: #58a;
top: 0;
right: 0;
left: 0;
bottom: 0;
z-index: -1;
position: absolute;
transform: perspective(.5rem) rotateX(5deg);
}
效果如图
这样可以实现,但是有一个问题,如果我们没有设置transform-origin的属性时候,应用变形效果会让这个元素以自身的中心线为轴进行空间上的旋转。因此,元素投射到2d屏幕上的尺寸会发生多种变化。
。。。。
14简单的饼图
1:基于transform的解决方案
- 这个方案在结构上是最佳解决方法:它只需要一个元素作为选择器,而其他部分由伪元素/变形元素/和css渐变来实现。