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.

✔ On screen size ≥ 600px, the desktop image is loaded

✔ 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

✖ 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.