Современная асинхронная загрузка CSS

Самый простой способ загрузить CSS в HTML-документ заключается в использовании тега link и атрибута rel="stylesheet":

<link rel="stylesheet" href="mycssfile.css">

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

Способы асинхронной загрузки CSS

Существует несколько способов заставить браузер загружать CSS асинхронно.

Первый способ (работает в современных браузерах) заключается в использовании JavaScript для создания и вставки ссылки на файл CSS в DOM:

// Создаем ссылку на таблицу стилей
var myCSS = document.createElement( "link" );
myCSS.rel = "stylesheet";
myCSS.href = "mystyles.css";
// вставляем ее в конце блока head
document.head.insertBefore( myCSS, document.head.childNodes[ document.head.childNodes.length - 1 ].nextSibling );

Второй способ заключается в том, чтобы задать  атрибуту media в теге link значение, которое не соответствует устройству пользователя. Например, media="print".

В результате браузеры будут воспринимать стили для неиспользуемых устройств как низкоприоритетные. Поэтому они будут загружать стили, не блокируя рендеринг страницы.

Но чтобы задействовать асинхронно загруженные стили, нужно использовать JavaScript-обработчик события onload. Это позволит изменить значение media на соответствующее браузеру и устройству пользователя. Например, screen или all:

<link rel="stylesheet" href="mystyles.css" media="nope!" onload="this.media='all'">

Примечание: мы используем комбинацию перечисленных выше приемов в библиотеке loadCSS.js, предназначенной для обработки асинхронной загрузки CSS. А также обходные пути для устаревших версий браузеров, которые не поддерживают события onload в элементах link.

Также можно загружать CSS асинхронно, используя значение rel="alternate stylesheet". Оно используется для того, чтобы предложить пользователю альтернативное представление сайта:

<link rel="alternate stylesheet" href="mystyles.css" onload="this.rel='stylesheet'">

Методы, описанные выше, работают. Но у них есть один общий недостаток: они используют JavaScript.

Современный метод

Существует решение, созданное специально для асинхронной загрузки CSS файлов: rel="preload". Но даже этот вариант использует обработчик события onload.

Ниже приведен использования rel="preload":

<link rel="preload" href="mystyles.css" as="style" onload="this.rel='stylesheet'">

Значение атрибута rel="preload" заставляет браузеры (которые его поддерживают) загружать, но не применять указанный файл. Поэтому необходим обработчик события onload, чтобы установить атрибут rel в значение stylesheet после загрузки.

Вариант с rel="preload" имеет одно важное преимущество: браузеры начнут загружать CSS раньше, чем при использовании подхода с несоответствующим значением атрибута media.

Использование rel=preload c loadCSS

Поддержка rel="preload" браузерами, ну… спасибо, что хотя бы Google Chrome его поддерживает. Другие популярные браузеры находятся на пути к этому.

Но мы можем обеспечить поддержку rel = 'preload' с помощью полифиллов.  Проект loadCSS предлагает скрипт cssrelpreload.js, который заставляет rel="preload" работать в браузерах, которые не поддерживают его по умолчанию.

Пошаговое руководство по использованию cssrelpreload.js можно найти в readme проекта. Ниже приведен пример применения скрипта:

<link rel="preload" href="mystyles.css" as="style" onload="this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="path/to/mystylesheet.css"></noscript>
<script>
/*! loadCSS rel=preload polyfill. [c]2017 Filament Group, Inc. MIT License */ (function(){ ... }());
</script>

loadCSS можно найти на Github и NPM.

Пожалуйста, оставляйте ваши отзывы по текущей теме статьи. Мы очень благодарим вас за ваши комментарии, лайки, подписки, отклики, дизлайки!