用css实现固定宽高比并居中

382 阅读3分钟

前言

我们在做直播场景,这个场景有以下要求:

  • 宽高是16:9,因为视频流是这么大,所有的内容都在这个区域内
  • 这个区域要尽量占满空间并居中,如果周围有空白则用黑色填充用以凸显直播部分
  • 因为浏览器可以随便改变大小,所以保证这个区域至少960x540,防止太小导致里面的内容错乱

clamp

看着上面的需求挺复杂,但是其实关键就是16:9并且最小960x540,那么如何实现这个布局?

我们使用css的clamp函数即可。

clamp函数需要传入3个参数,一个最小值,一个默认值,一个最大值,用于处理边界值,当默认值大于最大值时,取最大值,小于最小值时,取最小值,介于最小与最大之间时,取默认值。

clamp(MIN,DEFAULT,MAX)就相当于max(MIN,min(DEFAULT,MAX))

先来看宽度,默认值是窗口宽度来满足尽量占满空间,最小值是960,最大值则是 高度16/9,因为如果 宽度 小于 高度16/9,那么直播区域的宽度要比窗口宽度小,这样左右两边留出黑边即可。所以:

 width: clamp(960px, 100vw, 177.78vh);

同理可以得到高度:

height: clamp(540px, 100vh, 56.25vw);

这样就满足了直播区域的要求。

居中

满足直播区域的要求后,解决居中问题即可,这个很简单,完整代码如下:

.page-container {
  display: flex;
  justify-content: center;
  align-items: center;
  min-width: 960px;
  background-color: black;
  .live-container {
    position: relative;
    background-color: white;
    width: clamp(960px, 100vw, 177.78vh);
    height: clamp(540px, 100vh, 56.25vw);
  }
  ...
}

live-container就是直播区域,它在page-container的中间,留白为黑色。如果窗口小于960,则宽度固定960,在外层进行滚动即可。

css计算函数

这里面我们用到了css的clamp函数,css的函数有不少,其中用于计算数值相关的有以下几个:

  • calc():进行加减乘除计算
  • min():取最小值,可以有多个参数
  • max():取最大值,可以有多个参数
  • clamp():在区间内取合适的值

移动端

移动端用上面的方法有很多问题:

  • android:尺寸没问题,但是当弹出键盘的时候100vh就会变小,在横屏的情况下会导致直播区域变得非常小。其实我们希望它可以不改变尺寸,键盘应该是覆盖在上面的。
  • ios:ios上100vh不是可见高度,而是包括地址栏,这就导致直播区域底部有一部分不可见,需要滑动才可以。

目前这两个问题还没找到很好的解决方法,所以如果适配移动端的话,还是建议通过js动态计算再设置live-container的style吧。

js获取宽高:

const windowWidth = document.documentElement.clientWidth || document.body.clientWidth;
const windowHeight = document.documentElement.clientHeight || document.body.clientHeight;

虽然在android上弹出键盘还是会导致高度变小,但是我们在一开始获取正常的高度一次性设置完即可。