All of a sudden, my parallax perspective scroll effect did not work anymore in one of my recent web projects. I was not aware of any change, so what happened?
Why my parallax effect suddenly stopped working?
I saw no errors in the browser console, and everything else worked as expected. The website still worked on other devices but not on any desktop browser on my laptop. I had recently switched my operating system's color scheme from dark to light mode.
Diving deeper into the details, I found a CSS feature query that I had added last year to turn off the perspective effect in special cases. Shame on me, as the following code is anything but self-explanatory:
@supports (not (prefers-color-scheme: dark)) {
body.archive .decoration__container,
body.category .decoration__container,
body.search .decoration__container,
body.page.home .decoration__container {
transform: translateZ(0);
}
}
My commit message was even worse:
wip
But the previous commit pointed my to the right direction:
restrict progressive enhancement #59 (WIP)
Issue 59 contained detailed notes and screenshots of a device testing session in which I tried to make the site usable on every device, disabling the perspective effect when in doubt to prevent not being able to scroll on some older iPhones that don't get updated Safari or other web browsers anymore.
Quoting my own issue:
Unresolved aspects
- scroll block on old iPhone restrict progressive enhancement, improve social media fallback #59 #61 #60
- decoration z-index on old iPhone restrict progressive enhancement, improve social media fallback #59 #61 #60
I had merged my "wip" commit as part of a package of "partial fixes", tested and confirmed as "good enough" and "better than before" by several users.
What was that dirty code supposed to do, and where did it come from?
Apple seems to favor a Security through obscurity strategy for its older iPhones, which are outdated by its planned obsolescence policy. There are no modern browsers that people can use on an iPhone 8, and it is impossible to safely find out which buggy mobile Safari browser requests a website. So we either choose not to support outdated browsers or we must fiddle with unreliable "browser hacks" like the one above.
Progressive Enhancement vs. Planned Obsolescence
I was not even trying to make my perspective scroll effect work on the old device. I just wanted to ensure that users could browse and access the site's content using the "forgotten art" of Progressive Enhancement.
CSS Browser Hacks
In a perfect world, we do responsive web development and use media and feature queries only when needed. We don't rely on browsers' user agent strings and don't need any CSS hacks either. In a perfect world, z-index: 2
is enough to ensure an element is displayed on top of its siblings in any web browser since Internet Explorer 6. In a perfect world, people can install a modern mobile browser like Chrome, Chromium, or Firefox that doesn't use an outdated Safari engine due to Apple's software policies.
Many CSS hacks have been tested well and we can be quite sure to rule out undesired false positives when the code involves a vendor-prefixed property like -ms-high-contrast
. Here is a classic example for Internet Explorer 10 and 11:
IE10 and IE11
==================
@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
Detecting specific iPhone or MacOS Safari versions is less stable. I found the following in a DEV post from 2020 as a working but "NOT a recommended solution":
/* Only Safari 10.1+ */
@media not all and (min-resolution:.001dpcm)
{ @supports (-webkit-appearance:none) {
The one that broke my parallax scrolling effect was prone to fail from the start. It was supposed to target mobile iPhone browser engines up to Safari 12 (iPhone 8 or older), but not in Safari 13 and newer.
@supports (not (prefers-color-scheme: dark)) {
What does it even mean? A client that does not support dark color schemes? A client that supports color schemes that are not dark? Chromium does, but this feature query only fired after I did not use the supported dark mode option.
Alternatives to unstable CSS hacks?
Ironically, I could have removed the unstable hack. I had obsoleted it with a similar JavaScript detection that combines the JS equivalent of the same feature query with a user agent string match to restrict it to iPhones only.
var supportsColorSchemeQuery = window.matchMedia('(prefers-color-scheme: dark)');
config.supportsSuppportsColorSchemeQuery = (supportsColorSchemeQuery.matches);
// explicitly disable progressive enhancements to prevent bugs in outdated Apple browsers
// the following query / hack should target mobile Safari up to version 12
if (/iPhone/.test(navigator.userAgent) && config.supportsSuppportsColorSchemeQuery) {
window.kleiderordnung.config.prefersReducedMotion = true;
if (document.body.classList && typeof(document.body.classList.add === 'function')) {
document.body.classList.add('prefers-reduced-motion');
}
}
Now there are two discouraged techniques to rely on, and the code is not nice to read or maintain either. Maybe all modern browsers should implement a feature query isNoF******iPhoneSafariOrInternetExplorer
.
Conclusion?
I don't know. These kind of problems used to be worse in the past. I remember Netscape Navigator, a historic browser notorious for its shortcomings compared to its "browser war" contender, Internet Explorer which seemed much better and more modern, implementing an early DOM interface (document.all
) only to become the notorious legacy browser later.
Standards and best practices have improved much since then. We can do responsive web development with only some CSSmedia queries and feature queries most of the time. Most of my websites work (somehow) in Internet Explorer and probably even Netscape thanks to the web's Robustness principle. Now Apple has become notorious for legacy software. Who will be next?
Top comments (3)
Honestly: I hate Apple for that strategy. They "care" about their user on so many points/topics, but this one is a nightmare.
In a past project, I analyzed these hacks in a huge project, and what it would mean to support a lot of these. My "report" was given to the team. The PO was 😡 and sent it to the architect team. They read multiple pages of (a lot of) concerns, issues and (zero) benefits. Starting from taking a lot of additional testings to breaking changes on everywhere the hacks are used, to check on each iOS updates, etc. They saw the benefits of my solution to just trash it and use another strategy. So it went to the client.
The client was not happy until I showed to him the resources we had to put in and the next version of Safari and that would be used in the next iOS release. Invest was not what was expected, as it was higher each time we had to hack the UI elements. There were already tasks done with hacks, and each one had so many review issues that most of them needed a review each release. It was a crazy pile of super-hacks that might become useless over time or even conflict with other versions, so it had to be redone with another solution.
It was decided to not support these hacks or new/fancy/specific UI stuff on iOS until it was available, older versions were ignored based on analytic data. The client was happy, because all it wanted to have is a nice looking UI on the current iPhone. Only the designer were "frustrated", they needed to document in the component with a single comment: "iOS does not support feature X, until iOS supports it, to-do: review later".
So we cut off a lot of developer time on checking these tasks. The designers only needed to align with the developers on the support, that was just a caniuse link away (added to the docs after first request).
The biggest winner was the QA team. It had so many complaints each time about iPhone tests. They deleted a lot of tests afterward. 😄
That's a pragmatic strategy, although no solution to the underlying dilemma. If only Apple dared to unlock their abandoned products and encourage people to "jailbreak" and maintain alternative open-source operating systems, like LineageOS (formerly known as CyanogenMod) for Android.
I don't support outdated clients officially either, but I try to follow a progressive enhancement strategy for new projects and ensure that optional features are really optional, which also benefits accessibility. But still, I run into bugs like the one that I described. And some Safari fans still get upset when I call it "the new Internet Explorer". ¯\(ツ)/¯
Ironically, my fixed fix introduced a new problem I overlooked despite checking different browsers on different machines in BrowserStack. Conclusion: test, test, test, and if it ain't broke, don't fix it!
I should have followed my own instructions more thoughtfully:
JavaScript equivalent(s) of CSS @supports feature queries for bugfix detection
Ingo Steinke, web developer ・ Oct 11 '23