前言
现在有如下的 HTML 结构:
1 | <body> |
如果我们想给页面一个最小高度,保证 Header 和 Footer 分别位于页面的顶部和底部,我们通常会这样写样式:
1 | * { |
在浏览器中我们预览的效果如下:
但是如果在移动端使用某些浏览器,比如 iOS 的 Safari,就会出现纵向滚动条:
这是因为某些移动端浏览器在计算 vh 时,会将工具栏高度也计算进去,因此会出现滚动条,我们可以通过如下三种方案去尝试修复这个行为。
方案一:使用 -webkit-fill-available
-webkit-fill-available
是 webkit 浏览器独有的一个属性值,表示填充剩余可用空间,因此我们可以将 body
的 min-height
设置为该值,就可让 body 填充整个视口了:
1 | body { |
设置后我们发现 safari 的高度正常了,但是 PC 和 Android 的 Chrome 浏览器高度却不对了:
这是由于 -webkit-fill-available
两者的表现形式不统一造成的:
- 在 Safari 中:如果设定了
height: -webkit-fill-available
元素父级元素设定了绝对的宽高,那么其元素高度就是父级元素的高度。如果父级元素没有宽高,那其高度就是视口的宽度,可用于替代100vh
让移动端不出现滚动条; - 在 Chrome 中:只有 html 元素设置了
height: -webkit-fill-available
才会填充整个视口宽度,如果想让子元素的高度也为视口高,那就需要层层设置height: -webkit-fill-available
。
因此如果想要兼容 Chrome 的表现,就需要将 CSS 修改为:
1 | html { |
注意:html 必须设置 height 而不能设置 min-height,这是因为 body 要继承 html 的高度,如果不指明,子元素的
min-height: -webkit-fill-available
就相当于min-height: auto
。
该方法较为简单,CSS 兼容性也尚可,但是如果元素嵌套过深,比如:
1 | <body> |
我们想为 .container
设置 min-height
为 -webkit-fill-available
,那就必须将 body
、html
的 height
设置为 -webkit-fill-available
,这样 .cotainer
的最小高度才能在 Chrome 中生效。
参考:《CSS fix for 100vh in mobile WebKit》
方案二:使用 window.innerHeight
window.innerHeight
可以用于获取视口高度,在移动端浏览器中,该值不会包含工具栏的高度,因此我们可以通过该值来修正 vh
。
我们可以使用 CSS Var 来创建一个全局变量 --vh
,该变量的值为 window.innerHeight * 0.01
,也就是 1vh
的高度,然后将使用 100vh
的地方替换为 calc(var(--vh, 1vh) * 100)
即可。
代码逻辑如下:
1 | function setVhCssVar() { |
使用:
1 | body { |
这个方案虽然需要使用 Javascript,但是效果是比较好的,可以完美的替换 100vh
,且不存在浏览器的差异性。
方案三:使用 dvh
dvh
表示动态视口,是一个比较新的 CSS 单位。其可以动态的表示移动端浏览器的视口高度,比如当浏览器存在工具栏、地址栏时,其表示中间的小视口的高度;而当用户向下滑动,或者手动隐藏掉工具栏时,其表示的是隐藏掉栏框后的大视口高度:
因此我们只需要将 vh
替换为 dvh
即可完美解决滚动条问题:
1 | body { |
但是该特性由于较新,考虑兼容性问题的话需要慎重使用: