CSS – vw, vh, position fixed and ICB (initial containing block)

什么是 vw, vh?

vh 的 v 指的是 viewport, h 就是 height. 它是 CSS 值的单位就像 px, %.

.container {
  height: 30vh;
  background-color: red;
}

那么 30vh 是多高呢? 

30% of viewport heigth 的意思.

 

vh 和 % 的区别

% 对标当前 element 的 parent (或更准确的说是 containing block) 来计算的.

而 vh 则对标 viewport (initial containing block ICB) 来计算的.

 

ICB (Initial Containing Block)

既然 vh 是 viewport 的 percentage, 那就要先搞清楚 viewport(更准确的叫法是 ICB) height 具体是多少.

viewport 一般上指的就是屏幕 avaiable size (可视区). 也就是扣除了 address bar, tool bar, bookmark bar 等等

但是有些东西却会影响 viewport 的 size, 比如在手机, body scroll 以后, address bar 会消失 (对 vh 影响). 或者在电脑内容多的时候会有 vertical scroll bar (对 vw 影响).

那游览器的 viewport size 是动态的吗 ?

先看看 Chrome 的历史: URL Bar Resizing

以前 Chrome 确实是动态的, 100vh 它会因为 address bar 的消失而改变 value. 但后来这种体验实在太差了. 所以被修改成固定的了.

Safari, Chome viewport size 都是不包含 address bar 和 tool bar 的.

固定 viewport size 的问题

参考: The trick to viewport units on mobile

由于 100vh = viewport size without address/tool bar. 所以当 address bar 存在的时候, 效果就会像左图那样.

所以用 vh, vw 时要切记. 它是不包含任何 bar 的高度/宽度 (偏大).

How to get read avaiable viewport ?

tesla.com 这种一屏一屏的体验, 如果用 100vh 就不对了. 因为 address bar 是一直存在的 (记住: 没有 bar 时 vh 美美, 有 bar 时 vh 不美).

有 2 种方法可以拿到包含 address bar 的 size (偏小). 

参考: 

Mobile issue with 100vh | height: 100% !== 100vh [3 solutions]

The trick to viewport units on mobile

CSS fix for 100vh in mobile WebKit

CSS fix for 100vh in mobile WebKit

第 1 种方式是不要用 vh, 改用 -webkit-fill-available.

.div {
  min-height: 100vh;
  /* fill on ios */
  min-height: -webkit-fill-available;
}

这个方法适合用在 first layer. 如果很多层就不合适了.

第 2 种方法是用 JS 获取 window.innerHeight 然后赋值给 CSS variable

window.addEventListener('resize', () => { 
  document.querySelector(':root').style
    .setProperty('--vh', window.innerHeight/100 + 'px');
})
height: calc(100 * var(--vh));

调用, 10vh 等价于 10 * var(--vh)

假设 inner height 是 768px, 那么就是 10 x 768 = 7680px 所以 vh 需要先除于 100

最终就是 --vh = 768 / 100 = 7.68px, 然后 10vh = 10 * 7.68px = 76.8px.

监听 resize 的话基本上是模拟了 Chrome 早期 vh 的实现了. 

 

Large, Small, Dynamic (lvh, svh, dvh)

参考: YouTube – Learn Every CSS Viewport Unit In 10 Minutes

lvh, svh, dvh 是新的东西, 目前支持率还不是很好. 29 Nov 2022 的 Chrome 才开始支持.

顾名思义 lvh 就是 large vh, 也就是不包含 address bar 的 vh (偏大). 也是目前的 vh

svh small vh 就是包含 address bar 的 vh (偏小), 目前需要用 JS 才能获取到的.

dvh 就是 dynamic vh, 当 address bar 出现时它就偏小, 当 address bar 消失时它就偏大. 它就是早年 Chrome 对 vh 的实现.

有了这些就不那么乱水了. oh yeah.

 

vmax, vmin, vb, vl

vmax 是拿 vh, vw 最大的那个

vmin 是拿 vh, vw 最小的那个

vb 是 view block, 它是 Logical Properties. 正常情况下是 vh

vi 是 view inline, 它是 Logical Properties, 正常情况下是 vw

 

posted @ 2022-02-23 12:27  兴杰  阅读(373)  评论(0)    收藏  举报