From f6159af0b8f5a78f9dbdae1a8b21a369332ea4ef Mon Sep 17 00:00:00 2001 From: Chris Mills Date: Wed, 23 Jul 2025 17:05:09 +0100 Subject: [PATCH 01/11] Add viewport segments api demo --- README.md | 2 + viewport-segments-api/index.css | 194 +++++++++++++++++++++++++++++++ viewport-segments-api/index.html | 42 +++++++ viewport-segments-api/index.js | 54 +++++++++ 4 files changed, 292 insertions(+) create mode 100644 viewport-segments-api/index.css create mode 100644 viewport-segments-api/index.html create mode 100644 viewport-segments-api/index.js diff --git a/README.md b/README.md index 0ea83642..a9139b49 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,8 @@ Code examples that accompany various MDN DOM and Web API documentation pages. - The "touchevents" directory is for examples and demos of the [Touch Events](https://developer.mozilla.org/docs/Web/API/Touch_events) standard. +- The "viewport-segments-api" directory contains an example demonstrating how to use the [Viewport Segments API](https://developer.mozilla.org/docs/Web/API/Viewport_Segments_API). [Run the example live](https://mdn.github.io/dom-examples/viewport-segments-api/). + - The "visual-viewport-api" directory contains a basic demo to show usage of the Visual Viewport API. For more details on how it works, read [Visual Viewport API](https://developer.mozilla.org/docs/Web/API/Visual_Viewport_API). [View the demo live](https://mdn.github.io/dom-examples/visual-viewport-api/). - The "web-animations-api" directory contains [Web Animation API](https://developer.mozilla.org/docs/Web/API/Web_Animations_API) demos. See the [web animations README](web-animations-api/README.md) for more information. diff --git a/viewport-segments-api/index.css b/viewport-segments-api/index.css new file mode 100644 index 00000000..4b07642d --- /dev/null +++ b/viewport-segments-api/index.css @@ -0,0 +1,194 @@ +/* Document styles */ + +html { + font-family: helvetica, arial, sans-serif; + box-sizing: border-box; + height: 100%; +} + +body { + margin: 0; + height: 100%; + background: #ffc8dd; +} + +.wrapper { + height: 100%; + display: flex; +} + +.fold { + background-color: #999; +} + +/* Layout for the two main panes */ + +.wrapper, +.list-view, +.detail-view { + position: relative; +} + +.list-view, +.detail-view { + margin: 20px; + background: white; +} + +.list-view { + overflow: auto; + padding: 0 20px; + border-bottom: 20px solid white; + border-top: 20px solid white; +} + +.detail-view { + display: flex; + flex-direction: column; + justify-content: space-between; + padding: 20px; +} + +ul { + margin: 0; + padding: 0; +} + +ul li { + margin-bottom: 20px; + list-style-type: none; +} + +a { + color: black; + display: block; + padding: 20px; + outline: none; + text-decoration: none; + border: 1px solid rgb(0 0 0 / 0.3); + transition: 0.4s all; +} + +a:hover, +a:focus { + border-left: 20px solid rgb(0 0 0 / 0.3); +} + +ul li:nth-child(odd) { + background: #cdb4db; +} + +ul li:nth-child(even) { + background: #ffafcc; +} + +/* Heading and paragraph styles */ + +h1 { + margin: 0 0 20px; +} + +.posture-output { + background: #cdb4db; + padding: 20px; + margin: 0; + border: 1px solid rgb(0 0 0 / 0.3); +} + +.segment-output { + position: absolute; + top: 0px; + right: 0px; + background: #663880; + color: white; + padding: 10px; + border: 1px solid rgb(0 0 0 / 0.3); +} + +.segment-output h2 { + margin: 0; + font-size: 1.4rem; +} + +.segment-output p { + margin: 10px 0 0 0; +} + +/* Media queries */ + +@media (horizontal-viewport-segments: 1) and (orientation: landscape) { + .wrapper { + flex-direction: row; + } + + .list-view, + .detail-view { + flex: 1; + } + + .fold { + height: 100%; + width: 20px; + } +} + +@media (horizontal-viewport-segments: 1) and (orientation: portrait) { + .wrapper { + flex-direction: column; + } + + .list-view, + .detail-view { + flex: 1; + } + + .fold { + height: 20px; + } +} + +/* Segments are laid out horizontally. */ +@media (horizontal-viewport-segments: 2) { + .wrapper { + flex-direction: row; + } + + .list-view { + width: env(viewport-segment-width 0 0); + } + + .fold { + width: calc( + env(viewport-segment-left 1 0) - env(viewport-segment-right 0 0) + ); + background-color: black; + height: 100%; + } + + .detail-view { + width: env(viewport-segment-width 1 0); + } +} + +/* Segments are laid out vertically. */ +@media (vertical-viewport-segments: 2) { + .wrapper { + flex-direction: column; + } + + .list-view { + flex: 0 0 env(viewport-segment-height 0 0); + } + + .fold { + width: 100%; + height: calc( + env(viewport-segment-top 0 1) - env(viewport-segment-bottom 0 0) + ); + background-color: black; + } + + .detail-view { + flex: 0 0 env(viewport-segment-height 0 1); + } +} diff --git a/viewport-segments-api/index.html b/viewport-segments-api/index.html new file mode 100644 index 00000000..acf55697 --- /dev/null +++ b/viewport-segments-api/index.html @@ -0,0 +1,42 @@ + + + + + + Viewport segments API demo + + + + +
+
+ +
+
+
+

Article one

+ +

device posture:

+
+
+ + diff --git a/viewport-segments-api/index.js b/viewport-segments-api/index.js new file mode 100644 index 00000000..aec9a33c --- /dev/null +++ b/viewport-segments-api/index.js @@ -0,0 +1,54 @@ +const list = document.querySelector("ul"); +const detailHeading = document.querySelector(".detail-view h1"); +const postureOutput = document.querySelector(".posture-output"); + +// Update detail view when list item is clicked on + +list.addEventListener("click", (event) => { + detailHeading.textContent = event.target.textContent; +}); + +// Output device posture when the posture changes + +function reportPostureOutput() { + postureOutput.textContent = `Device posture: ${navigator.devicePosture.type}`; + console.log("event fired"); +} + +reportPostureOutput(); +navigator.devicePosture.addEventListener("change", reportPostureOutput); + +// Output viewport segment details to each segment + +const wrapperElem = document.querySelector(".wrapper"); +const listViewElem = document.querySelector(".list-view"); +const detailViewElem = document.querySelector(".detail-view"); + +function addSegmentOutput(segments, index, elem) { + const segment = segments[index]; + elem.innerHTML += ` +
+

Viewport segment ${index + 1}

+

${segment.width}px x ${segment.height}px

+
+ `; +} + +function reportSegments() { + // Remove all previous segment output elements before adding more + document + .querySelectorAll(".segment-output") + .forEach((segment) => segment.remove()); + + const segments = window.viewport.segments; + + if (segments.length === 1) { + addSegmentOutput(segments, 0, wrapperElem); + } else { + addSegmentOutput(segments, 0, listViewElem); + addSegmentOutput(segments, 1, listViewElem); + } +} + +reportSegments(); +window.addEventListener("resize", reportSegments); From 6e83aed177b9605e5885de9862ab56d720089c51 Mon Sep 17 00:00:00 2001 From: Chris Mills Date: Thu, 24 Jul 2025 11:39:54 +0100 Subject: [PATCH 02/11] Bugfixes --- viewport-segments-api/index.css | 4 ++-- viewport-segments-api/index.js | 23 +++++++++++------------ 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/viewport-segments-api/index.css b/viewport-segments-api/index.css index 4b07642d..39971b19 100644 --- a/viewport-segments-api/index.css +++ b/viewport-segments-api/index.css @@ -116,7 +116,7 @@ h1 { /* Media queries */ -@media (horizontal-viewport-segments: 1) and (orientation: landscape) { +@media (horizontal-viewport-segments: 1) and (vertical-viewport-segments: 1) and (orientation: landscape) { .wrapper { flex-direction: row; } @@ -132,7 +132,7 @@ h1 { } } -@media (horizontal-viewport-segments: 1) and (orientation: portrait) { +@media (horizontal-viewport-segments: 1) and (vertical-viewport-segments: 1) and (orientation: portrait) { .wrapper { flex-direction: column; } diff --git a/viewport-segments-api/index.js b/viewport-segments-api/index.js index aec9a33c..7a992a4d 100644 --- a/viewport-segments-api/index.js +++ b/viewport-segments-api/index.js @@ -12,7 +12,6 @@ list.addEventListener("click", (event) => { function reportPostureOutput() { postureOutput.textContent = `Device posture: ${navigator.devicePosture.type}`; - console.log("event fired"); } reportPostureOutput(); @@ -24,21 +23,21 @@ const wrapperElem = document.querySelector(".wrapper"); const listViewElem = document.querySelector(".list-view"); const detailViewElem = document.querySelector(".detail-view"); -function addSegmentOutput(segments, index, elem) { - const segment = segments[index]; - elem.innerHTML += ` -
-

Viewport segment ${index + 1}

-

${segment.width}px x ${segment.height}px

-
- `; +function addSegmentOutput(segments, i, elem) { + const segment = segments[i]; + + const divElem = document.createElement("div"); + divElem.className = "segment-output"; + + elem.appendChild(divElem); + + divElem.innerHTML = `

Viewport segment ${i + 1}

+

${segment.width}px x ${segment.height}px

`; } function reportSegments() { // Remove all previous segment output elements before adding more - document - .querySelectorAll(".segment-output") - .forEach((segment) => segment.remove()); + document.querySelectorAll(".segment-output").forEach((elem) => elem.remove()); const segments = window.viewport.segments; From 91320021bf456e7221d9402591a9bb7bcac4a405 Mon Sep 17 00:00:00 2001 From: Chris Mills Date: Thu, 24 Jul 2025 14:17:18 +0100 Subject: [PATCH 03/11] Remove unneeded div --- viewport-segments-api/index.html | 38 +++++++++++++++----------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/viewport-segments-api/index.html b/viewport-segments-api/index.html index acf55697..5b52ffa5 100644 --- a/viewport-segments-api/index.html +++ b/viewport-segments-api/index.html @@ -10,26 +10,24 @@
- +
From 0d959b2550f102d16a7eed0d7dbc64025b0ef26f Mon Sep 17 00:00:00 2001 From: Chris Mills Date: Thu, 24 Jul 2025 16:12:56 +0100 Subject: [PATCH 04/11] remove unnecessary MQ conditions --- viewport-segments-api/index.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/viewport-segments-api/index.css b/viewport-segments-api/index.css index 39971b19..420eb2c6 100644 --- a/viewport-segments-api/index.css +++ b/viewport-segments-api/index.css @@ -116,7 +116,7 @@ h1 { /* Media queries */ -@media (horizontal-viewport-segments: 1) and (vertical-viewport-segments: 1) and (orientation: landscape) { +@media (orientation: landscape) { .wrapper { flex-direction: row; } @@ -132,7 +132,7 @@ h1 { } } -@media (horizontal-viewport-segments: 1) and (vertical-viewport-segments: 1) and (orientation: portrait) { +@media (orientation: portrait) { .wrapper { flex-direction: column; } From 3498132292ebfdde92ca4367418f08eb4c1dddc0 Mon Sep 17 00:00:00 2001 From: Chris Mills Date: Thu, 24 Jul 2025 16:24:32 +0100 Subject: [PATCH 05/11] Add listeners to update segment report on posture and orientation change --- viewport-segments-api/index.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/viewport-segments-api/index.js b/viewport-segments-api/index.js index 7a992a4d..76c4e323 100644 --- a/viewport-segments-api/index.js +++ b/viewport-segments-api/index.js @@ -36,6 +36,7 @@ function addSegmentOutput(segments, i, elem) { } function reportSegments() { + console.log("change"); // Remove all previous segment output elements before adding more document.querySelectorAll(".segment-output").forEach((elem) => elem.remove()); @@ -51,3 +52,5 @@ function reportSegments() { reportSegments(); window.addEventListener("resize", reportSegments); +navigator.devicePosture.addEventListener("change", reportSegments); +window.screen.orientation.addEventListener("change", reportSegments); From 85d43fd6aac7284737b3640a3ef1939529c958bb Mon Sep 17 00:00:00 2001 From: Chris Mills Date: Thu, 24 Jul 2025 16:25:11 +0100 Subject: [PATCH 06/11] remove console.log --- viewport-segments-api/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/viewport-segments-api/index.js b/viewport-segments-api/index.js index 76c4e323..3a3a3ff9 100644 --- a/viewport-segments-api/index.js +++ b/viewport-segments-api/index.js @@ -36,7 +36,6 @@ function addSegmentOutput(segments, i, elem) { } function reportSegments() { - console.log("change"); // Remove all previous segment output elements before adding more document.querySelectorAll(".segment-output").forEach((elem) => elem.remove()); From 9f593dc9d2d3b0b17f7d3ddc8c7800886e0e60e7 Mon Sep 17 00:00:00 2001 From: Chris Mills Date: Thu, 24 Jul 2025 16:55:05 +0100 Subject: [PATCH 07/11] Simply vertical segments layout; flex not needed --- viewport-segments-api/index.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/viewport-segments-api/index.css b/viewport-segments-api/index.css index 420eb2c6..e74ce39f 100644 --- a/viewport-segments-api/index.css +++ b/viewport-segments-api/index.css @@ -177,7 +177,7 @@ h1 { } .list-view { - flex: 0 0 env(viewport-segment-height 0 0); + height: env(viewport-segment-height 0 0); } .fold { @@ -189,6 +189,6 @@ h1 { } .detail-view { - flex: 0 0 env(viewport-segment-height 0 1); + height: env(viewport-segment-height 0 1); } } From 9078234e711ccb1d6f17092d9472932e81afa7e4 Mon Sep 17 00:00:00 2001 From: Chris Mills Date: Thu, 24 Jul 2025 17:25:23 +0100 Subject: [PATCH 08/11] Fix element reference --- viewport-segments-api/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/viewport-segments-api/index.js b/viewport-segments-api/index.js index 3a3a3ff9..785b5ff0 100644 --- a/viewport-segments-api/index.js +++ b/viewport-segments-api/index.js @@ -45,7 +45,7 @@ function reportSegments() { addSegmentOutput(segments, 0, wrapperElem); } else { addSegmentOutput(segments, 0, listViewElem); - addSegmentOutput(segments, 1, listViewElem); + addSegmentOutput(segments, 1, detailViewElem); } } From 85b50cf052fcc39e8af1e91dd1603ef54bbf0cf5 Mon Sep 17 00:00:00 2001 From: Chris Mills Date: Fri, 25 Jul 2025 08:49:16 +0100 Subject: [PATCH 09/11] Get rid of unneeded screen orientation handler --- viewport-segments-api/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/viewport-segments-api/index.js b/viewport-segments-api/index.js index 785b5ff0..f4817cbf 100644 --- a/viewport-segments-api/index.js +++ b/viewport-segments-api/index.js @@ -52,4 +52,3 @@ function reportSegments() { reportSegments(); window.addEventListener("resize", reportSegments); navigator.devicePosture.addEventListener("change", reportSegments); -window.screen.orientation.addEventListener("change", reportSegments); From 99f598e2cd29e560f5459db8a434c04ecaea82e8 Mon Sep 17 00:00:00 2001 From: Chris Mills Date: Tue, 5 Aug 2025 11:35:10 +0100 Subject: [PATCH 10/11] Update viewport-segments-api/index.js Co-authored-by: Vadim Makeev --- viewport-segments-api/index.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/viewport-segments-api/index.js b/viewport-segments-api/index.js index f4817cbf..293f6a6e 100644 --- a/viewport-segments-api/index.js +++ b/viewport-segments-api/index.js @@ -1,11 +1,14 @@ -const list = document.querySelector("ul"); +const listLinks = document.querySelectorAll("ul a"); const detailHeading = document.querySelector(".detail-view h1"); const postureOutput = document.querySelector(".posture-output"); // Update detail view when list item is clicked on -list.addEventListener("click", (event) => { - detailHeading.textContent = event.target.textContent; +listLinks.forEach(item => { + item.addEventListener("click", (event) => { + event.preventDefault(); + detailHeading.textContent = event.target.textContent; + }); }); // Output device posture when the posture changes From 1a26bb514e260d03b08153dbdd2314f30764e6c9 Mon Sep 17 00:00:00 2001 From: Chris Mills Date: Tue, 5 Aug 2025 11:35:27 +0100 Subject: [PATCH 11/11] Update viewport-segments-api/index.css Co-authored-by: Vadim Makeev --- viewport-segments-api/index.css | 1 - 1 file changed, 1 deletion(-) diff --git a/viewport-segments-api/index.css b/viewport-segments-api/index.css index e74ce39f..52f10529 100644 --- a/viewport-segments-api/index.css +++ b/viewport-segments-api/index.css @@ -2,7 +2,6 @@ html { font-family: helvetica, arial, sans-serif; - box-sizing: border-box; height: 100%; }