响应式布局+栅格布局实现自定义布局

2,490 阅读2分钟

背景

  公司一直都有交互视觉走查的流程。最近有一个项目在走查中,UI小姐姐指出项目的布局不符合公司的视觉规范What?

    image.png

  还有这种操作? 我emo了,不过还是要改呀。

  首先看一下UI小姐姐所谓的布局规范是什么吧。

  具体来说就是:表单项目根据屏幕大小动态展示,屏幕小于1280的时候,展示2列,列间距是24px,且左右对齐。屏幕大于1280的时候,展示3列,间距同样是24px,且左右对齐,如下图所示:

1280屏宽 image-20211221164854205

大于1280屏宽 image-20211221165029495

方案一:使用element ui栅格布局

  看着还是挺简单的,该项目使用的组件库主要是基于element ui 的二次封装,所以第一时间就想到了使用栅格布局,BUT,改造起来并没有这么简单呀。怎么说呢,先看看该页面的组件布局情况吧:

image.png

  就是每个页面都引入pageLayout.vue公共组件,页面中写了el-form来替换pageLayout插槽部分。因此,如果要使用element-ui的栅格布局,我就要在每一个页面中,在el-form-item外面都套一层el-row/el-col,妈呀,想想工作量就巨大,因此方案一,PASS。

方案二:使用CSS grid网格布局,通过样式来整体控制

demo代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        body{
            margin: 0;
            padding: 0;
            background-color: pink;
        }
        .container{
            width: 100%;
        }
        .container-left{
            width: 200px;
            height: 700px;
            margin-right: 10px;
            float: left;
            background-color: yellow;
        }
        .container-right{
            margin-left: 210px;
            height: 700px;
            background-color: skyblue;
            padding: 20px;
        }
        .page-layout{
            border: 2px dashed red;
            display: flex;
            flex-wrap: wrap;
            gap: 24px;
        }
        .box{
            width: 200px;
            height: 100px;
            background-color: plum;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="container-left"></div>
        <div class="container-right">
            <h2>模块1</h2>
            <div class="page-layout">
                <div class="box">1</div>
                <div class="box">2</div>
                <div class="box">3</div>
                <div class="box">4</div>
                <div class="box">5</div>
                <div class="box">6</div>
                <div class="box">7</div>
                <div class="box">8</div>
                <div class="box">9</div>
            </div>
        </div>
    </div>
</body>
</html>

demo效果:

demo1.gif

结论:

  • 使用gap的优点是代码简洁,一行代码控制间距,布局灵活,根据屏幕大小,动态显示列数
  • 但是,gap的缺点也很明显,第一就是每行最后一项,会根据列数,留有不同程度的空白,并不能对齐;第二就是兼容性,不支持IE,且Chronme只支持57及以上版本,因此,方案二PASS

方案三:使用栅格布局+响应式组合控制,实现最终效果

上代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        body{
            margin: 0;
            padding: 0;
            background-color: pink;
            min-width: 992px;
        }
        .container{
            width: 100%;
        }
        .container-left{
            width: 200px;
            height: 700px;
            margin-right: 10px;
            float: left;
            background-color: yellow;
        }
        .container-right{
            margin-left: 210px;
            height: 700px;
            background-color: skyblue;
            padding: 20px;
        }
        .page-layout{
            border: 2px dashed red;
            display: flex;
            flex-wrap: wrap;
        }
        .box{
            width: calc(33.33% - 16px);
            height: 100px;
            background-color: plum;
            margin-bottom: 24px;
            margin-right: 24px;
            box-sizing: border-box;
        }
        .box:nth-child(3n){
            margin-right: 0;
        }
        /* 响应式开始 我这里使用的是小屏电脑,因此最大宽度使用的是PC宽度,项目中是1280px*/
        @media screen and (max-width: 992px) {
            .box{
            width: calc(50% - 12px);
            height: 100px;
            background-color: blue;
            margin-right: 0;
            margin-bottom: 24px;
            box-sizing: border-box;
            }
            .box:nth-child(2n){
            margin-left: 24px;
        }
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="container-left"></div>
        <div class="container-right">
            <h2>标题</h2>
            <div class="page-layout">
                <div class="box">1</div>
                <div class="box">2</div>
                <div class="box">3</div>
                <div class="box">4</div>
                <div class="box">5</div>
                <div class="box">6</div>
                <div class="box">7</div>
                <div class="box">8</div>
                <div class="box">9</div>
            </div>
        </div>
    </div>
</body>
</html>

demo效果

demo2.gif

  通过方案三,在page-layout组件中通过css控制el-form-item的宽度,来实现批量改造,最终达到走查要求

遇到的坑:

  不过在修改的时候,还是遇到了一些坑,比如,有些el-form-item是通过v-show控制的,这就导致nth-child控制的子元素没有对应视图显示,因此尽量使用v-if来控制元素是否显示吧。