Разрушители CSS, которые объединяют элементы, разрушительны?
Я нашел этот минификатор CSS ( http://www.lotterypost.com/css-compress.aspx). Внизу этой страницы есть раздел, озаглавленный "Что специально не делает CSS Compressor?" Есть четыре вещи, две из которых я не мог понять, почему они могут быть разрушительными:
Объединение отдельных полей, полей или границ в одно свойство.
margin-top: 10px;
margin-right: 0;
margin-bottom: 8px;
margin-left: 30px;
становится
margin: 10px 0 8px 30px;
И объединение стилей для одного и того же элемента, которые указаны в разных блоках стилей.
#element {
margin: 0;
}
#element {
color: #000000;
}
становится
#element {
margin: 0;
color: #000000;
}
Я думаю, что CSSTidy делает оба из них. Правильна ли вышеуказанная веб-страница? Существуют ли ситуации, когда эти типы минификации могут быть проблемой?
3 ответа
Я разработчик CSS Compressor, который является предметом этого вопроса ( http://www.lotterypost.com/css-compress.aspx), поэтому я приведу пример того, как компрессор может сломать CSS каскад, если инструмент агрессивно переписывает его.
Существует множество способов нацеливания на элементы в таблице стилей, и поскольку компрессор CSS не обладает глубокими знаниями о структуре DOM страницы, классах, идентификаторах и т. Д., У компрессора нет способа узнать, находится ли оптимизация, которая пересекает скобки. определения сломаются или нет.
Например, простая структура HTML:
<div class="normal centered">
<p>Hello world.</p>
</div>
И немного CSS:
div.normal p {
margin: 10px 0 10px 0;
}
div.centered p {
margin: 10px auto;
}
div.normal p {
margin-bottom: 5px;
}
Несжатый код создаст центрированный абзац с верхним полем 10px и нижним полем 5px.
Если вы запустите стили CSS через CSS Compressor, вы получите следующий код, который поддерживает порядок и каскад исходных несжатых стилей.
div.normal p{margin:10px 0}div.centered p{margin:10px auto}div.normal p{margin-bottom:5px}
Допустим, вы хотите еще больше агрессивно сжимать стили, комбинируя поля двух определений div.normal p. Оба имеют одинаковый селектор, и они, как представляется, избыточно стилизуют нижнее поле.
Было бы два способа объединить поля: вы можете объединить два определения полей в первый (верхний) стиль div.normal p или объединить их в последний (нижний). Давайте попробуем оба способа.
Если вы объедините поля в первый (верхний) стиль div.normal p, вы получите это:
div.normal p{margin:10px 0 5px}div.centered p{margin:10px auto}
В результате объединения полей таким образом нижнее поле будет неправильно установлено на 10 пикселей, потому что "центрированный" класс будет перекрывать нижнее поле (поскольку определение "центрированного" стиля теперь появляется позже в каскаде).
Если вы объедините поля в последний (нижний) стиль div.normal p, вы получите это:
div.centered p{margin:10px auto}div.normal p{margin:10px 0 5px}
В результате объединения полей таким образом, абзац больше не будет выглядеть как центрированный, потому что нижнее определение "p" переопределяет левое и правое поля "auto", которые определены в "центрированном" классе.
Таким образом, мы можем видеть, что объединение определений стилей, которые даже имеют один и тот же селектор, может вызвать довольно серьезные проблемы.
Вы бы лично когда-нибудь писали такой код? Может быть, а может и нет. Из-за различных "весовых" правил каскада можно попасть в ловушку кода такого типа, даже не осознавая этого.
Кроме того, учитывая тот факт, что на современных веб-страницах несколько файлов CSS часто объединяются в один файл, чтобы попасть на сервер с меньшим количеством загрузок, легко представить, что CSS Compressor по-королевски облажает каскад, переписывая несколько таблиц стилей (возможно, написаны разными людьми), которые объединены в один файл.
Фактически, я написал CSS Compressor для этого сценария на своем веб-сайте, Lottery Post. Каждая веб-страница имеет множество таблиц стилей, поддерживающих различные jQuery и другие компоненты, а CSS Compressor используется для автоматического сжатия всех этих таблиц стилей в одну загрузку. На всех страницах сайта есть как минимум 10 различных таблиц стилей, объединенных вместе, и на большинстве страниц их больше.
Например, если вы посмотрите на код позади самой страницы CSS Compressor, вы найдете в таблице главную таблицу стилей, которая выглядит следующим образом:
<link rel="stylesheet" href="http://lp.vg/css/d11019.0/j2HKnp0oKDOVoos8SA3Bpy3UHd7cAuftiXRBTKCt95r9plCnvTtBMU2BY2PoOQDEUlKCgDn83h16Tv4jbcCeZ(gupKbOQ9ko(TcspLAluwgBqrAjEhOyXvkhqHA(h5WFDypZDK2TIr(xEXVZtX7UANdFp6n1xfnxqIMR8awqGE)vrwUgY2hrCGNNTt1xV7R1LtCSfF46qdH1YQr2iA38r1SQjAgHze(9" />
Gobbledeegook в URL на самом деле является зашифрованной строкой, содержащей все таблицы стилей для объединения на сервере. Сервер сжимает их и кэширует результат.
Методы экономии пространства и времени при вызове одной таблицы стилей включают:
- Объединение множества таблиц стилей в один файл / загрузку, просто добавив их все вместе
- Сжатие комбинированной таблицы стилей с помощью CSS Compressor (без проблем в каскаде!)
- Использование другого доменного имени (lp.vg) для загрузки таблицы стилей, что улучшает возможности браузера загружать параллельно
- Использование очень короткого доменного имени (lp.vg)
- GZip сжатие применяется к таблице стилей на веб-сервере
- Номер версии таблицы стилей встраивается в URL (".../d11019.0/..."), так что если какой-либо стиль изменяется в любой из нескольких таблиц стилей, я могу изменить номер версии и браузер никогда не будет использовать версию, которую он кэшировал. (Обратите внимание, что номер версии должен быть частью пути URL, а не в строке запроса, поскольку некоторые прокси-серверы не смотрят на строку запроса, чтобы определить, должна ли страница быть извлечена из кэша.)
Я надеюсь, что это лучше объясняет и помогает тем, кто хочет улучшить производительность страницы!
-Todd
БОЛЬШЕ ИНФОРМАЦИИ:
Чтобы добавить к вышесказанному, представьте, что мы возьмем ваш пример цвета и объединим определения стилей с теми же селекторами.
Вот несколько несжатых стилей:
div.normal p {
margin: 10px 0 10px 0;
}
div.centered p {
margin: 10px auto;
color: blue;
}
div.normal p {
color: black;
}
Компрессор CSS производит следующий вывод:
div.normal p{margin:10px 0}div.centered p{margin:10px auto;color:blue}div.normal p{color:#000}
Если бы мы применили агрессивное объединение определений стилей с одинаковым селектором, мы получим следующий код.
Метод 1, объединяющий оба в первом определении, неправильно сделал бы цвет текста синим:
div.normal p{margin:10px 0;color:#000}div.centered p{margin:10px auto;color:blue}
Метод 2, объединяющий оба во второе определение, неправильно выровняет текст по левому краю:
div.centered p{margin:10px auto;color:blue}div.normal p{margin:10px 0;color:#000}
Единственное время, когда объединение определений стилей с одним и тем же селектором безошибочно на 100%, - это когда определения появляются непосредственно одно за другим, но в любом другом случае этот метод может привести к повреждению каскада стилей.
Я не мог представить себе случая, когда какой-либо разработчик мог бы написать код таким образом (два определения стиля с точно таким же селектором, одно сразу за другим), поэтому я пришел к выводу, что для его кодирования требуется много усилий и возможность дополнительная точка отказа в компрессоре, не стоила этого в конечном счете.
Честно говоря, я был бы очень обеспокоен компрессором CSS, который комбинировал стили из разных блоков определения, потому что каскад - очень хрупкая вещь, и сломать каскад чрезвычайно легко.
На странице есть раздел "причина не используется", в котором описывается, почему она не выполняет эти две вещи.
И вдобавок ко всему, я бы предположил, что он не пытается делать эти вещи, потому что он не является полным синтаксическим анализатором / интерпретатором CSS и начал бы создавать такие вещи, как условные блоки CSS.
Под "деструктивным" я полагаю, вы имеете в виду "CSS работает не так, как ожидалось".
Комбинация правил длинных рук, таких как ваш первый пример, может быть сделана без каких-либо побочных эффектов.
В простой старой таблице стилей без медиа-блоков или других причудливых вещей второй пример также не вызовет никаких проблем.
Причина № 2 является рискованной, потому что изменение порядка правил или сложение правил вместе без учета каскада может привести к поломкам.
Некоторые компрессоры CSS могут переупорядочивать правила по алфавиту или по типу селектора. Это очень рискованно, потому что перемещение правил может нарушить каскадное поведение, созданное автором.
Минифайеры, такие как YUI-компрессор, не делают ничего из этого, выбирая более безопасные стратегии, такие как удаление пробелов, избыточных точек с запятой и нулей и тому подобное.
С большим количеством CSS, содержащих медиа-блоки и другой CSS3-код, вполне вероятно, что многие из существующих CSS-компрессоров не будут работать правильно вообще. Большинство из них не имеют подходящего лексера для анализа кода - они используют контекстно-зависимые побайтовые (Tidy) или регулярные выражения (большинство остальных) для обработки кода.
При выборе компрессора я бы предложил найти что-то, что будет делать это локально, и подкреплено хорошим набором тестов, чтобы вы могли видеть, какие случаи обрабатываются (и не обрабатываются) правильно.