CSS `Viewport Segments` (`env(viewport-segment-width)`) (提案):折叠屏与多屏设备适配

嘿,各位屏幕控们,准备好迎接 CSS 新纪元了吗?

今天咱们不聊什么花里胡哨的动画,也不谈那些性能优化的老生常谈。咱们来点硬核的,聊聊 CSS 新晋的“变形金刚”—— Viewport Segments (视口分段)!

想象一下,你的网页不再被禁锢在一个规规矩矩的屏幕里,而是可以优雅地舞动在折叠屏、双屏甚至更多屏幕的设备上。是不是有点小激动?

没错,env(viewport-segment-width) 和它的小伙伴们,就是来解放生产力,啊不,是解放创造力的。

为什么需要 Viewport Segments?

先别急着撸代码,咱们得先搞清楚,这玩意儿到底解决了什么痛点。

折叠屏、双屏设备,看着炫酷,但对于网页开发者来说,简直就是噩梦。以前辛辛苦苦适配的响应式布局,在这些“异形屏”面前,瞬间就变成了 “应付式布局”。

比如,一个居中的按钮,在折叠屏展开后,可能正好被屏幕中间的“缝隙”给劈成两半,丑到没朋友。

再比如,双屏设备上,你想把一个内容横跨两个屏幕显示,传统的 CSS 布局根本无能为力。

所以,我们需要一种新的方式,让 CSS 能够感知到屏幕的“分段”情况,并根据这些信息,做出更智能的布局调整。

Viewport Segments 是什么?

Viewport Segments,简单来说,就是把屏幕分成若干个独立的“段”。

我们可以通过 env() 函数来获取这些段的宽度、高度、偏移量等信息,然后利用这些信息,来控制元素的布局。

目前,Viewport Segments 提供了以下几个环境变量:

环境变量 描述
viewport-segment-width 一个视口段的宽度。如果只有一个屏幕,则等于视口的宽度。如果有多个屏幕,则等于每个屏幕的宽度。
viewport-segment-height 一个视口段的高度。通常等于视口的高度,除非设备有不规则的屏幕形状。
viewport-segment-top 视口段顶部相对于视口顶部的偏移量。通常为 0。
viewport-segment-left 视口段左侧相对于视口左侧的偏移量。对于第一个屏幕,通常为 0。对于其他屏幕,则等于前面所有屏幕的宽度之和。
viewport-segments 这个属性允许你定义一个自定义的视口分段,它允许你根据特定的需求来分割视口。这在处理非传统的屏幕布局或需要特定分段逻辑的情况下非常有用。例如,你可能需要创建一个视口分段来容纳特定的UI元素或内容区域。 它接受一个或多个 <segment() 函数,每个函数定义一个视口段。

注意: 这些环境变量,目前还处于实验阶段,需要浏览器开启相应的实验性功能才能使用。

小试牛刀:让按钮不再被“腰斩”

咱们先来一个简单的例子,解决上面提到的按钮被“腰斩”的问题。

假设我们有一个按钮:

<button class="my-button">点我啊!</button>

我们希望这个按钮始终居中显示,即使在折叠屏上,也不要被屏幕中间的缝隙给劈开。

.my-button {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  /* 关键代码 */
  margin-left: calc(env(viewport-segment-left, 0px) - env(safe-area-inset-left, 0px));
}

代码解读:

  • position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);:这部分代码,让按钮相对于父元素绝对居中。
  • margin-left: calc(env(viewport-segment-left, 0px) - env(safe-area-inset-left, 0px));:这行代码是关键。
    • env(viewport-segment-left, 0px):获取当前视口段左侧的偏移量。如果只有一个屏幕,这个值是 0。如果有多个屏幕,这个值就是第一个屏幕的宽度。
    • env(safe-area-inset-left, 0px):获取安全区域的左侧内边距。这个值用于处理刘海屏等异形屏的情况。
    • calc(...):将两个值相减,得到最终的 margin-left 值。

原理:

通过 viewport-segment-left,我们可以知道当前屏幕是否是第一个屏幕。如果是第一个屏幕,margin-left 值为 0,按钮正常居中显示。如果不是第一个屏幕,margin-left 值就会等于第一个屏幕的宽度,这样按钮就会被推到第二个屏幕的中间,避免被“腰斩”。

更进一步:让内容横跨双屏

再来一个稍微复杂一点的例子,让一个图片横跨双屏显示。

<div class="container">
  <img src="image.jpg" alt="双屏图片">
</div>
.container {
  width: calc(env(viewport-segment-width) * 2); /* 关键代码 */
  height: 100vh;
  overflow: hidden; /* 避免图片溢出 */
}

img {
  width: 100%;
  height: 100%;
  object-fit: cover; /* 让图片填充整个容器 */
}

代码解读:

  • .container { width: calc(env(viewport-segment-width) * 2); }:这行代码是关键。它将容器的宽度设置为两个视口段的宽度之和。这样,容器就会横跨两个屏幕。
  • overflow: hidden;:隐藏超出容器的内容,避免图片溢出。
  • img { width: 100%; height: 100%; object-fit: cover; }:让图片填充整个容器,并保持宽高比。

原理:

通过 viewport-segment-width,我们可以知道每个屏幕的宽度。将容器的宽度设置为两个屏幕的宽度之和,就可以让容器横跨两个屏幕。然后,让图片填充整个容器,就可以实现图片横跨双屏显示的效果。

高级玩法:自定义视口分段

viewport-segments 属性允许你定义自定义的视口分段,这为更精细的布局控制打开了大门。

假设你想要创建一个视口分段,它只占据屏幕的特定区域,例如,你可能想要创建一个侧边栏,它只占据屏幕左侧的 20%。

@media (horizontal-viewport-segments: 2) {
  :root {
    viewport-segments: segment(20vw) segment(auto);
  }

  .sidebar {
    width: env(viewport-segment-width, 20vw);
    position: fixed;
    top: 0;
    left: 0;
    height: 100vh;
    background-color: #f0f0f0;
  }

  .main-content {
    margin-left: env(viewport-segment-width, 20vw);
    padding: 20px;
  }
}

代码解读:

  • @media (horizontal-viewport-segments: 2): 这是一个媒体查询,它只在设备有至少两个水平视口分段时应用样式。
  • :root { viewport-segments: segment(20vw) segment(auto); }: viewport-segments 属性被用来定义两个自定义的视口分段。第一个分段的宽度是 20vw(视口宽度的 20%),第二个分段的宽度是 auto,表示它会占据剩余的可用空间。
  • .sidebar: 侧边栏的宽度被设置为 env(viewport-segment-width, 20vw),这意味着它将占据第一个视口分段的宽度(即 20vw)。它被固定在屏幕的左侧。
  • .main-content: 主要内容的左边距被设置为 env(viewport-segment-width, 20vw),这会将主要内容推到侧边栏的右侧,避免重叠。

原理:

通过 viewport-segments,我们可以自定义视口分段。每个 segment() 函数定义一个视口段。segment(20vw) 创建一个宽度为 20vw 的视口段,而 segment(auto) 创建一个宽度为剩余可用空间的视口段。然后,我们可以使用 env(viewport-segment-width) 来获取这些自定义视口段的宽度,并将其应用于布局。

兼容性问题

说了这么多,最后还是要泼一盆冷水。

Viewport Segments 目前还处于实验阶段,兼容性还不太好。

  • 浏览器支持: 只有少数浏览器支持 Viewport Segments,而且需要在设置中手动开启实验性功能。
  • polyfill: 目前还没有成熟的 polyfill 方案。

所以,在生产环境中使用 Viewport Segments,还需要谨慎考虑。

总结

Viewport Segments 是 CSS 布局的一次重大革新,它为我们提供了更强大的能力,来适配折叠屏、双屏等新型设备。

虽然目前还存在一些兼容性问题,但相信随着技术的不断发展,Viewport Segments 最终会成为 CSS 布局的标配。

要点回顾:

  • Viewport Segments 可以将屏幕分成若干个独立的“段”。
  • 可以通过 env() 函数来获取这些段的宽度、高度、偏移量等信息。
  • 可以利用这些信息,来控制元素的布局,实现更智能的适配。
  • viewport-segments 属性允许自定义视口分段。
  • 目前兼容性还不太好,需要谨慎使用。

希望今天的分享,能让你对 Viewport Segments 有一个更深入的了解。

下次再见,祝大家写码愉快!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注