Самый простой способ реализации асинхронной загрузки CSS

Загружать CSS так, чтобы не задерживать рендеринг страниц – один из эффективных способов повысить производительность веб-страниц. В этой статье я опишу лучший способ реализации асинхронной загрузки.

Код

Зная, как браузер обрабатывает различные атрибуты тега link, мы можем добиться асинхронной загрузки CSS с помощью короткой строки HTML-кода:

<link rel="stylesheet" href="/path/to/my.css" media="print" onload="this.media='all'">

Разбираемся…

Атрибуту media элемента link присвоено значение print. Оно указывает применять стили подключенного CSS-файла, когда пользователь хочет распечатать веб-страницу.

При этом таблица стилей должна применяться ко всем элементам страницы, а не только к печатным. Но установив значение media, которое не соответствует текущей среде, можно заставить браузер загрузить CSS без задержки рендеринга страницы – асинхронно!

Также необходимо, чтобы CSS-код применялся к версии файла, отображаемой на экране. Для этого можно использовать атрибут onload, чтобы установить атрибут media в значение all после окончания загрузки.

Разве rel=preload не может сделать то же самое?

Последние несколько лет мы использовали link[rel=preload] вместо rel=stylesheet, чтобы реализовать переключение атрибута rel после загрузки вместо атрибута media.

Но этот метод имеет несколько недостатков, которые необходимо учитывать при использовании preload. Не все браузеры поддерживают <link rel="preload">. Поэтому для извлечения и применения CSS в разных браузерах нужно использовать полифилл. Такой, как используется в loadCSS.

Кроме этого preload извлекает файлы слишком рано, откладывая загрузку других важных ресурсов. Извлечению файлов отдается слишком высокий приоритет, который не слишком важен для критического CSS.

Но если необходимо высокоприоритетное извлечение, которое обеспечивает rel=preload, его можно объединить с кодом, который мы рассмотрели ранее:

<link rel="preload" href="/path/to/my.css" as="style">
<link rel="stylesheet" href="/path/to/my.css" media="print" onload="this.media='all'">

Этот код прост и понятен, поэтому мы предпочитаем использовать его вместо полифила.

Почему не стоит использовать атрибут media?

Когда браузеры сталкиваются с неподходящими типами медиа, они обрабатывают их одинаково – загружают файл. Но некоторые браузеры начинают учитывать различие между несоответствующими и недопустимыми типами медиа.  Поэтому они не запрашивают файлы, связанные с использованием недопустимых типов медиа. Но в целях безопасности мы рекомендуем использовать несоответствующее типу содержимого значение атрибута media. Например, print.

loadCSS может не понадобиться…

Мы продолжаем поддерживать loadCSS и считаем его полезным в некоторых ситуациях. Особенно для программного извлечения CSS-файла из Java Script. Например: loadCSS("/path/to/my.css"). Если вы уже используете loadCSS или шаблон его полифилла rel=preload, не нужно ничего менять. Он использует ту же технику, которая была описана в этой статье.