原文链接:Create Diagonal Layouts Like It's 2020,by NILS BINDER
实现对角线布局有三种方式:
- SVG(参见 Erik Kennedy 的文章)
- CSS clip-path(参见 Sebastiano Guerriero 或 Kilian Valkhof 的文章)
- CSS 转换
本文讲述如何使用 CSS 转换(对应 transform
属性)实现对角线布局效果。
一、HTML 结构
<div class="diagonal-box">
<div class="content"> ... </div>
</div>
复制代码
加一点基本的 CSS 样式:
.diagonal-box {
background-image: linear-gradient(45deg, #6303B1, #ff0099);
}
.content {
max-width: 50em;
margin: 0 auto;
}
复制代码
得到如下的效果:
一、开始转换
首先想到的是旋转(rorate)整个容器元素。但带来的问题是,100% 宽的 .diagonal-box
经旋转之后,不再能横向覆盖整个视口区域了。为此,我们需要增加宽度到 100% 之上来解决这个问题。
还有一个思路是,不用使用旋转,使用倾斜转换(skew-transformation)就能实现所需的效果,这个变换效果可能很少人知道。为了更加精确,我们仅沿 Y 轴对 .diagonal-box
做倾斜处理。
.diagonal-box {
background-image: linear-gradient(45deg, #6303B1, #ff0099);
transform: skewY(-11deg);
}
复制代码
得到结果:
三、内部和外部转换
上面的倾斜效果是对包括内容(.content
)在内的整个容器进行的转换效果。虽然,这个属性解决了一些问题,但也带来一些问题。有时候,我们不想内容也做倾斜。为此,我们需要在内容上再做一次反向转换:
.diagonal-box {
background-image: linear-gradient(45deg, #654ea3, #eaafc8);
transform: skewY(-11deg);
}
.content {
max-width: 50em;
margin: 0 auto;
transform: skewY(11deg);
}
复制代码
效果:
四、使用伪元素
如果内容元素上还包含一些过渡效果(比如,淡入动画)。那么我们在写这些效果之前,不得不先考虑是否要对元素做反向转换处理,有点让人感觉烦。幸亏还有解决办法:我们不对整个容器做偏斜处理,而是用跟容器一样大的伪元素来做倾斜效果。
.diagonal-box {
position: relative;
}
.diagonal-box::before {
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
background-image: linear-gradient(45deg, #654ea3, #eaafc8);
transform: skewY(-11deg);
}
.content {
max-width: 50em;
margin: 0 auto;
position: relative;
}
复制代码
这里的 ::before
元素使用了绝对定位。为此,我们还需要为 .diagonal-box
、.content
各加一句 position: relative
声明。为 .diagonal-box
加,是为了限制 ::before
是相对与它定位的;为 .content
加,是因为 ::before
使用绝对定位后,层级变高,会覆盖 .content
元素,我们给 .content
加 position: relative
后,就能避免覆盖了。
来看效果:
五、得体的展示内容
再看一遍上面的效果,发现内容元素超出了偏斜背景的边界,感觉上不是被偏斜背景包围的,我们需要加一点 padding
。一种方式是在控制台中反复调试,可是不够灵活;另一种方式,就是深入研究这里面包含的数学规律,计算出精确的 padding
值。看下面这张图:
根据图示,a 的宽度是已知的 ,也就是容器宽度。这里的角度 α 等于我们在 Y 轴上偏斜度数,即 11°。我们要求的是直角三角形其中一个直角边 x 的值。根据公式:
x = tan(α) * a / 2
**
遗憾的是,我们是无法在 CSS 计算中做此类计算的。 但这不是一个大问题,在大多数情况下,偏斜角度基本是保持不变的,因此我们可以直接存储计算出来的值就行了。
六、使用 CSS 变量
经计算,tan(11°) / 2 的结果约等于 0.09719。我们可以将它存储在 CSS 变量中。这样,代码可以更简单一点:
:root {
--magic-number: 0.09719; /* tan(11°)/2 */
--content-width: 100vw;
--skew-padding: calc(var(--content-width) * var(--magic-number));
}
@media screen and (min-width: 42em) {
:root {
--content-width: 42em;
}
}
复制代码
--skew-padding
就是内容元素要应用的 padding
值,它会随着 --content-width
的改变而动态改变。
除此之外,还能使用 --skew-padding
做别的效果。比如,多个盒子沿着对角线布局。
七、Demo
点击上面的链接,即可看见本篇文章中讲到的所有相关案例代码。
感谢阅读!
(完)