# 了解一下常见布局?
# 表单复杂布局
如果要你用 CSS 框架(ElementUI、Ant Design Vue 等等)实现以下效果,你会怎么实现?
<!-- 代码有缩减,目的是看懂 -->
<template>
<!-- 第一行普通布局 -->
<a-form-model
layout="horizontal"
:label-col="{ span: 4 }"
:wrapper-col="{ span: 10 }"
>
<a-form-model-item label="表描述" prop="tableDesc"></a-form-model-item>
<!-- 第二行内嵌其它表单布局 -->
<a-form-model-item
:label-col="{ span: 4 }"
:wrapper-col="{ span: 18 }"
label="业务及层级"
>
<a-row :gutter="10">
<a-col :span="6">
<a-form-model-item prop="businessId"></a-form-model-item>
</a-col>
<a-col :span="18">
<a-form-model-item prop="level"></a-form-model-item>
</a-col>
</a-row>
</a-form-model-item>
<!-- 第三行内嵌二级表单布局 -->
<a-form-model-item label="主题域&主题">
<a-row :gutter="10">
<a-col :span="12">
<a-form-model-item prop="primaryClassId" required></a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item
prop="secondaryClassId"
required
></a-form-model-item>
</a-col>
</a-row>
</a-form-model-item>
<!-- 第四行同行两个同类型表单布局 -->
<a-row :gutter="5">
<a-col :span="8">
<a-form-model-item
label="业务负责人"
prop="bizPrincipal"
:label-col="{ span: 12 }"
:wrapper-col="{ span: 10 }"
></a-form-model-item>
</a-col>
<a-col :span="8">
<a-form-model-item
label="技术负责人"
prop="techPrincipal"
:label-col="{ span: 8 }"
:wrapper-col="{ span: 10 }"
required
></a-form-model-item>
</a-col>
</a-row>
</a-form-model>
</template>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
这里面的重点是要理解a-form-model-item
的作用:它实际上起到布局和校验的作用,这里我们只考虑布局
实现第三行布局时(一个标签,两个联动选择框),我们可以用一个只带label
属性的a-form-model-item
去跟上面的表单布局适应,里面实际的渲染空间只有wrapper-col
的大小,在里面再使用一个a-row
来进行栅格布局就可以轻松达到每个输入框各占 50%
实现第四行布局时(两个标签,两个选择框),有两种写法
- 第一种类似第三行的布局
- 第二种直接用栅格布局,但是要注意两个
a-col
加起来要等于label-col
+wrapper-col
的大小(如果a-row
加了gutter
,则两个a-col
加起来要略大于label-col
+wrapper-col
的大小),之后在里面再使用a-form-model-item
的label-col
和wrapper-col
进行适当调整
# 网格自适应响应布局
<style>
/* content是外面的大盒子 */
.content {
display: grid;
grid-gap: 10px; /* 网格间距 */
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); /* 关键代码 */
grid-template-rows: auto;
}
</style>
2
3
4
5
6
7
8
9
解释一下关键代码grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
grid-template-columns
是设置网格列宽的
repeat
是一个函数,结合auto-fit
使用的话,表明每个列都是自适应的
minmax(200px,1fr)
表示列最小宽度是 200px,1fr
表示每列最大宽度自动分配等额剩余空间
# 左固定,右 10%,中间自适应
# float 实现
<style>
body {
margin: 0;
padding: 0;
}
/* 浮动 */
.float-wrapper {
width: 100%;
height: 500px;
}
.float-left {
float: left;
width: 200px;
height: 100%;
background-color: #000;
}
.float-right {
float: right;
width: 10%;
height: 100%;
background-color: #000;
}
.float-center {
margin: 0 10% 0 200px;
height: 100%;
background-color: yellow;
}
</style>
<body>
<!-- 左200px 右10% 中间撑满 -->
<!-- 浮动 -->
<div class="float-wrapper">
<div class="float-left"></div>
<div class="float-right"></div>
<div class="float-center"></div>
</div>
</body>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# flex 实现
<style>
body {
margin: 0;
padding: 0;
}
/* flex */
.flex-wrapper {
margin-top: 40px;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
height: 500px;
border: 1px solid #000;
}
.flex-left {
width: 200px;
background-color: green;
height: 100%;
}
.flex-center {
flex: 1;
background-color: yellow;
height: 100%;
}
.flex-right {
width: 10%;
background-color: red;
height: 100%;
}
</style>
<body>
<!-- 左200px 右10% 中间撑满 -->
<!-- 浮动 -->
<div class="flex-wrapper">
<div class="flex-left"></div>
<div class="flex-right"></div>
<div class="flex-center"></div>
</div>
</body>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# grid 实现
<style>
body {
margin: 0;
padding: 0;
}
/* grid */
.grid-wrapper {
margin-top: 40px;
width: 100%;
height: 500px;
display: grid;
grid-template-columns: 200px 1fr 10%;
}
.grid-left {
background-color: green;
height: 100%;
}
.grid-center {
background-color: yellow;
height: 100%;
}
.grid-right {
background-color: red;
height: 100%;
}
</style>
<body>
<!-- 左200px 右10% 中间撑满 -->
<!-- grid -->
<div class="grid-wrapper">
<div class="grid-left"></div>
<div class="grid-center"></div>
<div class="grid-right"></div>
</div>
</body>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 收缩展开布局
<template>
<div class="radio-content">
<a-radio-group
class="radio-group"
name="radioGroup"
:default-value="defaultVal"
button-style="solid"
v-model:value="subValue"
@change="(e) => $emit('update:value', e.target.value)"
>
<div class="label-wrapper" v-for="item in renderedOps" :key="item.val">
<a-radio-button :value="item.val" class="radio-btn">{{
item.label
}}</a-radio-button>
</div>
<div class="btn-content">
<a-button v-if="showMore" type="link" @click="expendOps" class="btn"
>更多</a-button
>
<a-button v-if="showShrink" type="link" @click="shrinkOps" class="btn"
>收起</a-button
>
</div>
</a-radio-group>
</div>
</template>
<style lang="less" scoped>
.radio-content {
flex-grow: 1;
.radio-group {
display: flex;
justify-content: flex-start;
align-items: center;
flex-wrap: wrap; /*关键代码*/
.label-wrapper {
flex: 0 0 25%; /*关键代码*/
text-align: center;
margin-bottom: 10px;
}
.btn-content {
width: 25%;
flex-grow: 1; /*关键代码*/
text-align: right; /*关键代码*/
margin-bottom: 10px;
.btn {
// float: right;
}
}
}
}
/deep/.ant-radio-button-wrapper {
border: none;
border-radius: 4px;
// margin: 5px;
padding: 0 10px;
}
/deep/.ant-radio-button-wrapper::before {
content: none;
}
</style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
思路:先不管选项内容,我们要十分清楚实现什么样的布局,重要是后面的多个radio
的布局,由于一行固定放四个(包括按钮),我们将一行均分成 4 个方块,每个方块基础宽度(flex-basis
)占25%
,不管里面放什么内容,不能伸缩放大,也就是设置flex: 0 0 25%
单独处理button
按钮,我们可以看到它是放在每一行的最右边,如果刚好是下一行也是如此,假设刚好有 5 个radio
,这时候应该是 4 个排在第一行,剩下 1 个排在第二行,后面剩下75%
的宽度如何放置按钮呢,我们可以将按钮的flex-grow
设置为 1,也就是吸收剩余空间,这样按钮就占据75%
的宽度的,此时按钮是默认排在第 5 个radio
的后面,我们需要将按钮移到最右边,怎么办呢?很简单,设置button
的父div
的text-align
为right
既可
布局关键点:
将操作按钮当成
radio
的一部分,放到options
最后面将每个
radio
选项和button
按钮用div
包裹,避免宽度影响原本的radio
和按钮大小父容器设置
display:flex;flex-warp:wrap;
radio
父div
设置flex: 0 0 25%;
button
父div
设置flex-grow: 1;width:25%;text-align: right;