CSSO (CSS Optimizer) — структурная минимизация CSS

    CSSO (CSS Optimizer) является минимизатором CSS, выполняющим как минимизацию без изменения структуры, так и структурную минимизацию с целью получить как можно меньший текст.
    CSSO написан на Javascript, выполняется как в браузере, так и в командной строке (с помощью NodeJS).
    Распространяется под лицензией MIT.

    Что умеет


    Минимизация без изменения структуры:
    • Удаление whitespace
    • Удаление концевых ‘;’
    • Удаление комментариев
    • Удаление неправильных charset и import
    • Удаление ошибочных элементов
    • Минимизация цвета
    • Минимизация 0
    • Минимизация margin и padding
    • Слияние многострочных строк в однострочные
    • Минимизация font-weight
    Минимизация с изменением структуры:
    • Слияние блоков с одинаковыми селекторами
    • Удаление перекрываемых свойств
    • Частичное выделение свойств в отдельный блок
    • Частичное слияние блоков

    Где найти


    Ссылки:Внимание: проект находится в статусе beta и может содержать недоработки и ошибки. Скорее всего, в дальнейшем изменятся адреса репозитория и хостинга для вебового интерфейса. Анонс призван познакомить общественность с новым CSS-минимизатором на ранней стадии, собрать отзывы, исправить пропущенные ошибки и сделать CSSO удобнее пользователю.

    Зачем ещё один минимизатор


    Большинство из современных популярных минимизаторов (YUICompressor и ему подобные) — это минимизация без разбора и анализа структуры. Грубо говоря, набором regexp'ов заменяют X на меньший Y.

    Пример:
    .test { color: red }
    .test { color: green }

    Обработка regexp'ами:
    .test{color:red}.test{color:green}

    Обработка с минимизацией структуры:
    .test{color:green}

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

    PS. Документация и даже JsDoc на русском языке. Будет и английский.
    Поделиться публикацией
    Ой, у вас баннер убежал!

    Ну. И что?
    Реклама
    Комментарии 58
    • 0
      В IE 8.0 не работает.

      Он может что-то большее чем:
      www.codebeautifier.com
      • 0
        Спасибо, разберёмся.

        Может. Вот пример.
        Вход:
        .test0 {
            color: green;
            margin: 0
        }
        
        .break {
            color: red
        }
        
        .test1 {
            color: green;
            margin: 0
        }

        CSSO (я отформатировал для чтения):
        .test0, .test1 {
            color: green;
            margin: 0
        }
        
        .break {
            color: red
        }
        
        .test1 {
            margin: 0
        }

        Code Beatifier (убил порядок селекторов, получили другой CSS):
        .break {
            color:red;
        }
        
        .test0,.test1 {
            color:green;
            margin:0;
        }

        Если выключать сортировку селекторов, структурной минимизации не происходит, это беда минимизаторов на основе CSSTidy.
        • 0
          Зачем Вы лукавите? Ваш результат тоже изменил CSS.
          Например: Тест

          Какого цвета был Тест, а какого стал после преобразования?
          • 0
            Я сейчас проверил результат работы исходного CSS и результат работы CSS после CSSO. Идентичный. Что именно подразумеваете под «изменил CSS» и как проверили?
            • 0
              Ниже пример. Хабраредактор съел и оставил только слово «Тест»
          • 0
            Выше читать так:
            Например:image
            • +4
              Да что ж мне так не везет!
              Вот что хотел привести в качестве примера:
              image

              • +1
                А. Нет, я не лукавлю, я ошибаюсь. Есть разница. Спасибо.
            • 0
              Либо я что-то упускаю из виду, либо последнее правило в этом случае (.test1 {margin: 0}) все-таки излишне — оно дублирует уже содержащееся в блоке .test0, .test1 и при этом ничем не перекрывается, чтобы была необходимость переопределить его позднее.
          • +1
            Глупый он у вас какой-то получился. Сломался на первом же примере:

            a [title="1px"]{color:red;}


            И что за мода пошла выкладывать на показ бетки… Вы сделайте нормальный, рабочий продукт и показывайте тогда.
            • 0
              Спасибо, исправим.
              • 0
                С другой стороны возможно вы и правы. Если на выходе сделаете достойный продукт, то бета имела место быть. Успехов вам.

                +
                p{
                font-family:Palatino,serif;
                font:italic 700 large Arial,serif;
                }


                font тоже можно было бы сжать.
                • +1
                  Мы будем очень стараться сделать достойный продукт, честное слово.
                  Спасибо.
              • +7
                Если бы все всегда ждали того момента когда будет «нормальный, рабочий продукт», мы бы с вами ещё с деревьев не спустились и прыгали по лианам :)
              • 0
                А как он относится к использованию хаков в css?
                • 0
                  Смотря каких. :) Например?
                  • 0
                    Так всевозможные IE'шные хаки.
                    «Underscore hack» и подобные, «Box model hack», «Child selector hack».
                    Хаки для версий типа IE5, можно опустить, думаю это уже не столь актуально.
                • 0
                  Ужал с 59 до 38 Кб. Неплохо.
                  • 0
                    А www.codebeautifier.com при настройке «All Optimisation»?
                    • 0
                      a [title="1px"]{width:-moz-calc(1px + 1px);color:hsla(0,0%,100%,.5)}

                      выдал:

                      Optimised number: Changed "-moz-calc(1px+1px)" to «0»

                      С чего бы это…
                      • 0
                        HabraCSS
                        codebeautifier: Input: 118.001KB, Output:81.682KB, Compression Ratio: 30.8%(-36319 Bytes)
                        CSSO: 84,1KB
                        • 0
                          А порядок селекторов при этом не слетел?
                          • 0
                            Выше мы видели как и у Вас произошло «недорозумение» с CSS.
                            • 0
                              Так я исправлю. :) В этом и смысл выкладывать анонсы даже бета-стадий. Чем раньше отловят ошибки, тем раньше они исправятся, да и заинтересованные люди подтянутся. Толпой и батьку бить легче.
                              • 0
                                Надеюсь в плане гибкости настроек тоже будут улучшения! А то сейчас по сути настроек вообще нет.
                                • 0
                                  Улучшения будут везде, где они не будут противоречить разуму и будут полезны пользователю. Всё не угадать, потому вот вас сейчас спрошу: каких настроек не хватает? Что бы лично вам оказалось полезным в повседневной практике?
                                  • 0
                                    Интересно было бы получать на выходе некую статистику по тому, что же произошло в процессе работы скрипта. Например, сколько пересекающихся селекторов, где в них пересекались стили и т.п. Такое возможно?
                        • 0
                          Output:40.182KB, Compression Ratio: 35.3%(-21964 Bytes)
                          Тоже неплохо.
                          • 0
                            Попробовал на нескольких своих, больше 13% не вышло — можно порадоваться за себя, что пока что такие штуковины мне не нужны
                            • 0
                              Почему не нужны? Почему бы не улучшать то, что можно улучшить, пусть даже это мелочи?
                              • 0
                                Я так думаю, 13% — это НДС на более красиво читаемый код
                                • 0
                                  М… А на каком этапе его читать будут? Человек, который зашёл на страницу и браузер которого скачал стили?
                        • 0
                          А серверный вариант будет, к примеру на пэхэпэ?
                          • +1
                            текущий вариант написан на js и отлично работает как на клиенте, так и на сервере через node.js.
                            • 0
                              Нашими силами — вряд ли. Но код очень простой технически, его можно без боли мигрировать на многие языки. Это open source, всё в руках энтузиастов.
                              • 0
                                Уточню: серверный вариант — уже. PHP — чьё-нибудь будущее. :)
                                • 0
                                  Поэтому и уточнил, в частности интересуют другие языки, нежели node.js
                              • –7
                                Никогда не верстал в столбик.
                                • –7
                                  Минусяторы верстают в столбик? :)
                                • +1
                                  В сравнении с www.codebeautifier.com в вашем интерфейсе вообще не понял оптимизировалось чего или нет, строки склеились, а процент сжатия не показывает. Баг? FF4.
                                • 0
                                  Покажите цифры в процентах, помнится фанател оптимизацией на проекте, где ставили жесткие требования по нагрузке — пришел к выводу, что обработка форматирования css — самое неэффективное из всего возможного, оставил оригинальные не обработанные файлы.
                                  а по сравнению с отдачей в gzip выигрыш был еще менее заметен (буквально пару килобайт на 1500 строк css).
                                  • 0
                                    Покажем при выходе из beta в production. Сейчас нет ряда минимизаций, зато есть баги. Любая метрика сейчас будет отличаться от будущих результатов.
                                    Эта пара килобайт играет в зависимости от нагрузки и от количества людей, использующих минимизацию. Если у страницы один посетитель в час, да ещё всё кешируется, минимизация — копейки. Если счёт на сотни тысяч, если минимизация не у одного проекта, а у всей Земли (допустим), числа становятся заметно интереснее.
                                    Наконец, если что-то можно сделать лучше хоть на копейку, почему бы не сделать.
                                    • 0
                                      Как-то на anekdot.ru начинающий разработчик выложил несжатый скрипт календаря. Всего +15кб. Но на главной странице. За сутки это вылилось в несколько гигов лишнего трафика.
                                    • 0
                                      Чем он лучше CssTidy?
                                      • 0
                                        CSSTidy или не минимизирует структуру или гробит порядок селекторов. Цель CSSO — минимизировать структуру И не гробить порядок селекторов.
                                        Наконец, CSSTidy хуже тем, что его никто (насколько знаю) не поддерживает, а на носу уже куски CSS3 со своей спецификой.
                                        • 0
                                          Дело в том, что CssTidy замечательно работает, вёрстку не разрушает. Порядок селекторов — вроде там есть настройки управления этим.

                                          Экономить байты, сжимая — бессмысленно. Намного больше в процентном соотношении сожмётся при удалении переносов строки и пробелов, да и gzip хорошо сожмёт тоже.
                                          • 0
                                            Я промахнулся и ответил ниже. Посмотрите, пожалуйста.
                                      • 0
                                        Давайте на всего одном примере: что вы будете делать, когда в полный рост поднимутся CSS3 media queries? Предлагаю проверить вот такое:
                                        @media screen and (min-width: 400px) and (max-width: 700px) { a { color:red } }
                                        • 0
                                          Данный подход даст выигрыш далеко не всегда.

                                          Проверил, прогнал сжатый YUICompressor'ом css-файл с рабочего проекта (весил 65783 байт). После структурной оптимизации он стал весить 64124, итого 1659 байт экономии (2,5%).

                                          Но если учесть, что css гзипуется, то вместо выигрыша, теряем сотню байт: 11833 байта против 11941.
                                          Файлы с примерами
                                          • 0
                                            Вы правы, не всегда. В данном случае потеряли. В другом можем выиграть. Мне кажется, универсального решения здесь не существует, разве что специально оптимизировать текст под алгоритмы сжатия, но это как-то… Но пример хороший, спасибо.
                                            • 0
                                              Без gzip использовать минификацию css не выгодно, пруфлинк.

                                              Я бы взял для анализа css популярных сайтов, желательно использующие различные подходы к написанию правил, и провёл сравнительный анализ вашего компрессора и аналогичных решений, чтобы понять в каком случае ваше решение даст наибольший выигрыш. Возможно, это подскажет, в какую сторону можно улучшить код чтобы он никогда не уступал тому же YUI.
                                          • +2
                                            Начало хорошее, не забрасывайте.

                                            Хочу ещё дать один пример:

                                            
                                            .class
                                            {
                                                border-top:1px solid #000;
                                                border-right:2px dashed #111;
                                                border-bottom:3px dotted #222;
                                                border-left:4px double #333;
                                            }
                                            


                                            …можно оптимизировать до:

                                            
                                            .class
                                            {
                                                border-width:1px 2px 3px 4px;
                                                border-style:solid dashed dotted double;
                                                border-color:#000 #111 #222 #333;
                                            }
                                            


                                            …и соответственно ещё уменьшить, если некоторые размеры, стили или цвета совпадают. Например:

                                            
                                            .class
                                            {
                                                border-top:1px solid #000;
                                                border-right:2px solid #111;
                                                border-bottom:1px solid #222;
                                                border-left:2px solid #111;
                                            }
                                            


                                            …можно оптимизировать до:

                                            
                                            .class
                                            {
                                                border-width:1px 2px;
                                                border-style:solid;
                                                border-color:#000 #111 #222;
                                            }
                                            
                                            • +1
                                              Не забросим. :)
                                              Да, border в ближнем TODO.
                                            • 0
                                              Так на вскидку пример не может прийти в голову, но мне кажется, что группировка селекторов в ряде случаев будет гробить верстку. По этому в ряде случаев этот процесс сложно автоматизировать. К тому же при gzip разница вообще будет будет мизерной.

                                              И еще, порой (когда длинна селектора превосходит длину перемещаемого свойства) группировка увеличивает объем, а не уменьшает его.
                                              • 0
                                                М… Чуть сложнее. Вот в общем случае она не гробится, если соблюдать итоговый порядок селекторов исходного CSS. Зато гробится в частном случае, когда в элементе комбинируются классы. Вон сверху сразу влепили такой случай и всё сломали. :) Но это решаемо.

                                                Абсолютно верно. Потому в CSSO при частичном выделении свойств в отдельный блок работает правило «Суммарная длина выделяемых свойств должна быть больше суммарной длины копируемых селекторов».
                                              • 0
                                                Из командной строки под win не пашет.
                                                1) __dirname под win использует виндовый backslash, так-что файл «csso\lib\csso.js» printFile должен быть таким:

                                                function printFile(filename) {
                                                    // Не пашет под виндой:
                                                    // print(fs.readFileSync(__dirname.slice(0, __dirname.lastIndexOf('/')) + '/' + filename).toString());
                                                    // пашет под виндой:
                                                    // print(fs.readFileSync(__dirname + '/../' + filename).toString());
                                                    // пашет под виндой:
                                                    print(fs.readFileSync(__dirname.replace(/[\\/][^\\/]+$/, '/' + filename)).toString());
                                                }

                                                2) виндовый dirname (dirname.exe, по крайней мере из популярного пака UnxUtils) не понимает «--», ругается («too many arguments») на конструкцию: $(dirname — "$0")
                                                Такой вариант проще и работает под win:

                                                #!/usr/bin/env bash
                                                CSSO_HOME=$(dirname $0)
                                                node "$CSSO_HOME/../lib/csso.js" $@

                                                либо можно сменить батник csso.cmd на такой:

                                                @IF EXIST "%~dp0\node.exe" (
                                                  "%~dp0\node.exe" "%~dp0\node_modules\csso\lib\csso.js" %*
                                                ) ELSE (
                                                  node "%~dp0\node_modules\csso\lib\csso.js" %*
                                                )

                                                <парсер кретин>который заменил два минуса на длинное тире</парсер кретин>

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

                                                Самое читаемое