Cross-platform Web Application Development

  • UUID: 33bf27be-ba09-42dc-a6b8-07462212ad53
  • Timestamps
    • 20231208.Started this article

So what does "cross-platform" together with "web" mean? Does "web" already mean "cross-platform"? Jein, so to say in German. Web applications nowadays is still the counter-part of platform dependent native applications. However, because of the different runtimes on different web browsers, web applications do not work automatically the same on all platform. In fact, they almost always work differently on different devices as there are also concepts as responsive design or mobile or desktop first way of thinking in the realm of web applications. But GUI representation aspects are not the core topic in this article. This artice focus more on the functionality or engine aspects of web applications. Of the difference, in worst cases, certain applications work well on some platforms but crashes on other platfoms, such as the gif-player powered web pages at JH-Articles:attachments/20231205.gif-player. (If you open the link on an iPhone (touch, scroll and wait a while), it could very much likley crash your web browser in use. Like it had always been so on my iPhone.) (By the way, gif-player was a great HTML custom element developed by the Canadian developer Simon Green (CaptainCodeman) about 6 years ago. It offers the possibility to pause the GIF image at certain frame decided by the mouse pointer location.)

gif-player crashes iPhone Safari
gif-player crashes iPhone Microsoft Edge (essentially also Safari as the web engine)

I haven't been successful diagnose the root cause of such a crash as iPhone Safari developer tool didn't give me a clue. But certainly, it is an example that different web runtimes offer different results to the same web application implementation. Another common complainment on the Internet about iPhone or iPad Safari is the support for Web Audio API, things around the AudioContext. Also because of the very problematic Web Audio API implementation in iPhone and iPad Safari, I also need to distinguish a bit in the implementation for iPhone and iPad. As a result, on iPhone and iPad, there is no audio visual representation available. (Because when using the MediaElementAudioSourceNode as the source node for AudioContext, there is unpredictable sound issues on iPhone and iPad, but it works just well on Windows, macOS or Android.)

qia-audio-clip on Mac Microsoft Edge
qia-audio-clip on iPhone Safari

In short, cross-platform web application development means specifically making alternative implementations targetting at different web vrowser runtimes. I think there is already enough told about the what and the necessity, but how?

Runtime Detection

The first thing to do in oder to target is to get to know what runtime the web application is at. Unfortunitely, there is no super intuitive or direct easy way to make the detection. In the scope of this topic, there are already countless discussions on the Internet, mostly people mention APIs including navigator.platform, navigator.userAgent, and navigator.maxTouchPoints. But they are all not perfect. Considering the navigator.platform is told as "deprecated" (as also not honestly implemented), the navigator.userAgent is commonly uncertain or faked, and the navigator.maxTouchPoints is also a topic for touchscreen Windows PCs although macOS PCs have no touch support as of today.

With CSS Media Query API in JavaScript, fortunitely, we have more tools to use, which include things like window.matchMedia('(pointer: fine)').matches and window.matchMedia('(hover: hover)').matches.

So, modern solution to detect runtime would be wise combinations of multiple APIs. And be awere, the topic is targetting at runtimes instead of devices or platforms. Unfortunitely, the answer to the how is not a simple answer. Because "wise combinations" is still an uncertain term. But some examples may help.


I am still planning to write a separated article about qia-gif, so there is not one available for the moment. Basically, qia-gif is a wrapper HTML custom element of gif-player as mentioned above. The qia-gif will use gif-player to represent GIF images when it is used at a runtime where there is precise pointer and convenient hover but use the fallback/default basic img to represent GIF images where there is no frame-pause feature. To see it live, read this article on different devices and check the following GIF image.


What is the wise combination used for qia-gif to differentiate runtimes? Here is it: window.matchMedia('(pointer: fine)').matches && window.matchMedia('(hover: hover)').matches.

A bit explanation

  • Basic logic:
    • use whitelist to do enhancement
    • use && to ensure accuracy in whitelist
    • so use if (window.matchMedia('(pointer: fine)').matches && window.matchMedia('(hover: hover)').matches) {
    • if (window.matchMedia('(pointer: fine)').matches) {
    • if(window.matchMedia('(hover: hover)').matches) {
      • if(window.matchMedia('(any-hover: hover)').matches) {
        • any-hover is less strict comparing to hover (which means primarily instead of any)
        • window.matchMedia("(any-pointer: fine)").matches returns true on all my mobile browsers and desktop for some reason.
        • window.matchMedia("(any-hover: hover)").matches always returns true too, even on mobile devices without a mouse.


For qia-audio-clip, as already mentioned, the AudioContext on iPhone and iPad Safari does not work as expected as of today. In comparison to whitelist and enhancement in qia-gif, qia-audio-clip adopts the way of thinking as blacklist and restriction. That is to say, when qia-audio-clip is running on iPhone and iPad, it only plays back audio without giving an visual representation of the sound but with a hint to users that better audio experience can be got on Windows, macOS or Andorid.

What is the wise combination used for qia-audio-clip? It is: /iPhone|iPod|iPad/.test(navigator.platform) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 2). Well, to be sincere, it is not wise enough but this is the best I think I can get in consideration of tradeoffs. The iPod is added kind of like a habit, as it is so on the Internet, but the navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 2 part is really the nasty part which worth a bit explanation. Unfortunitely, Apple had the value "MacIntel" for some iPad devices instead of just the "iPad" but the "MacIntel" is also used for macOS PCs. Inside the unfortune, there comes another smaller fortune which is only "MacIntel" iPad supports touchscreen as of 2023, so navigator.maxTouchPoints > 2 is added in the condition. Well, it is not a perfect combination because it doesn't address the future, not forward compatible. I cannot be sure that macOS does not support touchscreen in the future and I also cannot be sure that Apple tvOS does not join the league of "MacIntel" and "maxTouchPoints > 2" in the future. Last but not least, the inperfect version works because it could also be the case that the limitation is only necessary temporarily as iPhone and iPad Safari can catch up with the implementation of Web Audio API, therefore the blacklist patching is no longer needed.


For readers who have reached this part, in case you would like to feel the typical APIs used for runtime detection by your own hands. I have also made a runtime detectin page as JH-Articles:attachments/web-browser-runtime-detection. You can just open the link on different web browsers or different devices to see the different results. The following are results on my devices.

macOS Microsoft Edge
macOS Safari
iPad Safari
iPhone Safari

For even more, there is also a lot of useful information on the Internet.


* cached version, generated at 2024-01-09 14:38:27 UTC.

Subscribe by RSS