在我们的业务中,我们遇到比较通用的布局,上中下
,上左中下
以及更为复杂的结构,在一些常用交互设计上,我们究竟选择何种布局方案,最后都会产生不同的效果,在用户体验上来看也会千差万别。本文是一篇通用业务场景的解决方案,希望能带来一些思考和帮助。
正文开始…
上中下
这是我们在C端
常见的一种主体结构,什么意思?我们看下下面这种结构
我们从以上结构来看,内容始终是在我们设置的可视区域内部,如果内容很多,则会产生滚动条,header
与footer
始终是在整屏的顶部和底部。我们思考下为何会有种需求?按照正常文档流结构,我们的内容区域如果很多,底部就会被自动撑到非可视区域,并且我们的header也会随着内容滚动而被隐藏了。
我们针对不同的场景,我们说下为什么固定header与footer相比较不固定体验会好很多。
- 固定header与footer,内容滚动
在首屏能看到整个网页的内容Header
与footer
,无论内容是否多少,header
与footer
始终能被用户看到,且用户在滚动内容区域,非常快捷的切换其他tab
- 不固定header与footer,内容不滚动,随着内容有多少就撑多少
这种比较简单,基本不用我们特殊处理,也就是内容有少就会展示多少,并且footer
会贴着内容展示,并且当内容足够多时,当我们滑动到底部时,header
会看不见,这是一种不好的体验。
那如何实现首屏始终固定Header
与Footer
,内容始终在满屏滚动呢
- 方案一:
flex实现
我们先看下页面结构
<div class="app">
<header>
<div class="home">Home</div>
<div class="web">web技术学苑</div>
<div class="about">about</div>
<div class="login">登录</div>
</header>
<main>
<div>公众号:Web技术学苑</div>
<div>https://learn.wmcweb.cn</div>
</main>
<footer>
MIT Licensed | Copyright © 2022-present Maic
</footer>
</div>
对应的css
如下
* {
padding: 0;
margin: 0;
}
html, body {
height: 100%;
}
.app {
display: flex;
flex-direction: column;
height: 100%;
}
main {
flex:1;
padding: 0 20px;
}
header {
display: flex;
height: 50px;
align-items: center;
padding: 0 20px;
}
footer {
padding: 0 20px;
height: 30px;
}
header >div {
padding: 0 5px;
}
.web {
color: green;
}
.about {
flex:1;
display: flex;
justify-content: flex-end;
}
在以上对应的结构里我们发我们对.app
设置了flex
,但是flex-direction:column
主轴方向众向排列,因为我们的header
与footer
是固定高度,我们给了main
设置了flex:1
,并且我们将html,body
以及.app
的高度设置成了100%
,我们知道子级设置高度百分比会继承父级的高度
不知道你有没有发现在header
中我们的结构是下面这样简单单一的结构
<header>
<div class="home">Home</div>
<div class="web">web技术学苑</div>
<div class="about">about</div>
<div class="login">登录</div>
</header>
但是你会发现,我要实现的效果是左右这样的布局结构,我并没有将头部布局变成左右结构,而是利用flex
,单独设置了about
flex为1,并单独设置了它自己的样式,思考下是不是比下面这样的结构要简单,简单的结构,样式会少很多,并且可拓展性会更好点
<header>
<div class="left">
<div class="home">Home</div>
<div class="web">web技术学苑</div>
</div>
<div class="right">
<div class="about">about</div>
<div class="login">登录</div>
</div>
</header>
我们看下最终的效果
现在我们填充多一些内容
你会发现内容滚动头部会被隐藏,并没有达到我们想要的效果,那有什么办法可以解决这个问题呢?
我们知道产生滚动条的本质原因是,内容溢出了,在可视区域内容超出,就会产生滚动条,这个滚动条此时作用在body上的
所以我们只需要把滚动控制在内容区域即可
main {
flex:1;
padding: 0 20px;
height: calc(100vh - 80px);
overflow-y: auto;
}
在main上我们设置了固定高度,此时我们利用了一个calc的css计算,设置中间内容的固定高度就是calc(100vh - 80px)
,80px
是header与footer的高度,所以最后的效果就是下面这样的
注意我们给about
设置了flex:1
所以它承载了剩余的空间,并且我们单独将她设置成flex,并且居右排列
- 方案2: grid实现
我们在以上使用flex
实现了我们需要的效果,但实际上grid
实现更灵活
<div class="app">
<header>
<div class="home">Home</div>
<div class="web">web技术学苑</div>
<div class="about">about</div>
<div class="login">登录</div>
</header>
<main>
<div>公众号:Web技术学苑</div>
<div>https://learn.wmcweb.cn</div>
<div id="content"></div>
</main>
<footer>
MIT Licensed | Copyright © 2022-present Maic
</footer>
</div>
对应的css
* {
padding: 0;
margin: 0;
}
.app {
display: grid;
grid-template-rows: 50px 1fr 30px;
}
main {
padding: 0 20px;
height: calc(100vh - 80px);
overflow-y: auto;
}
header {
display: grid;
grid-template-columns: repeat(16,minmax(50px, 1fr));
align-items: center;
padding: 0 20px;;
}
footer {
padding: 10px 20px;
}
header >div {
padding: 0 5px;
}
.web {
color: green;
}
.about {
grid-column: 15;
display: flex;
justify-content: flex-end;
}
.login {
grid-column: 16;
display: flex;
justify-content: flex-end;
}
注意我们并没给html,body
设置高度,我们在app
上设置了grid
,并且设置了grid-template-rows: 50px 1fr 30px
,同样的,我们将滚动条放在了main
上,并设置了overflow-y:auto
效果与flex是一样的
- 方案3: 定位
定位的元素是脱离文档流的,但是我们可以将内容定位控制,footer可以是absolute或者fixed
* {
padding: 0;
margin: 0;
}
.app {
position: relative;
}
main {
padding: 0 20px;
height: calc(100vh - 80px);
overflow-y: auto;
position: absolute;
top: 50px;
bottom: 30px;
left:0;
right: 0;
}
header {
display: flex;
align-items: center;
padding: 0 20px;;
height: 50px;
}
footer {
padding: 10px 20px;
position: fixed;
bottom: 0;
}
header >div {
padding: 0 5px;
}
.web {
color: green;
}
.about {
flex:1;
display: flex;
justify-content: flex-end;
}
.login {
display: flex;
justify-content: flex-end;
}
上左中下
在我们了解上中下
结构后,我们在中台项目,这种结构是非常统一的
面对这种通用的结构,布局的方式有很多,但是我们通常来说一般顶部粘性,然后内容滚动,底部会随着内容并不固定在首屏
- 方案1:grid实现
<div class="app">
<header>
<div class="home">Home</div>
<div class="web">web技术学苑</div>
<div class="about">about</div>
<div class="login">登录</div>
</header>
<slide>
<div>菜单1</div>
<div>菜单2</div>
</slide>
<main>
<div>公众号:Web技术学苑</div>
<div>https://learn.wmcweb.cn</div>
<div id="content"></div>
</main>
<footer>
MIT Licensed | Copyright © 2022-present Maic
</footer>
</div>
对应的css
* {
padding: 0;
margin: 0;
}
.app {
display: grid;
grid-template-columns: 100px 1fr 1fr 1fr;
grid-template-rows: 50px 1fr 30px;
}
header {
grid-column: 1/5;
display: flex;
align-items: center;
padding: 0 20px;;
height: 50px;
background-color: yellow;
}
slide {
padding: 0 20px;
background-color: green;
}
main {
grid-column: 2/5;
padding: 0 20px;
height: calc(100vh - 80px);
overflow-y: auto;
padding: 0 20px;
background-color: pink;
}
footer {
padding: 10px 20px;
grid-column: 1/5;
}
header >div {
padding: 0 5px;
}
.web {
color: green;
}
.about {
flex:1;
display: flex;
justify-content: flex-end;
}
.login {
display: flex;
justify-content: flex-end;
}
最后的结果
- 方案2:flex
我们看下结构
<div class="app">
<header>
<div class="home">Home</div>
<div class="web">web技术学苑</div>
<div class="about">about</div>
<div class="login">登录</div>
</header>
<main>
<div class="slide">
<div>菜单1</div>
<div>菜单2</div>
</div>
<div class="content-box">
<div>公众号:Web技术学苑</div>
<div>https://learn.wmcweb.cn</div>
<div id="content"></div>
</div>
</main>
<footer>
MIT Licensed | Copyright © 2022-present Maic
</footer>
</div>
对应的css
header {
display: flex;
align-items: center;
padding: 0 20px;;
height: 50px;
background-color: yellow;
}
main {
display: flex;
}
.slide {
width: 100px;
height: calc(100vh - 80px);
background-color: green;
padding-left: 20px;
}
.content-box {
flex:1;
height: calc(100vh - 80px);
overflow-y: auto;
background-color: pink;
}
footer {
padding: 10px 20px;
}
...
- 方案3:普通的布局结构
我们尝试用普通的布局结构去实现我们的需求,相比较grid
,flex
布局,你会发现传统的布局代码量会产生很多
<div class="app">
<header>
<div class="home">Home</div>
<div class="web">web技术学苑</div>
<div class="about">about</div>
<div class="login">登录</div>
</header>
<main>
<div class="slide">
<div>菜单1</div>
<div>菜单2</div>
</div>
<div class="content-box">
<div>公众号:Web技术学苑</div>
<div>https://learn.wmcweb.cn</div>
<div id="content"></div>
</div>
</main>
<footer>
MIT Licensed | Copyright © 2022-present Maic
</footer>
</div>
你会发现首先我们内容区域的结构就变得相对复杂了些,但也没有那么特别复杂,我们再来看看css
* {
padding: 0;
margin: 0;
}
header {
display: flex;
align-items: center;
padding: 0 20px;;
height: 50px;
background-color: yellow;
}
main {
position: relative;
}
.slide {
position: absolute;
left:0px;
width: 100px;
height: calc(100vh - 80px);
background-color: green;
padding-left: 20px;
}
.content-box {
padding-left:120px;
width: calc(100vw - 120px);
height: calc(100vh - 80px);
overflow-y: auto;
background-color: pink;
}
footer {
padding: 10px 20px;
}
...
我们在调整结构后,最大的调整就是,左侧与内容的调整,左侧绝对定位,右侧内容就是给一个左侧的内边距,然后设置了固定宽度和高度,并且给了滚动显示
效果也是一样的
最后你会发现实现布局的方法有很多,不同的结构组织,对应的css会有所差别,每一种情况对于后期的可拓展性更是不一样,个人推崇首选grid
方式,然后是flex
,最后是定位
,grid
对于后期的修改兼容性更好,但对于使用者grid
特性有更高的要求
总结
-
了解
上中下
结构,我们如何让header
与footer
在可视区域显示,对应的内容在可视区域内滚动 -
用不同方式实现
上中下
结构的布局,比如flex
或者grid
都可以实现 -
实现
上左中下
结构,我们通过三种不同的方式去实现,grid
布局更加灵活,页面结构比较简单,css也相对较少,个人推崇grid
最佳 -
每一种方案都有其自己的特点,也并都不都是完美的,比如使用
grid
,那么对使用者有更高的要求,相对flex
与定位
它更灵活,面对复杂的机构,如果你掌握了grid
,那么会使用简单的结构,最少的css实现其他两种方案一样的效果。