yaodebian / blog

blog notes

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

如何在垂直方向上均匀展示高度相等的栏目?

yaodebian opened this issue · comments

如何在垂直方向上均匀展示高度相等的栏目?

场景:手机屏幕上需要垂直展示两个栏目块,并保证栏目块与顶部底部的距离、栏目块之间的距离相等(当然要满足不同的屏幕高度,即高度适配)。

具体效果大致如下:
在这里插入图片描述

要求保持上面的三块高度相等。

Now let's try several methods below:

  1. 方法一:基于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。

  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>

这种方法的缺陷是:

  • 高度的计算跟栏目数量有关(前提:栏目高度一样),不同的栏目数量需要重新计算一遍;
  • 不够精确,毕竟百分比有些只能四舍五入;
  1. 方法三:基于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>

这应该是最简单的方法。

  1. 方法四:基于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

个人目前能力有限,并没有自主构建一个社区的能力,如有任何问题或想法与我沟通,请通过上述某个平台联系我,谢谢!!!