【CSS揭秘】(二)形状

337 阅读5分钟

形状

  1. 自适应的椭圆
  2. 平行四边形
  3. 菱形图片
  4. 切角效果
  5. 梯形标签页
  6. 简单的饼图

1 自适应的椭圆

问题描述

使用border-radius实现不同的椭圆以及自适应的椭圆

  • border-radius:左上 右上 右下 左下
  • border-radius:左上 右上&左下 右下
  • border-radius:左上&右下 右上&左下
  • border-radius:四角
  • border-radius:水平半径 / 垂直半径 使用/分隔的前后值的数量对应关系都会按照上面的规则赋值给四个角

设置单个角时可以有两个值,一个水平半径,一个垂直半径,两个角

解决方案

css

.item1 {
    border-radius: 50%;
}
.item2 {
    border-radius: 50% 0 0 0;
}
.item3 {
    border-radius: 100% 0 0 0 / 100% 0 0 0;
}
.item4 {
    border-radius: 100% 0 0 100%/ 50%;
}

效果

image.png

其他形状

.item1 {
    border-radius: 20% / 50%;
}
.item2 {
    border-radius: 40% 0/100% 0;
}
.item3 {
    border-radius: 0 40% / 0 100%;
}
.item4 {
    border-radius: 10%/ 90% 90% 10% 10%;
}

image.png

2 平行四边形

问题描述

使用skew()可以实现元素的斜向拉伸,但是元素里的内容也会同时被拉伸

一个解决方案是嵌套一个元素,父元素拉伸后,子元素再反向拉伸,但是我们更希望不添加额外的HTML元素来实现这个效果

解决方案

使用伪元素生成矩形后拉伸,再将层级置于底部

css

.item1 {
    background: #58a;
    transform: skewX(-45deg);
}
.item2 {
    position: relative;
}
.item2::before {
    content: '';
    position: absolute;
    top: 0;right: 0;bottom: 0;left: 0;
    background: #58a;
}
.item3 {
    position: relative;
}
.item3::before {
    content: '';
    position: absolute;
    top: 0;right: 0;bottom: 0;left: 0;
    background: #58a;
    z-index: -1;
    transform: skewX(-45deg);
}

效果

image.png

3 菱形图片

问题描述

把图片裁剪成菱形

基于变形的方案

父元素变形后子元素的图片再逆向变形

css

.item1 {
    transform: rotate(45deg);
    overflow: hidden;
}
.item1 > img {
    max-width: 100%;
    transform: rotate(-45deg);
}

.item2 {
    transform: rotate(45deg);
    overflow: hidden;
}
.item2 > img {
    max-width: 142%;
    transform: rotate(-45deg);
}

.item3 {
    transform: rotate(45deg);
    overflow: hidden;
}
.item3 > img {
    max-width: 100%;
    transform: rotate(-45deg) scale(1.42);
}

效果

image.png

子元素宽度的百分比是跟随父元素的,想要使其不显示出被裁剪的效果,需要按比例去设置它的宽度。 可以在变形中设置scale

裁剪路径的方案

裁剪路径:clip-path:polygon()

css

.item1 {
    transform: rotate(45deg) ;
    overflow: hidden;
}
.item1 > img {
    max-width: 100%;
    transform: rotate(-45deg) scale(1.42);
}

.item2 {
    background: url(./img.png) center center / cover;
    clip-path: polygon(50% 0, 100% 50%,50% 100%,0 50%);
}

.item3 {
    background: url(./img.png) center center / cover;
    clip-path: polygon(50% 0, 100% 50%,50% 100%,0 50%);
    transition: 1s clip-path;
}
.item3:hover {
    clip-path: polygon(0 0,100% 0,100% 100%,0 100%);
}

效果

bandicam 2021-09-25 17-28-09-295[00-00-01--00-00-08].gif

如果父元素不是正方形,使用旋转的变形是不能得到菱形的,并且子元素的宽度也不易计算,如果使用拉伸,子元素还需要反拉伸

使用clip-path:ploygon()去裁剪元素,可以轻易的得到一个菱形,并且只需要一个元素

因为原背景就是平铺在元素上的,可以添加动画,在鼠标移入的时候过渡到未裁剪的样式,可以是不同的样式转换,从圆形到正方形或者其他

4 切角效果

问题描述

实现元素的切角效果

基于渐变的方案

css

.item1 {
   background: linear-gradient(-45deg,transparent 30px,#58a 0);
}
.item2 {
    background: 
        linear-gradient(-45deg,transparent 30px ,#58a 0) right,
        linear-gradient(45deg,transparent 30px ,#655 0) left;
    background-size: 50% 100%;
    background-repeat: no-repeat;
}
.item3 {
    background: 
        linear-gradient(135deg,transparent 30px ,#58a 0) top left,
        linear-gradient(-135deg,transparent 30px ,#655 0) top right,
        linear-gradient(-45deg,transparent 30px ,#58a 0) bottom right,
        linear-gradient(45deg,transparent 30px ,#655 0) bottom left;
    background-size: 50% 50%;
    background-repeat: no-repeat;
}
.item4 {
    border-radius: 10px;
    background: 
        linear-gradient(-135deg,transparent 25% ,#58a 0) top right,
        linear-gradient(-45deg,transparent 25% ,#58a 0) bottom right;
    background-size: 100% 50%;
    background-repeat: no-repeat;
}

效果

image.png

使用线性渐变从透明到实色的块进行拼接,可以实现四个角的裁剪,最后的箭头形状很实用。也可以使用其他渐变方式实现不同的裁剪效果。

但是渐变的方式代码量较大,不是所有浏览器都支持

SVG与border-image方案

使用border-image,通过内联SVG图像来产生切角的效果

css

.item1 {
    border: 20px solid transparent;
    border-image: 1 url('data:image/svg+xml,\
        <svg xmlns="http://www.w3.org/2000/svg"\
            width="3" height="3" fill="%2358a">\
        <polygon points="0,1 1,0 2,0 3,1 3,2 2,3 1,3 0 ,2" />\
        </svg>');
}
.item2 {
    border: 20px solid #58a;
    border-image: 1 url('data:image/svg+xml,\
        <svg xmlns="http://www.w3.org/2000/svg"\
            width="3" height="3" fill="%2358a">\
        <polygon points="0,1 1,0 2,0 3,1 3,2 2,3 1,3 0 ,2" />\
        </svg>');
    background: #58a;
    background-clip: padding-box;
}

效果

image.png

该方法需要边框与背景一致,当背景是条纹或图片时就不易实现切角的效果

裁切路径的方案

css

.item1 {
    background: #58a;
    clip-path: polygon(
        50px 0,calc(100% - 50px) 0,
        100% 50px,100% calc(100% - 50px),
        calc(100% - 50px) 100%,50px 100%,
        0 calc(100% - 50px),0 50px
    );
}

效果

image.png

路径裁切的方式能够解决边框与背景不同的问题,不过在修改时需要修改多个值,建议使用预编译。如果padding值较小容易切到内容。

corner-shape的提案能直接裁剪边角,目前浏览器还不支持

5 梯形标签页

问题描述

一般的梯形实现可使用伪元素的方式,一前一后,但是在给梯形添加其他效果时就很麻烦,并且消耗了元素的两个伪元素

解决方案

css

.item1 {
    position: relative;
}
.item1::before{
    content: '';
    position: absolute;
    top: 0;right: 0;left: 0;bottom: 0;
    z-index: -1;
    background: #58a;
    transform: perspective(1em) rotateX(5deg);
}
.item2 {
    position: relative;
}
.item2::before{
    content: '';
    position: absolute;
    top: 0;right: 0;left: 0;bottom: 0;
    z-index: -1;
    background: #58a;
    transform: perspective(1em) rotateX(5deg);
    transform-origin: bottom ;
}
.item3 {
    position: relative;
}
.item3::before{
    content: '';
    position: absolute;
    top: 0;right: 0;left: 0;bottom: 0;
    z-index: -1;
    background-image: linear-gradient(#e66465,#9198e5);
    border: 5px solid #9198e5;
    border-radius: 1em 1em 0 0;
    transform: perspective(1em) rotateX(5deg);
    transform-origin: bottom left;
}

效果

image.png

如果不设置transform-origin,旋转后的图像的大小会有变化,可以用该属性固定一个或两个边

使用这种方式可以直接统一的设置背景、边框这些效果,要比拼接的方式更方便

饼图后续更新...