{"id":2313,"date":"2022-03-10T11:19:40","date_gmt":"2022-03-10T19:19:40","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/surface-duo\/?p=2313"},"modified":"2022-03-10T11:19:40","modified_gmt":"2022-03-10T19:19:40","slug":"dual-screen-web-edge","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/surface-duo\/dual-screen-web-edge\/","title":{"rendered":"Microsoft Edge dual-screen web APIs"},"content":{"rendered":"<p>\n  Hello dual-screen web developers!\n<\/p>\n<p>\n  Microsoft Edge version 97 included the dual-screen web APIs that have been in preview since last year. Now Microsoft Surface Duo users with the latest Edge will get an enhanced web experience automatically when sites have implemented the CSS or JavaScript dual-screen APIs. Visit the <a href=\"https:\/\/docs.microsoft.com\/dual-screen\/web\/\">dual-screen web documentation<\/a> for more information on the APIs, as well as how to test on devices, emulators, and using desktop browser developer tools!\n<\/p>\n<p>\n  Today\u2019s post discusses the APIs you can use to adapt your content to dual-screen devices using either CSS or JavaScript.\n<\/p>\n<h2>Dual-screen CSS<\/h2>\n<p>\n  The CSS support for Surface Duo is a combination of dual-screen-aware media queries and environment variables:\n<\/p>\n<ul>\n<li><strong>Media queries<\/strong> &#8211; the dual-screen-aware media queries define styles that are only applied to the page when being viewed on a specific device layout, such as two viewports side-by-side as in the screenshot below.\n  <\/li>\n<li><strong>Environment variables<\/strong> \u2013 the dual-screen-aware environment variables describe the dimensions of each viewport, when more than one viewport is present. These values can be used to position elements relative to the hinge or fold between the viewports.\n  <\/li>\n<\/ul>\n<p><a href=\"https:\/\/conceptdev.github.io\/web-samples\/dual-screen-css\/boxes-future.html\">This example<\/a> shows a real-world implementation of the <a href=\"https:\/\/github.com\/MicrosoftEdge\/MSEdgeExplainers\/blob\/main\/Foldables\/explainer.md#colored-boxes-absolutely-positioned\">colored boxes absolutely positioned<\/a> section of the <a href=\"https:\/\/github.com\/MicrosoftEdge\/MSEdgeExplainers\/blob\/main\/Foldables\/explainer.md\">Foldables explainer<\/a>:\n<\/p>\n<p>\n  <img decoding=\"async\" width=\"722\" height=\"578\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2022\/03\/graphical-user-interface-text-application-white.png\" class=\"wp-image-2314\" alt=\"Surface Duo showing Microsoft Edge with the dual-screen demo web page of colored boxes\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2022\/03\/graphical-user-interface-text-application-white.png 722w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2022\/03\/graphical-user-interface-text-application-white-300x240.png 300w\" sizes=\"(max-width: 722px) 100vw, 722px\" \/><br \/><em>Figure 1: Colored boxes example in Microsoft Edge on Surface Duo 2<\/em>\n<\/p>\n<h3>Dual-screen media queries<\/h3>\n<p>\n  CSS media queries provide a way to selectively apply styles when the browser or device matches one or more rules. Examples include specifying styles only for the print media type, or styles that apply at different viewport widths. The dual-screen support available in Microsoft Edge extends this capability to detecting <em>how many<\/em> viewport segments exist, so that styles can be applied only when viewing on a dual-screen device.\n<\/p>\n<p>\n  There are two media expressions available \u2013 one that applies to the viewports side-by-side and another when the viewports are vertically arranged. This can be helpful when implementing different <a href=\"https:\/\/docs.microsoft.com\/dual-screen\/introduction\">dual-screen UX patterns<\/a> based on the device\u2019s posture \u2013 for example you might wish to create a book-like reading experience when the screens are side-by-side, but treat both screens as endless scrolling content in the vertical posture.\n<\/p>\n<p>\n  The CSS syntax for these device postures matches the number of segments in a horizontal or vertical direction:\n<\/p>\n<pre>@media (horizontal-viewport-segments:2) { \r\n  \/* styles for side-by-side *\/ \r\n}\r\n@media (vertical-viewport-segments:2) { \r\n  \/* styles for vertical layout *\/ \r\n}<\/pre>\n<p>\n  <img decoding=\"async\" width=\"800\" height=\"484\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2022\/03\/graphical-user-interface-description-automaticall.png\" class=\"wp-image-2315\" alt=\"Two stylized Surface Duo representations in different orientations - horizontal and vertical\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2022\/03\/graphical-user-interface-description-automaticall.png 800w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2022\/03\/graphical-user-interface-description-automaticall-300x182.png 300w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2022\/03\/graphical-user-interface-description-automaticall-768x465.png 768w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><br\/><em>Figure 2: viewport-segments media expressions<\/em>\n<\/p>\n<p>\n  The expressions can be combined, such as this CSS which detects a viewport that has <em>exactly<\/em> two segments that are side by side (although no currently shipping devices require this level of specificity):\n<\/p>\n<pre>@media (horizontal-viewport-segments: 2) and (vertical-viewport-segments: 1) {\r\n  \/* styles for side-by-side *\/ \r\n}<\/pre>\n<p>\n  Notice that when Surface Duo is vertically oriented, the top viewport segment (A) is smaller than (B) because of the address bar. You should never assume that the two segments are the same size, but instead use the environment variables explained below to determine the size of each area.\n<\/p>\n<h2>Dual-screen environment variables<\/h2>\n<p>\n  Once you\u2019ve decided to customize the page layout based on multiple viewport segments, you\u2019ll want to position elements to adapt to the device\u2019s orientation and hinge position. The dual-screen web support includes size additional environment variables that you can incorporate into your style sheets, which describe the dimensions of each viewport segment:\n<\/p>\n<pre>env(viewport-segment-width x y)\r\nenv(viewport-segment-height x y)\r\nenv(viewport-segment-top x y)\r\nenv(viewport-segment-left x y)\r\nenv(viewport-segment-bottom x y)\r\nenv(viewport-segment-right x y)<\/pre>\n<p>\n  The values are indexed, with the \u2018top left\u2019 viewport in any orientation always being <code>0 0<\/code>. Figure 3 illustrates the correct indexes for the viewports in each device posture.\n<\/p>\n<p>\n  <img decoding=\"async\" width=\"800\" height=\"485\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2022\/03\/stylized-surface-duo-device-mockups-showing-the-co.png\" class=\"wp-image-2316\" alt=\"Stylized Surface Duo device mockups showing the correct indexes for each screen, to be used with the environment variables syntax in CSS.\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2022\/03\/stylized-surface-duo-device-mockups-showing-the-co.png 800w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2022\/03\/stylized-surface-duo-device-mockups-showing-the-co-300x182.png 300w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2022\/03\/stylized-surface-duo-device-mockups-showing-the-co-768x466.png 768w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/>\n<\/p>\n<p><em>Figure 3: viewport-segment environment variables<\/em>\n<\/p>\n<p>\n  These values are only available when used inside a viewport segments expression, but you can use the environment variable\u2019s fallback parameter to set the default:\n<\/p>\n<pre>env(viewport-segment-width 0 0 300px)\r\n<\/pre>\n<h2>JavaScript<\/h2>\n<p>\n  The dual-screen JavaScript support is exposed via a new window property <code>visualViewport<\/code>, and its <code>segments<\/code> property. When <code>segments<\/code> is not <code>null<\/code> it will return an array of rectangles that describes the bounds of the two screens, which you can use to align elements on the page and avoid the obscured hinge area on some devices. This simple function shows the segment values in the console:\n<\/p>\n<pre>\r\nfunction printWindowSegments() {\r\n   const screens = window.visualViewport.segments;\r\n   if( segments &amp;&amp; segments.length &gt; 1 ) { \/\/ device has a hinge or fold\r\n      console.table(screens);\r\n    }\r\n}\r\nwindow.addEventListener(\"resize\", () =&gt; { \/\/ recalculate when size changes (could be spanned or unspanned)\r\n    printWindowSegments();\r\n});\r\nprintWindowSegments();<\/pre>\n<p>\n  The JavaScript <code>console.table<\/code> method makes it easy to visualize the value of the <code>segments<\/code> property, and also to see the difference between <a href=\"https:\/\/docs.microsoft.com\/dual-screen\/web\/emulator-device-testing\">testing on a Surface Duo 2 device<\/a> where the address bar reduces the size of the first viewport and <a href=\"https:\/\/docs.microsoft.com\/dual-screen\/web\/desktop-developer-tools\">developer tools in the browser<\/a> which does not simulate the address bar, and uses the dimensions of the original Surface Duo, as shown in Figure 4.\n<\/p>\n<p>\n  <img decoding=\"async\" width=\"800\" height=\"287\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2022\/03\/table-description-automatically-generated.png\" class=\"wp-image-2317\" alt=\"Screen of web browser developer tools console, showing two tables of screen dimensions from the window.visualViewport.segments property\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2022\/03\/table-description-automatically-generated.png 800w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2022\/03\/table-description-automatically-generated-300x108.png 300w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2022\/03\/table-description-automatically-generated-768x276.png 768w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><br \/><em>Figure 4: JavaScript console output (device versus devtools)<\/em>\n<\/p>\n<h2>Learn more at An Event Apart<\/h2>\n<p>\n  Join Stephane Stimac the <em>An Event Apart<\/em> online conference to learn more about <a href=\"https:\/\/aneventapart.com\/event\/spring-summit-2022#s32416\">Design and Development Considerations for Dual Screen Devices<\/a> on Monday April 18<sup>th<\/sup>.\n<\/p>\n<p>\n  You can <a href=\"https:\/\/store.aneventapart.com\/register\/2022\/spring-summit\">register online for the Spring Summit<\/a> that runs from April 18<sup>th<\/sup> \u2013 20<sup>th<\/sup>.\n<\/p>\n<h2>Resources and feedback<\/h2>\n<p>\n  These dual-screen capabilities have also been exposed in <a href=\"https:\/\/devblogs.microsoft.com\/surface-duo\/dual-screen-web-angular\">Angular<\/a> and <a href=\"https:\/\/devblogs.microsoft.com\/surface-duo\/dual-screen-react-web\/\">React<\/a>.\n<\/p>\n<p>\n  Check out the <a href=\"https:\/\/docs.microsoft.com\/dual-screen\/\" target=\"_blank\" rel=\"noopener\">Surface Duo developer documentation<\/a> and <a href=\"https:\/\/devblogs.microsoft.com\/surface-duo\/\" target=\"_blank\" rel=\"noopener\">past blog posts<\/a> for links and details on all our samples. \n<\/p>\n<p>\n  If you have any questions, or would like to tell us about your dual-screen websites or PWAs, use the <a href=\"http:\/\/aka.ms\/SurfaceDuoSDK-Feedback\" target=\"_blank\" rel=\"noopener\">feedback forum<\/a> or message us on Twitter <a href=\"https:\/\/twitter.com\/surfaceduodev\" target=\"_blank\" rel=\"noopener\">@surfaceduodev<\/a>.\u00a0\n<\/p>\n<p>\n  Finally, please join us on <a href=\"https:\/\/twitch.tv\/surfaceduodev\" target=\"_blank\" rel=\"noopener\">Twitch<\/a> on Friday 11<sup>th<\/sup> March at 11am Pacific time to discuss this post.\u00a0<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hello dual-screen web developers! Microsoft Edge version 97 included the dual-screen web APIs that have been in preview since last year. Now Microsoft Surface Duo users with the latest Edge will get an enhanced web experience automatically when sites have implemented the CSS or JavaScript dual-screen APIs. Visit the dual-screen web documentation for more information [&hellip;]<\/p>\n","protected":false},"author":570,"featured_media":2314,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[531,412,46,530],"class_list":["post-2313","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-surface-duo-sdk","tag-css","tag-javascript","tag-surface-duo","tag-web"],"acf":[],"blog_post_summary":"<p>Hello dual-screen web developers! Microsoft Edge version 97 included the dual-screen web APIs that have been in preview since last year. Now Microsoft Surface Duo users with the latest Edge will get an enhanced web experience automatically when sites have implemented the CSS or JavaScript dual-screen APIs. Visit the dual-screen web documentation for more information [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/posts\/2313","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/users\/570"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/comments?post=2313"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/posts\/2313\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/media\/2314"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/media?parent=2313"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/categories?post=2313"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/tags?post=2313"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}