feature: Add independent chrome tint elements for iOS 26+ compatibility and enhance related tests
Deploy to Dreamhost (dev) / build (push) Successful in 33s
Sync TODOs with Issues / sync_todos (push) Successful in 6s

This commit is contained in:
Keith Solomon
2026-07-12 14:30:41 -05:00
parent a41f6f3834
commit c82e6187af
4 changed files with 248 additions and 156 deletions
+27 -21
View File
@@ -72,35 +72,41 @@ main#maincontent {
.embed iframe, .embed object, .embed embed, .embed video { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
/*
* Bottom chrome tint.
* Chrome tint elements.
*
* On devices with `viewport-fit=cover` (iOS Safari), the area behind
* the home indicator is part of the page background. The fixed
* pseudo-element below fills the `env(safe-area-inset-bottom)` band
* and shows the footer color when the body has the `.footer-in-view`
* class. That class is toggled by static/js/modules/ChromeTint.js
* when the .site-footer is in view.
* iOS 26+ Safari samples the background-color of position: fixed
* elements within 4px of the top or 3px of the bottom of the viewport
* to tint the browser chrome (status bar / home indicator). The
* elements below are placed inside those sampling windows and their
* backgroundColor is updated at runtime by
* static/js/modules/ChromeTint.js.
*
* No effect on browsers without safe-area-inset-bottom (height resolves
* to 0px and the pseudo-element is invisible).
* The elements have no background by default — they only become
* opaque when the matching element (header / footer) is in view.
* pointer-events: none ensures they never intercept clicks.
*
* (iOS 26 ignores <meta name="theme-color">; this technique is
* what replaced it.)
*/
body::after {
background: var(--color-background);
bottom: 0;
content: "";
height: env(safe-area-inset-bottom);
left: 0;
.chrome-tint {
pointer-events: none;
position: fixed;
right: 0;
transition: background-color 200ms ease;
z-index: 9999;
}
body.footer-in-view::after {
background: var(--color-cwc-blue-02);
.chrome-tint--top {
left: 0;
min-height: 15px;
top: 4px;
/* 4px from top + 15px tall = within the 4px-to-12px sampling window. */
width: 90%;
/* width: 90% > 80% iOS minimum for being sampled. */
}
@media (prefers-reduced-motion: reduce) {
body::after { transition: none; }
.chrome-tint--bottom {
bottom: 3px;
/* 3px from bottom = within the 3px iOS sampling window. */
left: 0;
min-height: 15px;
width: 90%;
}