CSS案例:实现书页任意折角效果
书页任意角度折角效果示意图
<div class='note'> 欢迎来到二狗哥的博客,HTML、CSS、JavaScript等前端代码研究,你我共勉! </div>
代码编程要求:
1、折线与上边缘构成角度为30°;2、背景颜色色标#6d98bd,折角部分色标#577b98;3、为增加逼真效果,需要为折角添加阴影;4、折角不能遮盖内容文字部分;
书页任意角度折角效果分解为两个步骤:(1)绘制满足要求的特定三角形;(2)将三角形位置设置为指定坐标地点。
构建数学模型进行分析:
矩形ABCD代表主体元素(.note),三角形EFB1代表折角元素,并且三角形EFB1与三角形EBF关于EF轴对称。
实现思路:主体采用相对定位,翻折部分用伪元素通过绝对定位来实现。主体元素(.note)的背景翻折部分(虚线三角形),通过线性渐变颜色显示剪去翻折部分。
上面是数学模型的局部放大图,采用背景线性渐变来剪去目标三角形,剪去部分为透明色(transparent)。重点是确定达到指定线性渐变的渐变角度以及色标长度值。根据W3C中线性渐变渐变线的定义,想要EF为分界线,渐变角度为210°,透明色渐变长度等于线段BH长度值(BH与EF互相垂直)。
根据几何图形对称轴的特性有:
EB=EB1
FB=FB1
根据直角三角形的关系,我们可以得出:
BE=√3 BF
EB长度等于伪元素的高度y,BF长度等于伪元素的宽度x。若是网页设计时,相关圆角和尺寸都会由设计时进行确定,有比较详细的标注。这里采用圆角边框半径用5px,透明色标长度18px效果比较理想。考虑代码的后期维护性,转换为相对单位em。主元素的CSS代码如下:
.note { font-size: 12px; color: rgb(199, 197, 197); width: 200px; height: 100px; padding: 20px; border-radius: .4166em; /* 5px */ position: relative; background: #6d98bd; /* 回退机制 */ background: linear-gradient(210deg, transparent 1.5em, #6d98bd 0); }
对于目标三角形来说,由于透明色色标已经确定,它的长度和高度与BH关联确定。根据三角函数,可知:高度值y=2BH=3em,宽度值 x= 2BH/√3代入数值计算,值约为:1.732em。
.note::before { content: ''; display: block; width: 1.73em; height: 3em; }
伪元素显示为直角三角形,同样通过线性渐变来实现。线性渐变色标分界线为对角线,根据线性渐变定义,可以知道透明色色标色标值为渐变线长度的50%。
background: linear-gradient(60deg, #577b98 50%, transparent 0);
这样初步实现了折角部分效果,下面重点是进行定位。默认的伪元素(.note::before)为主元素(.note)的第一个子元素,位于其内容盒中的左上角。目标位置靠近右上角,并需要经过一定的旋转实现。
伪元素位于主元素右上角后,需要上移FL距离,然后以F点为旋转点,旋转60°,即达到目标位置。FL=y-x=1.27em。
绝对定位与位置转换:
position: absolute; right: 0; top: 0; transform: translateY(-1.27em) rotate(-30deg); transform-origin: bottom right;
左下角圆弧:
border-bottom-left-radius: inherit;
最后增加阴影效果,让折角更加逼真:
box-shadow: -.2em .2em .3em -.1em rgba(0, 0, 0, .15);
完整的代码:
.note { font-size: 12px; color: rgb(199, 197, 197); width: 200px; height: 100px; padding: 20px; border-radius: .4166em; /* 5px */ position: relative; background: #6d98bd; /* 回退机制 */ background: linear-gradient(210deg, transparent 1.5em, #6d98bd 0); } .note::before { content: ''; display: block; width: 1.73em; height: 3em; position: absolute; background: linear-gradient(60deg, #577b98 50%, transparent 0); right: 0; top: 0; border-bottom-left-radius: inherit; transform: translateY(-1.27em) rotate(-30deg); transform-origin: bottom right; box-shadow: -.2em .2em .3em -.1em rgba(0, 0, 0, .15); }