故事前景:
实现一个如下图的布局:
看到这个设计图,各路摸鱼大神纷纷劝我使用图片,然后控制点击区域,简单方便,用图一分钟,摸鱼两小时。
沉思三秒钟之后,我考虑到了以下三点:
- 用户体验较差(用户点击区域有限)
- 图片需要一个请求(浪费性能)
- 太简单的做法(我不干)
于是,我就开始了我的做法:
首先,我准备了四个层级的元素:
- 准备一个外层盒子,用来旋转角度;
- 内层盒子需要创建一个根据宽度自适应高度的正方形盒子,并相对定位;
- 定位元素下生成一个绝对定位元素,宽高100%;
- 绝对定位元素下四个方向;
// layout
<div class="outBox">
<div class="innerBox">
<p class="center"></p>
<ul class="absoluteEle">
<li
class="direction"
v-for="(item,i) of dirList"
:key="i"
>
{{item}}
</li>
</ul>
</div>
</div>
// style
.outBox{
transform: rotateZ(45deg);
}
.innerBox{
overflow: hidden;
border-radius: 50%;
padding: 50%;
position: relative;
}
.center{
position: absolute;
width: 38%;
height: 38%;
color: #fff;
background: #fff;
left: 31%;
top: 31%;
overflow: hidden;
z-index: 1;
border-radius: 50%;
}
.absoluteEle{
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
grid-row-gap: 20px;
grid-column-gap: 20px;
}
.direction{
width: 100%;
height: 100%;
box-sizing: border-box;
}
.absoluteEle > li:nth-child(2n) {
margin-right: 0;
}
.absoluteEle > li:nth-child(3),
.absoluteEle > li:nth-child(4) {
margin-top: 20px;
}
得到如下样式:
好像还不错,改改颜色放个箭头就perfect了,而且用户点击范围也更加精准!
于是我信心满满的提交测试... ...
安卓很完美,苹果高版本也不错,测试到低版本的苹果手机时,测试那平平无奇的脸上皱起了眉头,仿佛一下苍老十岁<( ̄▽ ̄)/
接下来就开始了我(小伙砸)与测试的巅峰对决:
- 测试:小伙砸,你这页面有问题啊,点了没效果啊,咋回事啊?
- 小伙砸:不可能,我测试了好多次都没问题的!
- 测试:小伙砸,你别犟,眼见为实(将iphone12mini递给了我);
- 小伙砸接过手机开始调试...
- 测试不屑的看着我
- 咦,咋点不了,我赶紧将页面恢复到测试状态,我丢,这页面咋这样
好家伙,身经百战的我如定海神针一般,表面稳如老狗,内心也稳如泰山!!!
这绝对是哪个属性没起作用咯,待小伙砸测试一番... ...
我一眼扫过代码,发现display:grid这个属性语法较新,应该是它了;然后我就开始了代码更改,也引来了@supports规则的使用:
// style(代码修改)
.absoluteEle{
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
/* 新增 */
display: flex;
flex-wrap: wrap;
}
.direction{
box-sizing: border-box;
/* 新增 */
width: calc(~"50% - 10px");
height: calc(~"50% - 10px");
margin: 0 20px 0 0;
}
@supports (display:grid){
.absoluteEle{
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
grid-row-gap: 20px;
grid-column-gap: 20px;
}
.direction{
width: 100%;
height: 100%;
margin:0;
}
}
再提交测试,ok,perfect!
既然提到了@supports(),那就记录学习一下这个规则吧!!!
@supports规则是从Edge12浏览器开始支持的,所以根本没有IE浏览器什么事情。
声明语法
先通过一个示例看看@supports的语法:
@supports (display:grid){
.grid{
display:grid;
}
}
这段代码意思简单明了,如果浏览器支持display:grid,则匹配.grid类名的元素设置为display:grid;
@supports规则还支持使用操作符进行判断,这些操作符分别为not、and和or,分别表示否定、并且和或者。
来看这些操作符实现简单的逻辑判断:
/* 支持网格布局 */
@supports (display:grid){ }
/* 不支持网格布局 */
@supports not (display:grid){ }
/* 同时支持网格布局和弹性布局 */
@supports (display:grid) and (display:flex){ }
/* 支持网格布局或者弹性布局 */
@supports (display:grid) or (display:flex){ }
/* 同时支持网格布局和弹性布局和transform */
@supports (display:grid) and (display:flex) and (transform: none){ }
/* 支持网格布局或者弹性布局或者transform */
@supports (display:grid) or (display:flex) or (transform: none){ }
但是,若是遇到复杂逻辑判断,还是一知半解的使用这些函数语法就会出现问题,来看几个依葫芦画瓢的示例:
1. @supports (display:flex) and not (display:grid) {} //支持弹性布局并且不支持网格布局
2. @supports not (display:grid) and (display:flex) {} //不支持网格布局并且支持弹性布局
想要学会@supports的条件判断语法,级联、嵌套,必须要多花亿点点时间来深入理解其规则!
我们先定义一个数据类型,命名为<[name]>,用来表示括号里面的条件,然后将条件拆出来看:
(display:flex) == <支持弹性布局>
not (display:grid) == <不支持网格布局>
(支持网格布局) and (支持弹性布局) and (支持transform) == <var>
(支持网格布局) or (支持弹性布局) or (支持transform) == <var>
每个条件都可以理解为一个变量,套用以上规则,来判断支持弹性布局,但不支持网格布局这样的条件实在太简单:
@supports (<支持弹性布局>) and (<不支持网格布局>) { }
得到正确写法:
@supports (display:flex) and (not (display:grid)) { }
选择器语法
来看两个示例:
@supports (--var:blue) { }
@supports selector(:default) { }
以上示例在实际项目中实用性较低,这里不再记录。。。