今天学习了CSS中各种图形不同的绘制方法,利用radial-gradien和linear-gradient可以实现多种缺角造型,利用border-radius可以实现多种不同曲率圆角的组合。我们可以通过调节矩形各个角的曲率半径实现多种类圆造型。同时在图片的裁剪方面我们可以通过clip-path属性来指定图片裁剪路径。为了实现多种造型的阴影,我们需要用到css3中的滤镜filter:drop-shadow来实现阴影效果。网页中菱形与梯形的实现也是一个难点,我们可以通过元素的旋转来实现它。
- 通过指定曲率半径实现圆与类圆
Border-radius的语法如下:
border-radius: 1-4 length|% / 1-4 length|%;
其中length以具体数值定义曲率半径,%以百分比定义曲率半径,不同半径组合会构成不同形状的圆角,如下图:
当我们为border-radius属性赋值时,其对应的圆角如下图:
我们定义一大一小的半径构成一个椭圆圆角,CSS代码为:
border-radius: 100px / 75px
以此为据,我们可以通过调节半径实现1/2椭圆与1/4椭圆:
考虑半椭圆的四角上的曲率半径,可以分析得出第一个竖向半椭圆的top left,top right两角的横向半径占据总宽度的50%,纵向半径占据所有高度,于是写出CSS代码如下:
border-radius: 50% / 100% 100% 0 0;
同理分析,可得上图中横向半椭圆与1/4椭圆的绘图CSS代码分别为:
横向半椭圆:
border-radius: 100% 0 0 100% / 50%;
1/4椭圆:
border-radius: 100% 0 0 0;
通过对各角的调节,我们可以通过CSS自定义不同形状,这些DIY的形状可以使用在诸如按钮、导航栏等地方。下面便是一个应用的例子,定制了多种造型的按钮:
- 平行四边形的实现
在现代网页的设计中,我们往往会有平行四边形的需求,例如下图的导航栏:
用到了很多平行四边形的因素,但是原生CSS并不提供平行四边形的直接构造方法,我们当然可以通过transform: skewX(-45deg);来对原始图像进行拉伸,但是这会使得被包裹的文字同样变形,变成如下效果:
为了实现内容保持不变,通常我们使用嵌套元素再反向拉伸的方式,但这样会使得代码繁杂,且结构层的变更会变得及其不友好。
此时我们可以通过伪元素的方法来实现,因为伪元素并不包含内容,所以伪元素的变形不会影响到内容。我们把所有的样式,包括背景,边框应用到伪元素上,并让伪元素继承原始元素的宽高,同时将伪元素置于下层,代码如下:
.original{
position:relative;
/*其他样式定义*/
}
.original::before{
content: '';
position: absolute;z-index=-1;
top: 0; right: 0; bottom: 0; left: 0; }
在这之后,我们再对伪元素进行变形,就可达成上述效果:
.original {
position: relative;
/* 其他的文字颜色、内边距等样式…… */
}
.original::before {
content: ''; /* 用伪元素来生成一个矩形 */
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
z-index: -1;
background: #58a;
transform: skew(45deg);
}
- 多边形图片的实现
当我们拿到一张规矩的原图时,若要想将其裁剪成我们期望的形状,例如平行四边形、菱形、圆、类圆等我们可以通过专业的工具进行裁剪例如photoshop,当然这是费力不讨好的事情,因为图片的布局可能会修改微调,一旦图片仅通过物理手段修改其本身容易造成可维护性低下的缺点。
我们可以通过二中的变形方式来实现,将图片包裹在一层div中,对两者实现相反的变形,从而实现如下图的效果:
代码如下:
<div class="picture">
<img src="adam-catlace.jpg" alt="..." />
</div>
.picture {
width: 400px;
transform: rotate(45deg);
overflow: hidden;
}
.picture > img {
max-width: 100%;
transform: rotate(-45deg);
}
但是可以明显看出,这种方式有几个明显缺点,首先这种方式需要元素嵌套,使得html结构不简洁清晰,同时css代码中的两次相反旋转并不能完全实现菱形,我们还需要计算包裹div的宽高,过于繁杂。其次他的健壮性也不够好,当处理非正方形图像时,这种方法会出现问题。
为了解决这个问题,我们可以通过直接裁剪的方式,利用clip-path指定裁剪路径:
clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
效果如下图:
可以看出,效果很好。使用这种方式还有一个特点,他可以让图片参与动画,例如我们可以实现当滑过图片时扩展为完整图片:
img {
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%);
}
- 切角效果
当然上述的clip-path可以实现切角效果,但是当我们针对自己填充的背景时,可以有更好的方法。我们可以想想一块完整的背景,我们想要切一块缺角,如下图:
是否可以想成那块黑色的角,变成了透明色呢?如此一来,这背景就看起来缺了一个角,动手实现:
background: #58a;
background:
linear-gradient(-45deg, transparent 15px, #58a 0);
同样,我们也可以采用切割的方式:
clip-path:polygon(0 0,100% 0, 100% 85%, 85% 100%, 0 100%);