Разрушители 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) или регулярные выражения (большинство остальных) для обработки кода.

При выборе компрессора я бы предложил найти что-то, что будет делать это локально, и подкреплено хорошим набором тестов, чтобы вы могли видеть, какие случаи обрабатываются (и не обрабатываются) правильно.

Другие вопросы по тегам