You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: ApplicationContextMediaFeature/explainer.md
+45-24Lines changed: 45 additions & 24 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -72,31 +72,31 @@ The two concepts of "is this an installed app?" and "what is the current display
72
72
73
73
### Syntax
74
74
75
-
A new CSS media feature named `application-context`, used as an enumerated media feature with discrete values:
75
+
A new CSS media feature named `application-context`, used as a boolean media feature:
76
76
77
77
```css
78
-
@media (application-context: installed) {
78
+
@media (application-context) {
79
79
/* Styles applied only inside an installed app window */
80
80
}
81
81
82
-
@media (application-context: browser) {
82
+
@medianot(application-context) {
83
83
/* Styles applied only in a regular browser tab */
84
84
}
85
85
```
86
86
87
-
The name `application-context` communicates that the feature describes the context in which the application is running, not whether the app is installed on the device globally.
87
+
The name `application-context` communicates that the feature describes the context in which the application is running, not whether the app is installed on the device globally. The feature matches (evaluates to `true`) when the document is running in an installed app window, and does not match (evaluates to `false`) in a regular browser tab.
88
88
89
89
### Behavior Rules
90
90
91
-
1.**Matches`installed`** when the document is in an application context: a top-level browsing context with a manifest applied, presented in its own OS-level app window.
92
-
2.**Remains `installed` regardless of display mode.** Whether the app is in `standalone`, `fullscreen`, or `minimal-ui` mode, the `application-context` media feature continues to match`installed`.
93
-
3.**Only applies to top-level browsing contexts and same-origin iframes.** In cross-origin iframes, the feature matches `browser`. Same-origin iframes inherit the top-level context, since they already have access to the top-level window via `window.top`.
94
-
4.**Matches `browser`in browser tabs.** Even if the same URL has an installed app elsewhere, opening it in a regular browser tab means `(application-context: installed)` does not match. The feature reflects the *current* browsing context, not global installation state.
91
+
1.**Matches** when the document is in an application context: a top-level browsing context with a manifest applied, presented in its own OS-level app window.
92
+
2.**Remains matching regardless of display mode.** Whether the app is in `standalone`, `fullscreen`, or `minimal-ui` mode, the `application-context` media feature continues to match.
93
+
3.**Only applies to top-level browsing contexts and same-origin iframes.** In cross-origin iframes, the feature does not match. Same-origin iframes inherit the top-level context, since they already have access to the top-level window via `window.top`.
94
+
4.**Does not match in browser tabs.** Even if the same URL has an installed app elsewhere, opening it in a regular browser tab means `(application-context)` does not match. The feature reflects the *current* browsing context, not global installation state.
95
95
5.**Usable via `matchMedia()`.** JavaScript can query and listen for changes using `window.matchMedia()`, following standard media query semantics.
@@ -118,7 +118,7 @@ A PWA shows an install banner to browser-tab users but hides it for users alread
118
118
display: flex;
119
119
}
120
120
121
-
@media (application-context: installed) {
121
+
@media (application-context) {
122
122
.install-banner {
123
123
display: none;
124
124
}
@@ -136,7 +136,7 @@ An installed app shows a back button and "open in browser" link that don't make
136
136
display: none;
137
137
}
138
138
139
-
@media (application-context: installed) {
139
+
@media (application-context) {
140
140
.app-nav {
141
141
display: flex;
142
142
}
@@ -148,7 +148,7 @@ An installed app shows a back button and "open in browser" link that don't make
148
148
A site conditionally shows a service worker update prompt only in the installed experience:
149
149
150
150
```js
151
-
if (window.matchMedia('(application-context: installed)').matches) {
151
+
if (window.matchMedia('(application-context)').matches) {
152
152
showUpdatePrompt();
153
153
}
154
154
```
@@ -158,16 +158,16 @@ if (window.matchMedia('(application-context: installed)').matches) {
158
158
Although uncommon, a document could transition between contexts (e.g., a browser tab being "captured" into an app window). Developers can listen for this reactively:
An alternative approach is to define a boolean media feature named `installed`:
170
+
An alternative is to name the boolean media feature `installed` instead of `application-context`:
171
171
172
172
```css
173
173
@media (installed) {
@@ -179,13 +179,32 @@ An alternative approach is to define a boolean media feature named `installed`:
179
179
}
180
180
```
181
181
182
-
This design is simpler to author, following the pattern of other boolean media features like `(hover)` or `(scripting)`. However:
182
+
This name is shorter and follows the pattern of other boolean media features like `(hover)` or `(scripting)`. However:
183
+
184
+
-**Naming ambiguity.** The name `installed` suggests a statement about global installation state. A developer might reasonably expect `(installed)` to be `true` if the app is installed on the device, even when viewed in a browser tab. In reality, the feature only matches when running *inside* an installed app window. The name `application-context` makes this distinction explicit, and describes the current context, not a global property.
185
+
186
+
**Conclusion:** Both names describe the same boolean signal, but `application-context` offers clearer semantics and avoids conflation with global installation state.
187
+
188
+
### An Enumerated Media Feature
189
+
190
+
Rather than a boolean, `application-context` could be defined as an enumerated media feature with discrete values such as `installed` and `browser`:
191
+
192
+
```css
193
+
@media (application-context: installed) {
194
+
/* Styles for an installed app window */
195
+
}
196
+
197
+
@media (application-context: browser) {
198
+
/* Styles for a regular browser tab */
199
+
}
200
+
```
201
+
202
+
An enumerated feature offers an explicit `browser` value and room to add future context values. However:
183
203
184
-
-**Naming ambiguity.** The name `installed` suggests a statement about global installation state. A developer might reasonably expect `(installed)` to be `true` if the app is installed on the device, even when viewed in a browser tab. In reality, the feature would only match when running *inside* an installed app window. The name `application-context` makes this distinction explicit, and describes the current context, not a global property.
185
-
-**Limited extensibility.** A boolean feature can only express two states. If future application contexts emerge, a boolean feature cannot accommodate them without introducing additional media features. An enumerated feature like `application-context` can grow by adding new values.
186
-
-**No `browser` counterpart.** With a boolean feature, styling for the browser-tab case requires `not (installed)`, which is less readable and less intentional than `(application-context: browser)`.
204
+
-**Unnecessary complexity for a binary state.** The installed-versus-browser distinction is fundamentally binary. A boolean feature expresses it more simply: `(application-context)` for the installed case and `not (application-context)` for the browser case, matching the existing pattern of boolean media features.
205
+
-**Speculative extensibility.** The additional values an enumerated feature could accommodate are hypothetical. If new application contexts ever emerge, they can be represented by dedicated media features at that time, rather than designing for them speculatively today.
187
206
188
-
**Conclusion:**While the boolean form is simpler for a binary state check, the `application-context` enumerated approach offers clearer semantics and room to grow.
207
+
**Conclusion:**A boolean feature is the simplest fit for a binary state. The enumerated form adds overhead without a corresponding benefit for the current use case.
189
208
190
209
### Standardizing `navigator.standalone`
191
210
@@ -221,7 +240,7 @@ A dedicated JS property could work, but:
221
240
222
241
### Privacy
223
242
224
-
-**No cross-site information leak.** The feature only reflects the current browsing context. It does not reveal whether the app is installed on the device, only whether the current document is *running* in an app window. A site opened in a browser tab always sees `(application-context: installed)` as non-matching, even if the user has the app installed.
243
+
-**No cross-site information leak.** The feature only reflects the current browsing context. It does not reveal whether the app is installed on the device, only whether the current document is *running* in an app window. A site opened in a browser tab always sees `(application-context)` as non-matching, even if the user has the app installed.
225
244
-**No new fingerprinting surface.** The information exposed (the current app context) is already inferable from existing signals like `display-mode: standalone`, except that `application-context` is stable across display mode changes. It does not expose any new bits of entropy beyond what the user has already disclosed by opening the app window.
226
245
-**Cross-origin iframe isolation.** The feature evaluates to `browser` in cross-origin iframes, preventing embedded third-party content from detecting the host app's installation state. Same-origin iframes are permitted to inherit the top-level context, as they already have full access to the top-level window via `window.top` and do not represent a privacy boundary.
227
246
@@ -247,7 +266,7 @@ Without a built-in property on `Client`, developers would manually relay the app
247
266
```js
248
267
// On page load, inform the service worker of the current app context
@@ -289,11 +308,11 @@ This approach has several drawbacks:
289
308
290
309
### Proposed Extension
291
310
292
-
A natural complement to the `app-context` CSS media feature would be exposing the same information on the [`WindowClient`](https://developer.mozilla.org/en-US/docs/Web/API/WindowClient) interface in the Service Worker API. For example, an `appContext` property:
311
+
A natural complement to the `application-context` CSS media feature would be exposing the same information on the [`WindowClient`](https://developer.mozilla.org/en-US/docs/Web/API/WindowClient) interface in the Service Worker API. For example, a boolean `applicationContext` property:
0 commit comments