Stop using pixel values in your CSS media queries
Several days ago, I had an epiphany as I was writing CSS media queries. I want to create a Navbar that works differently whether a user is using a mouse or their finger to interact with the screen. I looked up screen sizes for desktop devices, laptops, tablets, and phones. Here is a list of what I found:
- The MacBook air 2018 model has a width of 2560 pixels.
- The Dell XPS 13 2020 has a width of 1920 pixels
- The iPad Pro 12.9" has a width of 2732 pixels in landscape orientation.
- The Samsung Tab S8 Ultra has a width of 2960 pixels in landscape orientation.
- The width of the iPhone 13 pro in landscape orientation is 2532 pixels, and 1170 pixels in portrait orientation.
- Last one I promise :) The width of the Samsung s22 ultra in landscape orientation is 3088 pixels, and 1440pixel in portrait orientation.
At this point, I realized two things. First, omg modern technology is amazing. The screen of a modern smartphone has as many pixels as the screen of a laptop or tablet. Second, how am I supposed to write a pixel/rem/em based media query to target only smartphones and tablets? There must be a better way to address my problem that doesn’t involve writing multiple media queries with few pixels difference between them. There is!
What if we could judge a device by its interaction method, mouse or finger, rather than based on its viewport size? CSS Interaction-based Media queries to the rescue. Modern CSS has a spec for Interaction Media Features that includes three definitions:
- Pointing Device Quality
- Hover Capability
- Rare Interaction Capabilities
For my use case, I only needed to utilize the Pointing Device Quality. Hence this is what I will be explaining here.
“The pointer media feature is used to query about the presence and accuracy of a pointing device such as a mouse. If a device has multiple input mechanisms, the pointer media feature must reflect the characteristics of the “primary” input mechanism, as determined by the user agent.” — W3C
The keyword here is the “accuracy” of the pointing device. A mouse or a drawing stylus is very accurate and has the value of fine. However, a finger or a Kinect peripheral isn’t and takes the value of coarse. Therefore, we can adapt our UI elements to the user’s pointer capabilities. This is useful to adapt our UI elements to viewports with different interaction capabilities. Here is an example of the code I wrote:
Please note that depending on where you are viewing this post, on a device that supports touch or doesn’t the codepen viewport will behave differently.
Lastly, you can combine interaction queries with px/rem/em queries to create CSS media queries that work on devices with specific view port width and interaction devices.
Thank you for reading about my journey to create a better CSS media query. I hope I taught you something new and didn’t just waste your time!