šŸŽµ

Viewport and media query based preloading

Originally published at https://medium.com/@francis.john/viewport-and-media-query-based-preloading-87db30ff6d5f

I recently encountered a bug that I couldnā€™t find any information about elsewhere so Iā€™m documented it to hopefully save someone time in the future.

This only applies if you are using theĀ mediaĀ attribute on aĀ <link rel="preload">Ā tag and you are using a media query to only target certain viewports.

The markup

<head>
...
  <link rel="preload" media="(min-width: 600px)" href="desktop.jpg" as="image">
  <link rel="preload" media="(max-width: 599px)" href="mobile.jpg" as="image">
  <meta name"viewport" content="width=device-width, initial-scale=1">
...
</head>

Using this, letā€™s see what gets loaded on different screen sizes.

image

āœ” On screen size ā‰„ 600px, the desktop image is loaded

image

āœ” On screen size < 600px, the mobile image is loaded

So far so good. If you are like me, at this point you might assume that the media query is working correctly. But letā€™s take a look at what happens when we switch to the chrome emulator.

The issue

image

āœ– On chrome mobile emulator, the desktop image is loaded

Well this is confusing. TheĀ desktopĀ image is being preloaded on chromeā€™s mobile emulator (at a device width of 375px). To double check the media query is correct, you can run in the consoleĀ window.matchMedia('(max-width: 599px)').matchesĀ which returnsĀ true.Ā What is happening here?!

What

The solution

It turns out that the browserā€™s preload scanner will not wait for other meta tags to be parsed before evaluating the media query inĀ <link>Ā tags, so in this caseĀ the viewport has not been configured when the media query is evaluated.

Since the viewport has not been set, it works correctly for a shrunken screen size browser, but does not work on a device with smaller device width.

The solution is simpleā€” reorder theĀ <meta name"viewport" content=ā€width=device-width, initial-scale=1">Ā tag to be above the preload tags.To entirely avoid running into this sort of behavior, Iā€™d recommend putting theĀ viewportĀ media query right at the top of the entire<head>Ā tag, just below theĀ <title>Ā .

Happy hacking!