来源:https://blogs.windows.com/msedgedev/
作者:Microsoft Edge Team
浏览器是所有设备上使用最广泛的应用之一,如今,它运行在全新的硬件类别上:双屏和可折叠设备。
随着各种新的双屏和可折叠设备进入市场,包括微软 Surface Duo[1],现在再没有比现在更好的时间来考虑你的网站如何采用这些外形。
今天,我们很高兴地宣布推出两项新的实验性功能,这两项功能将帮助Web开发人员有效地在跨越多个显示区域的浏览器窗口中布局内容,并创建响应式网站,以自然地适应这一类新设备。
CSS screen-spanning media feature[2]和一组环境变量来描述折叠的几何形状。
JavaScript window segments enumeration API[3],在处理Canvas2d和WebGL等非DOM目标时很有用。
可折叠设备类
广义上讲,可折叠设备有两种变体:双屏设备和利用柔性显示技术的单屏设备。两者有很多共同点:它们是便携式的多姿势设备,允许用户旋转,翻转和折叠。按照这种尺寸,应用程序可以位于一侧,也可以跨两个显示区域。响应这种跨越状态的网站与逻辑上划分呈现内容的语义和意图集成在一起。这类设备所实现的广阔的屏幕空间和独特的姿态,让Web开发者可以在一个可以装进口袋或钱包的设备中开启前所未有的网络体验。
从传统的连续屏幕过渡到双屏和可折叠屏
虽然现有的网站会继续使用开箱即用的方式,但让网站意识到设备的可折叠性,可以大大提升用户体验。为了更好地说明这个机会,并展示新创建的浏览器特性是如何工作的,我们将带你增强一个电子邮件客户端布局示例。并排显示收件箱的列表视图和电子邮件的内容是一种常见的模式,自然适合较大的查看区域。当浏览器窗口跨越双屏设备上的两个显示区域时,总的视口宽度很可能与传统的水平平板电脑设备相当。未经修改,电子邮件客户端将继续像往常一样工作。然而,如果我们能够将收件箱和邮件栏与折页对齐,将每个栏目都保持在一个显示区域的边界内,那么体验将得到极大的改善。这样,内容区域都不会被设备铰链切割或遮盖,也不会在柔性显示器的折叠区域上呈现。为了实现理想的布局,我们引入了一个新的 screen-spanning
媒体功能和一组预先定义的环境变量,允许Web开发人员将可折叠设备作为另一个响应式Web设计目标。开发人员现在可以创建适用于每种设备类别的布局,而无需严格依赖特定的硬件参数。这种灵活性提高了可扩展性,因为它不需要为每个新设备类型重复工作。检测显示区域CSS screen-spanning
媒体功能将帮助Web开发人员测试根视口是否被跨越到多个相邻的显示区域,并提供关于这些相邻显示区域的配置细节(如堆叠或并排)。
screen-spanning
媒体功能被指定为一个值,该值描述设备具有的折叠(或铰链)数量及其姿势。如果该设备不是可折叠设备,则该值为none。如果它是可折叠的,则可以具有以下两个值之一:
Single-fold-vertical
:匹配具有单个折叠(两个显示区域)且折叠姿势为垂直的设备。Single-fold-horizontal
:匹配具有单个折叠(两个显示区域)且折叠姿势为水平的设备。
计算显示区域的几何形状
假设当处于 screen-spanning
状态时,折叠总是要把视口正好分成两半,这是不安全的。此外,某些窗口管理器可能会选择隐藏首屏后的Web内容。为了帮助Web开发人员计算每个显示区域的大小,并确保他们知道他们的内容(如果有的话)需要填充多少以避免遮罩,我们正在添加四个预定义的CSS环境变量。
env(fold-top)
env(fold-left)
env(fold-width)
env(fold-height)
这些变量的值是以CSS像素表示的,并且是相对于布局视口而言的(即在客户端坐标中,如CSSOM视图所定义)。当对不处于跨越状态的内容进行评估时,这些值将被视为不存在,并且浏览器将使用传递给env()函数的回退值。
增强我们的电子邮件示例应用程序,以实现双屏和可折叠的体验
让我们将CSS的 screen-spanning
媒体功能和折叠几何环境变量付诸实践,增强我们电子邮件客户端的读者视图。
@media screen and (min-width: 799px) {
/* 特定于平板电脑屏幕的规则 */
}
@media screen and (min-width: 799px) and (screen-spanning: single-fold-vertical) {
/* 主要是一个元素,其中包含上图中突出显示的3个flex项目 */
main {
display: flex;
flex-direction: row;
}
.navigation {
/*
** flex方向是行,因此flex-basis的行为类似于此flex项的宽度
**根据设计,可折叠/双屏上的所需宽度为60px
*/
flex-basis: 60px;
flex-grow: 0;
flex-shrink: 0;
}
.inbox {
/*
** 收件箱宽度会占用第一个显示区域的整个宽度,例如
** 收件箱宽度=显示区域1宽度-60像素(导航列宽度)
*/
flex-basis: calc( env(fold-left) - 60px );
/*
** 有些设备具有遮罩,因此我们需要在此列之后添加边距或间隙
** env(fold-width) = surface Duo上的28个CSS像素。
** env(fold-width) = 0不屏蔽内容的设备上的CSS像素。
*/
margin-inline-end: env(fold-width);
flex-grow: 0;
flex-shrink: 0;
}
.email-content {
/*
** 电子邮件内容栏应 "增长 "以填满其余空间。
** 但要演示如何计算第2个显示区域的宽度。
** 我们将手动设置宽度
*/
flex-basis: calc( 100vw - (env(fold-left) + env(fold-width)) );
flex-grow: 0;
flex-shrink: 0;
}
}
在JavaScript中枚举窗口段
当使用非DOM目标(如Canvas2d或WebGL)时,你可以使用新的 Window Segments Enumeration API
获得每个显示区域的几何体。getWindowSegments()
是Window对象上的一个方法,它返回一个由1个或多个DOMRects组成的数组,这些DOMRects代表每个显示区域的几何形状和位置。返回的数组是该方法被调用时显示区域状态的不可改变的快照。如果用户从跨接状态过渡到非跨接状态,或者旋转设备,则之前检索到的窗口段将无效。
const segments = window.getWindowSegments();
// 案例1:台式机、传统触屏设备、可折叠设备不跨越的问题
console.log(segments.length) // 1
// 案例2:双屏和可折叠
console.log(segments.length) // 2
页面应该监听窗口调整大小(resize
)事件或方向改变(orientationchange
)事件,以检测浏览器是否被调整大小,或设备是否被旋转,并检索更新的显示区域。
let segments = window.getWindowSegments();
// 状态1:浏览器横跨2个显示器,且折叠为垂直。
console.log(segments.length); // 2
// 状态2:用户决定旋转设备,浏览器仍然是跨越的,但现在折叠是水平的。
// 在窗口调整大小时,调整大小和方向改变事件都会被触发
// 当用户进入或退出跨屏状态时,调整大小事件也会触发。
window.addEventListener('resize', () => {
// 我们最初检索的片段已不复存在
// 当折叠为水平时,用表示片段2的最新信息进行更新
segments = window.getWindowSegments();
});
没有明确的方法来了解折叠姿势是垂直还是水平,因为可以从返回的DOMRects中轻松计算出此信息:
function isSingleFoldHorizontal() {
const segments = window.getWindowSegments();
// 单折叠式是指设备有1折叠式和2个显示区域
if( segments.length !== 2 ) {
return false;
}
// 横折指第一段顶部小于第二段顶部
if( segments[0].top < segments[1].top ) {
return true;
}
// if we reach this point, the fold is vertical
return false;
}
同样适用于折叠宽度,Web开发人员可以使用 getWindowSegments()
提供的信息来了解窗口管理器是否掩盖了呈现在折叠后面的内容,以及折叠宽度是否大于零像素。
function foldWidth() {
const segments = window.getWindowSegments();
// 如果有1段,折叠蒙版不适用,返回0
// 如果有超过2个段,我们不处理这种设备,但返回0
if( segments.length !== 2 ) {
return 0;
}
// 折叠是垂直的
// 设备看起来像这样 [][]
if( segments[0].top === segments[1].top ) {
return segments[1].left - segments[0].right;
}
// if we reach this point, the fold is horizontal
return segments[1].top - segments[0].bottom;
}
面向未来
作为开发者,我们在为今天创造的时候,往往会对未来进行规划,所以需要进行最低限度的重构,以解锁未来可能出现的场景。具有2折和3个屏幕的假想设备与CSS不同,JavaScript有数组、循环和条件的概念,这使得窗口段枚举API和有N个显示区域的设备之间的映射更加直接。对于上图所示的假想设备,当浏览器横跨3个显示区域时,调用 getWindowSegments()
方法将返回一个由3个DOMRects组成的数组,使用简单的语言基元,如循环或内置的数组方法,你可以了解更多关于显示区域的配置情况(例如屏幕都是相同的宽度?等)在CSS中,目前的计划是简单地在代表新的屏幕拓扑结构的 screen-spanning
媒体功能中添加新的值。
立即开始增强你的网站的可折叠体验
CSS screen-spanning 媒体功能和 Window Segment Enumeration API是可以在实验性标志后面使用的,你可以在edge://flags/#enable-experimental-web-platform-features处启用它们。从Microsoft Edge 86开始,Web开发者可以使用Microsoft Edge DevTools[4]在Windows和Mac桌面平台上模拟双屏&可折叠设备。另外,你也可以下载并安装新的Surface Duo模拟器预览版[5](2020.806.1或更新版本),在启用实验性平台功能标志后,使用内置的Edge浏览器进行测试和调试。JavaScript Window Segments Enumeration API和 CSS screen-spanning媒体功能均以 Origin Trials 的形式提供,你可以获得代币并在生产中安全地试用这些新基元,以换取我们对 API 的反馈。
前方的路
这些API在Chromium项目、Google、Intel、W3C的CSSWG、第二屏WG等多方合作下,经过多次迭代和改进后,今天就可以供你实验了。我们将桌面平台的CSS和JavaScript基元都贡献给了Chromium开源项目,现在DevTools的可折叠和双屏设备仿真不仅可以在Edge中使用,还可以在Chrome中使用,很快就可以在其他基于Chromium的浏览器中使用。目前,我们正在努力提升Android的实现,使所有基于Chromium的浏览器在Android操作系统上都能支持Web开发人员为这个灵活的设备类别提供令人兴奋的新体验。