如何在垂直方向上均匀展示高度相等的栏目?
yaodebian opened this issue · comments
如何在垂直方向上均匀展示高度相等的栏目?
场景:手机屏幕上需要垂直展示两个栏目块,并保证栏目块与顶部底部的距离、栏目块之间的距离相等(当然要满足不同的屏幕高度,即高度适配)。
要求保持上面的三块高度相等。
Now let's try several methods below:
- 方法一:基于flex实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>demo1: by flex</title>
<style>
.box {
width: 300px;
height: 500px;
background: yellow;
display: flex;
flex-direction: column;
align-items: center;
}
.wrapper {
width: 100%;
height: 40px;
position: relative;
}
.block {
color: #ffffff;
text-align: center;
width: 90px;
height: 40px;
box-sizing: border-box;
line-height: 40px;
padding: 0 15px;
border-radius: 5px;
display: inline-block;
position: absolute;
left: 50%;
margin-left: -45px;
}
.box-block1 {
background: #67C23A;
bottom: 0;
}
.box-block2 {
background: #409EFF;
top: 50%;
margin-top: -20px;
}
.box-wrapper1 {
flex-grow: 1
}
.box-wrapper2 {
flex-grow: 2;
}
</style>
</head>
<body>
<div class="box">
<div class="box-wrapper1 wrapper">
<div class="box-block1 block">冬沐</div>
</div>
<div class="box-wrapper2 wrapper">
<div class="box-block2 block">帅哥</div>
</div>
</div>
</body>
</html>
这种方法思路很简单,就是将整个“屏幕”分成上下两个部分wrapper1和wrapper2,wrapper1放置一个栏目1,wrapper2放置栏目2,并使栏目1贴近wrapper1底部,栏目2垂直居中wrapper2,接着结合flex布局中子元素中的flex-grow来完成。wrapper1的flex-grow设为1,wrapper2的flex-grow设为2,这样,就能保证wrapper2中的空隙是wrapper1的两倍,加上栏目2垂直居中等分wrapper2中的间隙。
扩展:那如果是不止2个栏目呢,这种方法还能很好地复用吗?当然可以,直接在上述代码基础上增加栏目,并保证最后一个栏目在其包裹块中垂直居中,并设置flex-grow为2,前面的栏目则贴紧包裹块的底部,flex-grow设为1。
- 方法二:基于百分比
基于方法一,我们已经有了一个很清晰的思路,即分成上下两个部分,上部分中栏目贴紧底部,下部分中栏目垂直居中。基于这个思路,我们通过百分比来确定上下部分的高度。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>demo2: by percentage height base on demo1 layout</title>
<style>
.box {
width: 300px;
height: 500px;
background: yellow;
}
.wrapper {
height: 40px;
position: relative;
}
.block {
color: #ffffff;
text-align: center;
width: 90px;
height: 40px;
box-sizing: border-box;
line-height: 40px;
padding: 0 15px;
border-radius: 5px;
display: inline-block;
position: absolute;
left: 50%;
margin-left: -45px;
}
.box-block1 {
background: #67C23A;
bottom: 0;
}
.box-block2 {
background: #409EFF;
top: 50%;
margin-top: -20px;
}
.box-wrapper1 {
height: calc(33.3% + 13.3px);
}
.box-wrapper2 {
height: calc(66.6% - 13.3px);
}
</style>
</head>
<body>
<div class="box">
<div class="box-wrapper1 wrapper">
<div class="box-block1 block">冬沐</div>
</div>
<div class="box-wrapper2 wrapper">
<div class="box-block2 block">帅哥</div>
</div>
</div>
</body>
</html>
这种方法的缺陷是:
- 高度的计算跟栏目数量有关(前提:栏目高度一样),不同的栏目数量需要重新计算一遍;
- 不够精确,毕竟百分比有些只能四舍五入;
- 方法三:基于flex的space-between
就是单纯的space-between,看代码就是了:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>demo3: by flex base on space-between</title>
<style>
.box {
width: 300px;
height: 500px;
background: yellow;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
}
.block {
color: #ffffff;
text-align: center;
width: 90px;
height: 40px;
box-sizing: border-box;
line-height: 40px;
padding: 0 15px;
border-radius: 5px;
}
.box-block1 {
background: #67C23A;
}
.box-block2 {
background: #409EFF;
}
</style>
</head>
<body>
<div class="box">
<div></div>
<div class="box-block1 block">冬沐</div>
<div class="box-block2 block">帅哥</div>
<div></div>
</div>
</body>
</html>
这应该是最简单的方法。
- 方法四:基于space-between和flex-grow
我们在整个屏幕顶部和底部分别插入一个空的wrapper,并设置flex-grow为1,栏目我们放在一个wrapper中,并通过space-between使里面的栏目均匀分布,同时根据里面的间隙数量设置flex-grow,比如:里面有两个栏目,也就是一个间隙,设为1,如果有三个栏目,有两个间隙,设为2,以此类推。。。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>demo4: by flex base on space-between and flex-grow</title>
<style>
.box {
width: 300px;
height: 500px;
background: yellow;
display: flex;
flex-direction: column;
align-items: center;
}
.box-wrapper {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
flex-grow: 1;
}
.box-space {
width: 100%;
flex-grow: 1;
}
.block {
color: #ffffff;
text-align: center;
width: 90px;
height: 40px;
box-sizing: border-box;
line-height: 40px;
padding: 0 15px;
border-radius: 5px;
}
.box-block1 {
background: #67C23A;
}
.box-block2 {
background: #409EFF;
}
</style>
</head>
<body>
<div class="box">
<div class="box-space"></div>
<div class="box-wrapper">
<div class="box-block1 block">冬沐</div>
<div class="box-block2 block">帅哥</div>
</div>
<div class="box-space"></div>
</div>
</body>
</html>
总结:上面四种方法,方法134都是通过flex实现,1、4比较通用,3最通用,但这几种方法由于弹性布局兼容性问题不好,有必要仔细斟酌一下。方法2虽然有不够通用,精度比较差的缺陷,但兼容性比较好,如果追求兼容性,请选择这种方法。
上述demo代码详见:https://github.com/yaodebian/blog_code/tree/master/equal_layout
last(最后)
非常感谢您能阅读完这篇文章,您的阅读是我不断前进的动力。对于上面所述,有什么新的观点或发现有什么错误,希望您能指出。
最后,附上个人常逛的社交平台:
知乎:https://www.zhihu.com/people/bi-an-yao-91/activities
csdn:https://blog.csdn.net/YaoDeBiAn
github: https://github.com/yaodebian
个人目前能力有限,并没有自主构建一个社区的能力,如有任何问题或想法与我沟通,请通过上述某个平台联系我,谢谢!!!