今天看到@Chris Coyier刚发的一篇帖子,使用CSS怎么写一个切口盒子(Notched Boxes)?其实这个效果早在@Lea Verou的CSS Secrets一书中有一个专门的小节介绍CSS怎么实现这个斜切口的效果。所以说这不是什么新东西。不过接下来的内容和前面还是略有不同。
使用到的技术
@Lea Verou曾经介绍了几种实现盒子斜切口的效果,比如说使用CSS的linear-gradient
、clip-path
等。那么接下来的的内容其实除了运用到了clip-path
之外,还使用了CSS的自定义属性以及CSS的calc()
函数。从单个技术点上而言,或许大家都清楚他们的特性,或者很多同学都能灵活的使用这些CSS特性。那么今天重新花一篇篇幅来介绍,主要是因为:
将
clip-path
、calc()
和CSS自定义变量结合一起来使用,制作切口盒子会变得很容易,也很灵活。
实现过程
还是看看为什么结合他们,会让我们事情变得更轻松。
首先来看clip-path
。对于了解过clip-path
的同学来说,这个不是很难的事情,在clip-path
中提供了一个polygon()
函数,在这个函数中我们可以传很多个点的坐标(通过每个点的x
和y
来确定点在Web坐标系统中的位置),这样一来,我们就可以借助polygon()
绘制出任意你想要的多边形。比如下面的代码,绘制了一个三角形:
.module {
clip-path:
polygon(
50% 0,
100% 100%,
0 100%
);
}
效果如下:
随着点的位置增加,你就可以得到一个带斜切角的盒子:
.module {
clip-path:
polygon(
0% 5%, /* 左上1 */
5% 0%, /* 左上2 */
95% 0%, /* 右上1 */
100% 5%, /* 右上2 */
100% 95%, /* 右下1 */
95% 100%, /* 右下2 */
5% 100%, /* 左下1 */
0 95% /* 左下2 */
);
}
效果如下:
如果把polygon()
每个点在图上描出来,就像下图所示的一样:
如果你想要的斜切口这样的图形,你可以借助在线的clip-path
工具CSS clip-path
maker来获取,甚至你可以使用类似Sketch的Polygon工具来绘制,然后导出你所需要的图形坐标点。如果你使用的是Sketch导出的坐标点,那么你还需要人肉或借助工具将px
转换成%
。有关于百分比的计算,我想你知道如何计算。不过我们今天聊的只是斜切口的制作,其他不是我们今天所讨论的范围,如果你自己感兴趣,可以去自己试试。
对于上图所展示的斜切口效果,你会发现这些凹槽并不是完美的45deg
。造成这种现象的主要原因是元素本身并不是一个正方形。另外,你想确定你的斜切口的大小,还可以借助一些数学公式来计算,比如勾股定理:
话又说回来,要解决凹槽不是45deg
角也不是难事,借助CSS的calc()
函数,可以让我们事情变得简单而又是完美。比如,clip-path
裁剪一个带20px
切角的矩形元素,我们就可以这样写:
.module {
clip-path:
polygon(
0% 20px,
20px 0%,
calc(100% - 20px) 0%,
100% 20px,
100% calc(100% - 20px),
calc(100% - 20px) 100%,
20px 100%,
0 calc(100% - 20px)
);
}
对于x
轴的calc(100% - 20px)
和y
轴的calc(100% - 20px)
对应的位置。正如这个示例,如果元素的尺寸是:
事实上calc(100% - 20px)
对应的就是calc(400px - 20px)
,也就是元素的x
轴的380px
处,同样的y
轴的calc(100% - 20px)
即是calc(277px - 20px)
,也就是元素y
轴的257px
处。这也是为什么这里使用calc()
函数,它可以根据元素自身的尺寸,保证你最终得到的斜切角度是完美的45deg
。
上面示例的代码中,不难发现,20px
我们使用了很多次,这样一来,可以借助CSS处理器(比如,Sass,LESS之类),可以声明一个变量,如此一来,你需要修改斜切口的大小时,只需要修改变量的值。到目前为止,CSS自身也具有变量的概念(规范现在称之为CSS自定义属性)。CSS自定义属性的运行也非常的简单,你可以在:root{}
下声明一个变量,你也可以在该元素下声明一个变量,然后通过var()
函数来调用声明的变量。下面的示例是在元素自身中声明了一个--notchSize
的变量:
.module {
--notchSize: 20px;
clip-path:
polygon(
0% var(--notchSize),
var(--notchSize) 0%,
calc(100% - var(--notchSize)) 0%,
100% var(--notchSize),
100% calc(100% - var(--notchSize)),
calc(100% - var(--notchSize)) 100%,
var(--notchSize) 100%,
0% calc(100% - var(--notchSize))
);
}
如果你从未接触过CSS自定义属性,那么强烈建议你花点时间阅读一下这方面的教程。小站上整理了不少关于CSS自定义属性的教程。
使用CSS自定义属性还有一个优势,可以借助其给开发者暴露的 API:element.style.setProperty('--variableName', variableValue)
进行动态修改CSS自定义属性的值。比如下面的示例,配合input type="range"
,你拖动input
的滑块时,可以看到元素斜切角的变化:
var inp = document.querySelector("input");
var mod = document.querySelector(".module");
inp.addEventListener("input", function() {
mod.style.setProperty("--notchSize", this.value + "px");
});
最终的效果如下,大家可以亲自体验一把:
封装一个Vue组件
如果你只想实现一个斜切口效果,你已经完成了,而且效果非常的完美。看到这样的一个效果的时候,我在想,我是否可以将这个效果封装成一个Vue组件。那是因为自己最近在学习Vue相关的知识,所以我尝试着使用Vue来完成这个效果的组件。
具体过程不详细描述,先来看组件模板的代码:
<template id="notch">
<div class="notch" :style="{'--notchSize': changeChildNotchSize}">
<slot>This is notch module box!</slot>
</div>
</template>
<div id="app">
<c-notch :child-notch-size = notchSize></c-notch>
<div class="form">
<input type="range" min="0" max="50" v-model="notchSize" @input="change">
</div>
</div>
对应的JavaScript代码:
Vue.component('c-notch',{
template: '#notch',
props: ['childNotchSize'],
computed: {
changeChildNotchSize: function () {
return this.childNotchSize + 'px'
}
}
})
let app = new Vue({
el: '#app',
data () {
return {
notchSize: '20'
}
},
methods: {
change: function (e) {
this.notchSize = e.target.value
}
}
})
这个组件刚好让我运用到了前面学习的一些理论知识,比如定义Vue组件模板的方式(除了示例上的创建组件模板方式之外,你也可以使用单个文件来创建组件)、Vue组件通讯和Vue的插槽等。
最终效果如下:
VueStudy是自己学习Vue写的一些小示例,如果你对此感兴趣,不仿加入一起玩耍。
总结
使用CSS实现一个元素斜切口效果的方案其实有很多种,这篇文章主要介绍了,如何使用clip-path
实现盒子四边带切口的效果,同时为了切口更为完美,借助calc()
函数,让切口具有完美的45deg
角。为了更好的避免你多次修改切口的宽度值,采用CSS自定义属性来解决这种重复性工作。最后为了能更好的重复使用该效果,借助于Vue,将其封装为Vue的组件。如果大家感兴趣,不仿试试,利用这些技术,实现其他的一些特效。
如需转载,烦请注明出处:https://www.w3cplus.com/vue/create-notched-boxes-component-with-vue.html