Не используйте @import

Original author: Steve Souders
  • Translation
В данной статье автор Steve Souders приводит наглядные доказательства, почему не стоит использовать import для загрузки стилей в документ.

LINK vs. import


Существует 2 способа загрузки файлов стилей. Использовать тег LINK:
<link rel='stylesheet' href='a.css'>

Или импортировать файлы с помощью import:
<style>
@import url('a.css');
</style>

Я предпочитаю использовать LINK для удобства, т.к. вы должны помнить, что import нужно размещать всегда в самом верху блока стилей, в противном случае они не импортируются.

import import


Я хочу рассказать о различных способах использования LINK и import. В приведенном ниже примере прописаны 2 файла стилей: a.css и b.css. Каждый файл по загрузке занимает ровно 2 секунды, чтобы было удобно отследить влияние на скорость загрузки в дальнейшем. В первом примере используется import для загрузки обоих файлов стилей. В этом примере, называемом import import, HTML документ содержит следующий блок стилей:
<style>
@import url('a.css');
@import url('b.css');
</style>

Если вы всегда будете использовать только import для загрузки стилей, то проблем с производительностью не будет, хотя мы увидим ниже, это может привести к ошибке с JavaScript. Оба файла загружаются параллельно (см. рисунок 1) Но проблемы начинают появляться, если использовать import внутри файла стилей, либо вместе с LINK.

import-import
Рис. 1.

LINK import


В примере LINK import используется тег LINK для загрузки a.css, и import для b.css:
<link rel='stylesheet' type='text/css' href='a.css'>
<style>
@import url('b.css');
</style>

В IE (тестировалось в 6, 7, и 8), это привело к тому, что файлы загружаются последовательно друг за другом, как показано на рисунке 2. Соотвественно, время загрузки страницы в IE увеличится.

link-import
Рис. 2

LINK с import


В примере LINK с import, файл  a.css загружается через LINK, и содержит внутри правило import для b.css:
В документе:
<link rel='stylesheet' type='text/css' href='a.css'>

в a.css:
@import url('b.css');

Этот способ также приводит к тому, что файлы загружаются последовательно (рис. 3.), а не параллельно, но теперь это происходит не только в IE, но и остальных браузерах. Если подумать — все логично: браузер загружает a.css и начинает парсить его. Обнаружив внутри правило import, начинается загрузка файла b.css.

link-with-import
Рис. 3.

Блоки LINK с import


Незначительное отличие от предыдущего примера привело к удивительным результатам в IE. LINK используется для вызова a.css и для нового файла proxy.css, который содержит только import для b.css.
В коде:
<link rel='stylesheet' type='text/css' href='a.css'>
<link rel='stylesheet' type='text/css' href='proxy.css'>

В proxy.css:
@import url('b.css');

Результаты эксперимента в IE показаны на рисунке 4. Первый запрос — HTML документ. Второй запрос -  a.css (2 секунды). Третий — proxy.css. Четвертый — b.css (2 секунды). И вот что удивительно, IE не хочет начинать загрузку b.css, пока файл a.css не будет загружен полностью. Во всех других браузерах такого сюрприза не происходит, что приводит к более быстрой загрузке страницы (см. рисунок 5).

link-blocks-import
Рис. 4. Результаты в IE.

link-blocks-import-not-ie
Рис. 5. Результаты в других браузерах.

Много @imports


Использование сразу нескольких правил import в IE приводит к тому, что файлы загружаются не в том порядке, в котором они указаны в коде. В этом примере используется 6 файлов стилей (каждый из которых загружается по 2 секунды), за которыми следует JS скрипт (4 секунды для загрузки).
<style>
@import url('a.css');
@import url('b.css');
@import url('c.css');
@import url('d.css');
@import url('e.css');
@import url('f.css');
</style>
<script src='one.js' type='text/javascript'></script>

На рис. 6 вы увидите, что самый долгий по загрузке — это скрипт. Несмотря на то что он указан после стилей, в IE он загружается первым. Если в скрипте содержится код, который зависит от применяемых стилей (getElementsByClassName, и т.п.), это может привести к ошибкам работы скрипта, т.к. он загружается прежде чем стили.

many-imports
Рис. 6.

LINK LINK


Проще и безопасней использовать LINK для загрузки стилей:
<link rel='stylesheet' type='text/css' href='a.css'>
<link rel='stylesheet' type='text/css' href='b.css'>

Использование LINK обеспечивает параллельную загрузку файлов во всех браузерах (см. рисунок 7). Применение LINK также гарантирует, что файлы будут загружены именно в том порядке, который указан в коде документа.

import-import
Рис. 7.

Для нас особенно плохо то, что ресурсы могут быть загружены в другом порядке, нежели указано в документе. Все браузеры должны заглядывать наперед перед загрузкой стилей для извлечения правил import и начинать их загрузку немедленно. До тех пор, пока браузеры не реализуют это, я советую избегать использование import и загружать стили только с помощью LINK.

Надеюсь на ваши комментарии также здесь.
Share post

Similar posts

Comments 52

    +4
    Интересно, это будет удобно тогда, когда надо четко определить порядок загрузки. Бывали часто такие ситуации, когда нужно «задержать» загрузку определенной таблицы стиле, пока не загрузиться предыдущая. Спасибо, учту этот момент, до этого всегда использовал исключительно link.
      +2
      Давно не использовал @import и даже не знал что с ним так дела обстоят). Спасибо.
        +2
        Каким образом getElementsByClassName зависит от применяемых стилей? Похоже, соответствующий кусок хабратопика следует переправить.
          +3
          Ну разве что скрипт меняет текущие стили на основании присвоенных в css (типа увеличение left при position: absolute).
            0
            Представьте что скрипт делает следующее:
            document.getElementsById(«mydiv»).style.height

            А стили для #mydiv еще не загружены. Вот в этом и проблема.
              +1
              > Представьте что скрипт делает следующее:
              Чего будет деать? Если присваивать данному выражению значение, оно перекроет стили в любом случае, когда бы они не загрузились — здесь не действует правило «кто первый встал того и тапки». Если значение будет браться из этого выражения, оно будет пустым, пока тем-же ява-скрпитом не будет присвоено другое значение. ТАК css свойства не получаются.

              > Вот в этом и проблема.
              Да нет, проблема в том, что вы матчасть не знаете.
                –1
                Понимания матчасти нет — это я согласен.

                Но что если требуется взять
                document.getElementsById(«mydiv»).style.clientHeight? :)

                В общем ситуация такая может быть. Но аффтор сам дурак что в таком случае использует импорт. А если хочет динамическую подгрузку стилей — пусть использует нечто вроде document.createElement('link') и отслеживает их подгрузку ручками. Хотя не знаю что будет если внутри него будет импорт…

                И вообще — собирайте все файлы стилей в один и архивируйте.
                • UFO just landed and posted this here
                    0
                    ну да. написал фигню :) ессно там стиль не нужен :)

                    в том-то и дело что левое значение ведет к ошибкам. В основном это ошибки рассчета размеров элементов и соответсвенно их позиционирования в случае если эту функцию берет на себя жс-движок

                    имя класса да. никак не завязано. Опять-же если не работать с классами внутри файла стилей средствами жс. Вроде это как-то можно делать… но также вроде это жуткое извращение :)
                    • UFO just landed and posted this here
                  0
                  я имела ввиду не присваивание, а забор значения из стилей. Если сделать еще и так:
                  alert(document.getElementsById(«mydiv»).style.height);

                  вы получите Undefined.
                  • UFO just landed and posted this here
                  0
                  По хорошему, вы сначала должны убедится, что вся страница вместе со скриптами загружена, а только потом выполнять скрипт.
                    0
                    опять же все перекладывается на плечи разработчика :)
                      0
                      Естественно, а на кого ещё? ))
                        0
                        на разработчиков браузеров :)
                –2
                а как ведут себя более другие браузеры?
                  0
                  какие другие? В статье говорится обо всех наиболее используемых.
                    –8
                    Любые другие.
                    В стать упоминается только ИЕ
                    И засунь себе свой минус в жопу
                      0
                      lol. я даже не голосовала.
                        0
                        на самом деле он частично прав
                        таргетная аудитория с IE не так критично относится к подобного рода шалостям. А вот Safari/Konqueror4/Webkit/Chromonium/Opera… куда интереснее =)
                  –2
                  Странно, что эта статья опубликована сразу же после chikuyonok.ru/2009/04/dont-use-import/
                  • UFO just landed and posted this here
                    • UFO just landed and posted this here
                    +1
                    о черт, отметил статью для перевода — а ее уже перевели :)
                      +3
                      Каким образом меряется скорость загрузки файлов в ИЕ?
                      0
                      хоть импортом и не пользовался, но когда-нить всё равно попробовал бы)
                      а вот вы своей статьёй сэкономили мне много времени в будущем, пока я с этим импортом разбирался бы, что не так)
                      спасибо!
                        +3
                        Вы не учли самую важную деталь — при использовании import браузер не лезет на сервер с заголовком If-modified-since и не ждет 304. Он полезет если упорно нажать F5 или ctrl+f5.

                        Лично для меня это играет самую важную роль, так как нет лишних запросов на каждую страницу.
                          0
                          Не думаю что запрос If-modified-since будет забираться дольше, чем загрузка самого стиля. В случае непараллельной загрузки, да еще и не в том порядке никакой выгоды нет.
                            0
                            выгода — 100%! один раз загруженные стили хранятся в кэше и браузер больше не будет на каждую страницу делать запросы. а если оставлять LINK — при каждом открытии страницы — запрос на файл стилей, а если не один еще…
                              0
                              @import и link используют кэш равноправно. Это равносильные конструции везде, где это касается диалога браузера с сервером. В статье идет речь про внутреннюю логику обработки браузером последовательности этих элементов на странице.
                        • UFO just landed and posted this here
                            0
                            Потому что это семантично. Я тоже клал на линки с высокой колокольни, но не для продакшена, а во время разработки.

                            Я делаю так:
                            index: />
                            style/style.css:
                            @import url(«reset.css»);
                            @import url(«layout.css»);
                            @import url(«visual.css»);

                            Удобно править только нужные файлы.
                              0
                              Хабр съел разметку, там в начале как раз линк на style/style.css
                                0
                                Вот! кстати — таже мысль пришла и мне на кануне; я как кодер — не хочу дёргать шаблон каждый раз, когда кто-то пропишет новый стиль. Поэтому указываю «master.css» в котором будут подключаться остальные стили.

                                Хотя чувствую — что надо проверить время загрузки…
                              +1
                              Интересно, но я использую web-optimizer :)
                                0
                                таки запустился? :) поздравляю, кину ссылку в Twitter :)
                                0
                                Хоть у меня опыт и небольшой, я использовала только линки. Автор подал пищу для размышлений и новых экспериментов.
                                  –4
                                  :)

                                  А что им (@import) кто-то пользуется? ;)

                                  :)))
                                    0
                                    Вполне, если нужно на одной какой-то конкретной странице много стилей подключить, которые в отдельный файл выносятся, но CMS-ка дубовая и подключить их в head не очень удобно.
                                    0
                                    Есть один момент, если файлов стилей много, то ИЕ 6 начинает глючить вплоть до падения, если импортить их через @import то этого не происходит. Недавно ловили этот баг почти 2 дня…
                                      –1
                                      Только вчера при общении с дизайнером говорил о желательности именно <link />.

                                      Статья очень вовремя :)
                                        0
                                        Я обычно линкую только файл style.css, в него импортом добавляю все остальные css.
                                        Целью всегда было уменьшить количество ссылок на стили и скрипты в, чтобы контент был ближе к верху. Ведь и главную навигацию специально спускают в коде вниз и стилями ставят сверху только для этого.

                                        А проблем с загрузкой никогда не наблюдалось.
                                          0
                                          Я вот тоже думаю почему бы так не делать. Или в таком случае свои косяки?
                                          0
                                          Лучше всего не сильно напрягаться по этому поводу.
                                          Многие нормальные CMS кэшируют CSS стили в один файл и проблем с загрузкой их не должно возникать.
                                            0
                                            На самом деле стоит учитывать плохо документированную фичу IE 6 (и вроде IE 7), которая может загружать только 32 <link… > Элемента идущих в шапке.

                                            Столкнулись на одном проекте давно уже, с такой проблемой, было много подключаемых CSS файлов, и после 32го все остальные не грузились

                                            Проблема решалась разбивкой на блоки
                                            в каждых из которых было не более 32х импортов

                                            Хотя понимаю всю абсурдность такого кол-ва файлов стилей :)
                                              0
                                              В больших проектах, например с использованием dojo-dijit-dojox, без импорта туговато — тоже что программировать без require/import/include…
                                              я думаю при разработке импорт очень хорош!
                                              а в продакшен надо все стили скриптом (поищите или сами напишите) собирать в один файл (dojo build system — умеет это dojocampus.org/content/2008/05/26/dojo-build-201-layers-and-css-optimizing-builds/)

                                              Совсем недавно для себя сформулировал правило -one entry point for js and css
                                              те на странице только один link на стиль, c которого потом разростается дерево импортов
                                              после билда в страничку подгружается тока один файл
                                              0
                                              Если в документе содержатся два и более тегов <link>, броузер должен представить пользователю список таблиц стилей, на которые ссылаются теги. Пользователь выбирает таблицу, которую броузер загружает и применяет при форматировании документа. Остальные таблицы из тегов <link> игнорируются.

                                              Если речь идёт об @import, то, напротив, всякий распознающий стили броузер должен слить множество указанных в директивах таблиц в один набор стилевых правил для документа. При возникновении каких-либо взаимных противоречий приоритет имеет последняя импортированная таблица.



                                              На практике популярные броузеры обращаются с таблицами стилей, присоединёнными с помощью тега <link>, так же, как с импортированными таблицами, каскадным образом совмещая их действие. Броузеры в настоящее время не позволяют выбирать таблицу стилей.



                                              Ни один [броузер] не поддерживает множественные и выбираемые пользователем таблицы стилей, соответствующие стандарту CSS2.

                                              «HTML и XHTML. Подробное руководство. 6-е издание» — Чак Муссиано и Билл Кеннеди
                                                0
                                                Кому что-то не удобно — чьи ж это проблемы, если в собственном коде ориентироваться не можете?

                                                Как по мне — в разработке можно использовать все что угодно!
                                                Но в конце концов у меня всегда получается один link, без @import, потому что вполне достаточно ОДНОГО .css в любой ситуации

                                                Only users with full accounts can post comments. Log in, please.