CSS 知识总结分享—— 踩坑记录——关于CSS切角的实现与踩坑解决(clip-path)

12 阅读8分钟

CSS 知识总结分享—— 踩坑记录——关于CSS切角的实现与踩坑解决(clip-path)

前言

记录目的:首先是懒得去死记硬背那又破又长的概念!能CV就CV~~~哈哈哈,当然为了当个合格的程序员还是得抱着深入理解的心态去研究一下的 @_@ 注:作者本人也还是在不断学习中~若有错误记录勿喷,或有更好的解决方案,欢迎评论留言或私信互相学习一下~ 话不多说,直接上代码! 开始对clip-path的理解并不是很深入,在我的知识领域内我只知道clip-path的使用作用之一是可以实现css切角 ! 所以就~


clip-path 切角使用基本使用模板

所以就直接上不同效果的案例吧: 使用模板对应效果: 在这里插入图片描述 对应代码效果:

/* 左上角切角 */
.item.top-left {
    clip-path: polygon(25px 0, 100% 0, 100% 0, 100% 100%, 100% 100%, 0 100%, 0 calc(100% - 25px), 0 25px);
}
/* 右上角切角 */
.item.top-right {
    clip-path: polygon(0 0, calc(100% - 25px) 0, 100% 25px, 100% 100%, 0% 100%, 0 100%, 0 0);
}
/* 右下角切角 */
.item.bottom-right {
    clip-path: polygon(0 0, 100% 0, 100% 25px, 100% calc(100% - 25px), calc(100% - 25px) 100%, 0 100%, 0 100%, 0 0);
}
/* 左下角切角 */
.item.bottom-left {
    clip-path: polygon(0 0,100% 0,100% 0,100% 100%,25px 100%,0 calc(100% - 25px),0 0);
}
/* 左上-右下角对切角 */
.item.top-left-to-bottom-right {
    clip-path: polygon(25px 0, 100% 0, 100% 25px, 100% calc(100% - 25px), calc(100% - 25px) 100%, 0 100%, 0 calc(100% - 25px), 0 25px);
}
/* 右上-左下角对切角 */
.top-right-to-bottom-left {
    clip-path: polygon(0 0,calc(100% - 25px) 0,100% 25px,100% 100%,25px 100%,0 calc(100% - 25px),0 0);
}

这就结束了?开玩笑像我这么”优秀“怎会没遇到几个坑呢 请看VC......R, 像我这么”优秀“的还会遇到什么坑呢?咳咳,请继续看下文


实战踩坑记录

实现需求:不想切图,使用图片背景去实现,使用css切角 ,同时能减少客户端对背景图片素材的性能加载负担

使用时所遇问题:

1. ==元素使用clip-path实现切角时会把其子元素里超出的部分一同切掉。== ——》 ==对应的预期效果:切角同时,元素内的子元素超出的内容也能正常显示==

在这里插入图片描述

解决思路:切角不写在元素本身上,用元素的伪类去实现:首先先清除元素原来的切角、背景色效果,添加个超出显示的属性 overflow: visible ,让伪元素来替代元素本身来实现切角和背景色效果

案例代码

/* 切角+子元素超出内容正常显示 */
.item.overflow-true {
    clip-path: none;
    overflow: visible;
    position: relative;
    background: none;
}

.item.overflow-true::before {
    content: '';
    display: block;
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: #4030a9;
    clip-path: polygon(25px 0, 100% 0, 100% 0, 100% 100%, 100% 100%, 0 100%, 0 calc(100% - 25px), 0 25px);
}

常用场景:该形式常使用在侧边栏hover事件弹窗浮窗 在这里插入图片描述


2. ==元素使用clip-path实现切角时,若元素带border边线效果也会一同切掉。== ———》 ==对应预期效果是,切角的同时,border边线能沿着切角的路径保留显示。==

在这里插入图片描述

解决问题思路:首先清楚元素本身的背景色和border属性,分别使用元素伪类before和after并使用绝对定位来替代元素本身来实现切角、背景色、border等效果。元素的border无非就是比元素本事的上下左右各多个的border-width那部分嘛,利用伪类before和after自带的优先级属性,让before的width和height超出的部分来实现border部分效果,再使用after盖在before上面去实现实元素本身的width、height、background等效果了,最后伪类before和after同时添加切角效果即可......这里注意给元素的子元素添加优先级,否则内容会被伪类after遮盖住了。

案例代码:

/* 切角+子元素border正常显示 */
.item.border-false {
    border: 1px solid pink;
}

.item.border-true {
    clip-path: none;
    border: none;
    background: none;
}

/* 切角用元素的伪类来实现 */
.item.border-true:before,
.item.border-true:after {
    content: '';
    display: block;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    clip-path: polygon(25px 0, 100% 0, 100% 0, 100% 100%, 100% 100%, 0 100%, 0 calc(100% - 25px), 0 25px);
}

/* 这里使用元素伪类 before 代替显示元素的border */
.item.border-true:before {
    width: calc(100% + 2px);
    height: calc(100% + 2px);
    background: pink;
}

/* 这里使用元素伪类 after 来代替显示元素的元素本身的背景色 */
.item.border-true:after {
    width: 100%;
    height: 100%;
    background: #4030a9;
}

/* 使用伪类实现切角时要注意给元素的子元素添加优先级显示 */
.item.border-true .item-inner {
    z-index: 5;
}

官方定义

clip-path的概念理解:

属性定义及使用说明:clip-path 属性使用裁剪方式创建元素的可显示区域。区域内的部分显示,区域外的隐藏。可以指定一些特定形状。

语法

clip: clip-source|basic-shape|margin-box|border-box|padding-box|content-box|fill-box|stroke-box|view-box|none|initial|inherit;

属性值

描述
clip-source用 URL 表示剪切元素的路径
basic-shape将元素裁剪为基本形状:圆形、椭圆形、多边形或插图
margin-box使用外边距框作为引用框
border-box使用边框作为引用框
padding-box使用内边距框作为引用框
content-box使用内容框作为引用框
fill-box使用对象边界框作为引用框
stroke-box使用笔触边界框(stroke bounding box)作为引用框
view-box使用最近的 SVG 视口(viewport)作为引用框。
none这是默认设置。 没有剪辑
initial设置属性为默认值。
inherit属性值从父元素继承。

完整案例源码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>关于CSS切角的实现与踩坑解决(clip-path)</title>
</head>
<style>
    .content {
        display: block;
        position: relative;
        width: 100%;
        height: auto;
        min-height: 100vh;
    }

    .list {
        display: flex;
        flex-wrap: wrap;
        justify-content: center;
        position: relative;
        width: 1200px;
        height: auto;
        padding: 100px 50px;
        background: gray;
        margin: 0 auto;
    }

    .item {
        display: flex;
        align-items: center;
        justify-content: center;
        position: relative;
        box-sizing: border-box;
        width: 200px;
        height: 300px;
        /* border: 1px solid pink; */
        background: #4030a9;
        margin: 0 50px 50px 0;
    }

    /* 左上角切角 */
    .item.top-left {
        clip-path: polygon(25px 0, 100% 0, 100% 0, 100% 100%, 100% 100%, 0 100%, 0 calc(100% - 25px), 0 25px);
    }

    /* 右上角切角 */
    .item.top-right {
        clip-path: polygon(0 0, calc(100% - 25px) 0, 100% 25px, 100% 100%, 0% 100%, 0 100%, 0 0);
    }

    /* 右下角切角 */
    .item.bottom-right {
        clip-path: polygon(0 0, 100% 0, 100% 25px, 100% calc(100% - 25px), calc(100% - 25px) 100%, 0 100%, 0 100%, 0 0);
    }

    /* 左下角切角 */
    .item.bottom-left {
        clip-path: polygon(0 0, 100% 0, 100% 0, 100% 100%, 25px 100%, 0 calc(100% - 25px), 0 0);
    }

    /* 左上-右下角对切角 */
    .item.top-left-to-bottom-right {
        clip-path: polygon(25px 0, 100% 0, 100% 25px, 100% calc(100% - 25px), calc(100% - 25px) 100%, 0 100%, 0 calc(100% - 25px), 0 25px);
    }

    /* 右上-左下角对切角 */
    .top-right-to-bottom-left {
        clip-path: polygon(0 0, calc(100% - 25px) 0, 100% 25px, 100% 100%, 25px 100%, 0 calc(100% - 25px), 0 0);
    }

    .item-inner {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 240px;
        height: 50%;
        font-size: 18px;
        font-weight: bold;
        text-align: center;
        color: #000;
        background: #fff;
    }

    .item.overflow-false .item-inner,
    .item.border-false .item-inner {
        color: #f00;
    }

    .item.overflow-true .item-inner,
    .item.border-true .item-inner {
        color: #080;
    }

    /* 切角+子元素超出内容正常显示 */
    .item.overflow-true {
        clip-path: none;
        overflow: visible;
        position: relative;
        background: none;
    }

    .item.overflow-true::before {
        content: '';
        display: block;
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background: #4030a9;
        clip-path: polygon(25px 0, 100% 0, 100% 0, 100% 100%, 100% 100%, 0 100%, 0 calc(100% - 25px), 0 25px);
    }

    /* 切角+子元素border正常显示 */
    .item.border-false {
        border: 1px solid pink;
    }

    .item.border-true {
        clip-path: none;
        border: none;
        background: none;
    }

    /* 切角用元素的伪类来实现 */
    .item.border-true:before,
    .item.border-true:after {
        content: '';
        display: block;
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        clip-path: polygon(25px 0, 100% 0, 100% 0, 100% 100%, 100% 100%, 0 100%, 0 calc(100% - 25px), 0 25px);
    }

    /* 这里使用元素伪类 before 代替显示元素的border */
    .item.border-true:before {
        width: calc(100% + 2px);
        height: calc(100% + 2px);
        background: pink;
    }

    /* 这里使用元素伪类 after 来代替显示元素的元素本身的背景色 */
    .item.border-true:after {
        width: 100%;
        height: 100%;
        background: #4030a9;
    }

    /* 使用伪类实现切角时要注意给元素的子元素添加优先级显示 */
    .item.border-true .item-inner {
        z-index: 5;
    }
</style>

<body>
    <main class="content">
        <h1>关于CSS切角的实现与踩坑解决(clip-path)</h1>
        <section>
            <h2>clip-path 切角使用基本使用模板</h2>
            <ul class="list">
                <li class="item top-left">
                    <span class="item-inner">左上角切角</span>
                </li>
                <li class="item top-right">
                    <span class="item-inner">右上角切角</span>
                </li>
                <li class="item bottom-right">
                    <span class="item-inner">右下角切角</span>
                </li>
                <li class="item bottom-left">
                    <span class="item-inner">左下角切角</span>
                </li>
                <li class="item top-left-to-bottom-right">
                    <span class="item-inner">左上-右下角<br />对切角</span>
                </li>
                <li class="item top-right-to-bottom-left">
                    <span class="item-inner">右上-左下角<br />对切角</span>
                </li>
            </ul>
        </section>
        <section>
            <h2>踩坑与对应解决方案</h2>
            <ul class="list">
                <li class="item top-left overflow-false">
                    <span class="item-inner">切角+子元素超出内容<br />非正常显示</span>
                </li>
                <li class="item top-left overflow-true">
                    <span class="item-inner">切角+子元素超出内容<br />正常显示</span>
                </li>
            </ul>
            <ul class="list">
                <li class="item top-left border-false">
                    <span class="item-inner">切角+子元素border<br />非正常显示</span>
                </li>
                <li class="item top-left border-true">
                    <span class="item-inner">切角+子元素border<br />正常显示</span>
                </li>
            </ul>
        </section>
    </main>
</body>

</html>

总结

作者本人也还是在不断学习中,若有错误记录勿喷,或有更好的解决方案,欢迎评论留言或私信互相学习一下~

联系我gitHub: Sunnyyy-G

个人微信公众号:Ligen web