Mercadona from mobile
2020-01-19 17:00 #commit
I usually buy at Mercadona: it’s my home’s nearest supermarket, it has reasonable prices and I know where are located the products I buy so I can purchase everything quickly. When I go to another Mercadona it takes me twice as long to do it; I’ve always dreamed with a Google Maps-like app which guided me through the shortest route through the aisles to get the products, but this is something which supermarket’s owners would like to avoid: they want us to wander through the supermarket, not to save our time.
I don’t buy online at Mercadona, but sometimes I need to check if they sell a product or the price of it. When I access Mercadona’s web using my mobile, I’m exasperated to find this screen:
I don’t want to install Mercadona’s app in my device, neither I think it’s needed. With today’s Web technologies you can have a very good buying experience without the need to install an application. If you’re a regular customer the app will work smoothly and perhaps it will be a good option, but I feel excluded and forced when I see that screen. I’m sure it’s a business decision: the team at Mercadona Tech is very good and they know how to build such a web app.
But I want to access Mercadona’s web from my mobile; as a developer, I started to seek for a way to do it. I’m not a frontender, but I thought they were using a library or a complex function to detect if it was being accessed from mobile devices. If I could find out the criteria they were using, perhaps I could fake it somehow.
The solution was simpler than I believed: it was checking only screen width. Below 978px it detected the device as mobile and showed the above screen. It happened in desktop browsers too, so they weren’t performing a complex checking like user-agent strings, etc. That helped me a lot: using my tablet in landscape mode would allow me to use the web.
But, what about my phone? Was there a way to access the web? After some research I found a way: in Firefox, I could go to about:config and change layout.css.devPixelsPerPx to 1. With that, I could use Mercadona’s web (and screwed up the display of all web pages) Why did that work and why it had that behaviour?
It has to be with how to measure things on web pages.
When I was younger and things were simpler, there were only pixels. We all had CRT monitors capable of displaying from 640x480 to 1024x768 pixels. If you had a 1024x768 monitor you were at the top of the range (if you were using a graphics operating system like Windows 3.11 you were working with top tech)
Once the web arrived, things were measured in pixels. If your image had 320px width, it would occupy half of a 640px screen. And so on. You had three different screen resolutions to support, and usually, webs weren’t accessible below 800x600px; two resolutions to support, it was all.
Nowadays you have an apparently infinite number of resolutions to support: from 4K monitors to tablets and mobiles, and your web should display properly on all of them (that’s the purpose of responsive design and media queries) But you have another problem which has to be with measurement: display density. That terms refer to the number of pixels you have in a given size, usually an inch, and it’s measured in points per inch or dots per inch (ppi/dpi)
Pixels don’t have the same size on all devices. For example, if you have a 15’’ monitor with a resolution of 1024 each pixel will have 15/1024 = 0.015 inches width (you will have 1/0,015= pixels per inch, that is, a dpi of 66dpi). If you have same resolution on a 19’’ monitor, the size of the pixels would be 19/1024 = 0,018 (16% wider and a dpi of 1/0.018=55 dpi). But if you have a mobile phone 3’’ width, each pixel will be 3/1024 = 0,003 width (333dpi). Too small to see it well. As dpi grows, things look smaller.
If we measured pixels as before, we should change the size of each element to match different devices' dpis. The solution to this was elegant: pixel was redefined to represent not a device pixel, but a fraction of an inch. Each pixel is now 1/96th of an inch. The browser adjusts the size of the screen’s elements to do this. We can also use different absolute measures as cm and inches directly [1]
That’s the theory. In practice, all of this is bullshit. Let’s check it with a simple codepen example. I’ve created four squares: red squares are 100px width. Blue squares are 1.041666in. All of them should have the same size (because 100px = 100*1/96 inches) Does that work? Yes, they have the same size:
1 1/8'' aprox. |
6/8'' aprox. |
6/8'' aprox. |
Bullshit. They don’t measure 1'', and they don't have the same measure on each device. Maybe it has an explanation, but I think this is the kind of shit a frontender designer must fight daily. Those are the kinds that make me hate frontend development.
But, returning to Mercadona’s web. My mobile device has 1080 px width (1920px using it in landscape mode) So why is the mobile browser detecting less than 978 pixels? It should show the real web and not the fuck-you-and-install-the-app screen. However, you can see that viewport size is 360px, one-third of real resolution, and much less than the 978px required by Mercadona. That is because the browser is using 3 device pixels to draw each of the web’s pixels. That ratio is what “devPixelsPerPx” property controls. I think that when you set the value to -1 (and 0, which seems to have the same effect) the browser uses some algorithm to detect the optimum ratio. Augmenting the ratio has the effect that webs’ elements look bigger, so elements have the same relative aspect to our eyes.
It seems that you can set a fractionary number for that property, but not using an integer number of device pixels for each web pixel would result in a blurry image when rendering the web.
One last check: what about the same device but a different browser? Let’s see on my mobile phone:
6/8'' aprox. |
6/8'' aprox. |
6/8'' aprox. |
And on my laptop:
11/16'' aprox. |
11/16'' aprox. |
The images are the same size, so it seems that measures are consistent across browsers but no across devices (the font is smaller in chrome, but I will investigate it another time; fonts are another world)
That’s it. Now I can check from my mobile if Mercadona sells chickpea flour wherever I will be if I want to cook some falafel (hint: they don’t, but you don’t need it if you have chickpeas and a Thermomix)