Giter Club home page Giter Club logo

csso's Introduction

NPM version Build Status Coverage Status NPM Downloads Twitter

CSSO (CSS Optimizer) is a CSS minifier. It performs three sort of transformations: cleaning (removing redundants), compression (replacement for the shorter forms) and restructuring (merge of declarations, rules and so on). As a result an output CSS becomes much smaller in size.

Install

npm install csso

Usage

import { minify } from 'csso';
// CommonJS is also supported
// const { minify } = require('csso');

const minifiedCss = minify('.test { color: #ff0000; }').css;

console.log(minifiedCss);
// .test{color:red}

Bundles are also available for use in a browser:

  • dist/csso.js – minified IIFE with csso as global
<script src="node_modules/csso/dist/csso.js"></script>
<script>
  csso.minify('.example { color: green }');
</script>
  • dist/csso.esm.js – minified ES module
<script type="module">
  import { minify } from 'node_modules/csso/dist/csso.esm.js'

  minify('.example { color: green }');
</script>

One of CDN services like unpkg or jsDelivr can be used. By default (for short path) a ESM version is exposing. For IIFE version a full path to a bundle should be specified:

<!-- ESM -->
<script type="module">
  import * as csstree from 'https://cdn.jsdelivr.net/npm/csso';
  import * as csstree from 'https://unpkg.com/csso';
</script>

<!-- IIFE with an export to global -->
<script src="https://cdn.jsdelivr.net/npm/csso/dist/csso.js"></script>
<script src="https://unpkg.com/csso/dist/csso.js"></script>

CSSO is based on CSSTree to parse CSS into AST, AST traversal and to generate AST back to CSS. All CSSTree API is available behind syntax field extended with compress() method. You may minify CSS step by step:

import { syntax } from 'csso';

const ast = syntax.parse('.test { color: #ff0000; }');
const compressedAst = syntax.compress(ast).ast;
const minifiedCss = syntax.generate(compressedAst);

console.log(minifiedCss);
// .test{color:red}

Also syntax can be imported using csso/syntax entry point:

import { parse, compress, generate } from 'csso/syntax';

const ast = parse('.test { color: #ff0000; }');
const compressedAst = compress(ast).ast;
const minifiedCss = generate(compressedAst);

console.log(minifiedCss);
// .test{color:red}

Warning: CSSO doesn't guarantee API behind a syntax field as well as AST format. Both might be changed with changes in CSSTree. If you rely heavily on syntax API, a better option might be to use CSSTree directly.

Related projects

API

minify(source[, options])

Minify source CSS passed as String.

const result = csso.minify('.test { color: #ff0000; }', {
    restructure: false,   // don't change CSS structure, i.e. don't merge declarations, rulesets etc
    debug: true           // show additional debug information:
                          // true or number from 1 to 3 (greater number - more details)
});

console.log(result.css);
// > .test{color:red}

Returns an object with properties:

Options:

  • sourceMap

    Type: Boolean
    Default: false

    Generate a source map when true.

  • filename

    Type: String
    Default: '<unknown>'

    Filename of input CSS, uses for source map generation.

  • debug

    Type: Boolean
    Default: false

    Output debug information to stderr.

  • beforeCompress

    Type: function(ast, options) or Array<function(ast, options)> or null
    Default: null

    Called right after parse is run.

  • afterCompress

    Type: function(compressResult, options) or Array<function(compressResult, options)> or null
    Default: null

    Called right after syntax.compress() is run.

  • Other options are the same as for syntax.compress() function.

minifyBlock(source[, options])

The same as minify() but for list of declarations. Usually it's a style attribute value.

const result = csso.minifyBlock('color: rgba(255, 0, 0, 1); color: #ff0000');

console.log(result.css);
// > color:red

syntax.compress(ast[, options])

Does the main task – compress an AST. This is CSSO's extension in CSSTree syntax API.

NOTE: syntax.compress() performs AST compression by transforming input AST by default (since AST cloning is expensive and needed in rare cases). Use clone option with truthy value in case you want to keep input AST untouched.

Returns an object with properties:

  • ast Object – resulting AST

Options:

  • restructure

    Type: Boolean
    Default: true

    Disable or enable a structure optimisations.

  • forceMediaMerge

    Type: Boolean
    Default: false

    Enables merging of @media rules with the same media query by splitted by other rules. The optimisation is unsafe in general, but should work fine in most cases. Use it on your own risk.

  • clone

    Type: Boolean
    Default: false

    Transform a copy of input AST if true. Useful in case of AST reuse.

  • comments

    Type: String or Boolean
    Default: true

    Specify what comments to leave:

    • 'exclamation' or true – leave all exclamation comments (i.e. /*! .. */)
    • 'first-exclamation' – remove every comment except first one
    • false – remove all comments
  • usage

    Type: Object or null
    Default: null

    Usage data for advanced optimisations (see Usage data for details)

  • logger

    Type: Function or null
    Default: null

    Function to track every step of transformation.

Source maps

To get a source map set true for sourceMap option. Additianaly filename option can be passed to specify source file. When sourceMap option is true, map field of result object will contain a SourceMapGenerator instance. This object can be mixed with another source map or translated to string.

const csso = require('csso');
const css = fs.readFileSync('path/to/my.css', 'utf8');
const result = csso.minify(css, {
  filename: 'path/to/my.css', // will be added to source map as reference to source file
  sourceMap: true             // generate source map
});

console.log(result);
// { css: '...minified...', map: SourceMapGenerator {} }

console.log(result.map.toString());
// '{ .. source map content .. }'

Example of generating source map with respect of source map from input CSS:

import { SourceMapConsumer } from 'source-map';
import * as csso from 'csso';

const inputFile = 'path/to/my.css';
const input = fs.readFileSync(inputFile, 'utf8');
const inputMap = input.match(/\/\*# sourceMappingURL=(\S+)\s*\*\/\s*$/);
const output = csso.minify(input, {
  filename: inputFile,
  sourceMap: true
});

// apply input source map to output
if (inputMap) {
  output.map.applySourceMap(
    new SourceMapConsumer(inputMap[1]),
    inputFile
  )
}

// result CSS with source map
console.log(
  output.css +
  '/*# sourceMappingURL=data:application/json;base64,' +
  Buffer.from(output.map.toString()).toString('base64') +
  ' */'
);

Usage data

CSSO can use data about how CSS is used in a markup for better compression. File with this data (JSON) can be set using usage option. Usage data may contain following sections:

  • blacklist – a set of black lists (see Black list filtering)
  • tags – white list of tags
  • ids – white list of ids
  • classes – white list of classes
  • scopes – groups of classes which never used with classes from other groups on the same element

All sections are optional. Value of tags, ids and classes should be an array of a string, value of scopes should be an array of arrays of strings. Other values are ignoring.

White list filtering

tags, ids and classes are using on clean stage to filter selectors that contain something not in the lists. Selectors are filtering only by those kind of simple selector which white list is specified. For example, if only tags list is specified then type selectors are checking, and if all type selectors in selector present in list or selector has no any type selector it isn't filter.

ids and classes are case sensitive, tags – is not.

Input CSS:

* { color: green; }
ul, ol, li { color: blue; }
UL.foo, span.bar { color: red; }

Usage data:

{
    "tags": ["ul", "LI"]
}

Resulting CSS:

*{color:green}ul,li{color:blue}ul.foo{color:red}

Filtering performs for nested selectors too. :not() pseudos content is ignoring since the result of matching is unpredictable. Example for the same usage data as above:

:nth-child(2n of ul, ol) { color: red }
:nth-child(3n + 1 of img) { color: yellow }
:not(div, ol, ul) { color: green }
:has(:matches(ul, ol), ul, ol) { color: blue }

Turns into:

:nth-child(2n of ul){color:red}:not(div,ol,ul){color:green}:has(:matches(ul),ul){color:blue}

Black list filtering

Black list filtering performs the same as white list filtering, but filters things that mentioned in the lists. blacklist can contain the lists tags, ids and classes.

Black list has a higher priority, so when something mentioned in the white list and in the black list then white list occurrence is ignoring. The :not() pseudos content ignoring as well.

* { color: green; }
ul, ol, li { color: blue; }
UL.foo, li.bar { color: red; }

Usage data:

{
    "blacklist": {
        "tags": ["ul"]
    },
    "tags": ["ul", "LI"]
}

Resulting CSS:

*{color:green}li{color:blue}li.bar{color:red}

Scopes

Scopes is designed for CSS scope isolation solutions such as css-modules. Scopes are similar to namespaces and define lists of class names that exclusively used on some markup. This information allows the optimizer to move rules more agressive. Since it assumes selectors from different scopes don't match for the same element. This can improve rule merging.

Suppose we have a file:

.module1-foo { color: red; }
.module1-bar { font-size: 1.5em; background: yellow; }

.module2-baz { color: red; }
.module2-qux { font-size: 1.5em; background: yellow; width: 50px; }

It can be assumed that first two rules are never used with the second two on the same markup. But we can't say that for sure without a markup review. The optimizer doesn't know it either and will perform safe transformations only. The result will be the same as input but with no spaces and some semicolons:

.module1-foo{color:red}.module1-bar{font-size:1.5em;background:#ff0}.module2-baz{color:red}.module2-qux{font-size:1.5em;background:#ff0;width:50px}

With usage data CSSO can produce better output. If follow usage data is provided:

{
    "scopes": [
        ["module1-foo", "module1-bar"],
        ["module2-baz", "module2-qux"]
    ]
}

The result will be (29 bytes extra saving):

.module1-foo,.module2-baz{color:red}.module1-bar,.module2-qux{font-size:1.5em;background:#ff0}.module2-qux{width:50px}

If class name isn't mentioned in the scopes it belongs to default scope. scopes data doesn't affect classes whitelist. If class name mentioned in scopes but missed in classes (both sections are specified) it will be filtered.

Note that class name can't be set for several scopes. Also a selector can't have class names from different scopes. In both cases an exception will thrown.

Currently the optimizer doesn't care about changing order safety for out-of-bounds selectors (i.e. selectors that match to elements without class name, e.g. .scope div or .scope ~ :last-child). It assumes that scoped CSS modules doesn't relay on it's order. It may be fix in future if to be an issue.

csso's People

Contributors

1000ch avatar a-koptsov avatar afelix avatar angryobject avatar anotherquiz avatar bonga avatar charlessuh avatar dab avatar djibe avatar gruzzilkin avatar insane-developer avatar jk708 avatar lahmatiy avatar leonya avatar mathiasbynens avatar mungell avatar nattheriddle1 avatar nitriques avatar rubaxa avatar sergeche avatar smelukov avatar sokra avatar spmason avatar t32k avatar tadatuta avatar tonyganch avatar vithar avatar xhmikosr avatar yuanyan avatar zoobestik avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

csso's Issues

Можно ещё преобразовывать цвета.

Например, преобразовывать
#F00
white
rgba(0,0,0,1)
rgba(255,255,255,0.5)
до
red
#FFF
#000
hsla(0,0%,100%,0.5)
Местами тут экономия на спичках и редкие юз-кейсы (#F00 → red), но вот с rgba и прочими может местами быть хорошая экономия, кажется.

Вырезание дефолтных значений из шортхендов

Довольно большая, но, кажется, не сильно сложная задача: для каждого шортхенда есть много дефолтных значений, которые хочется обрезать (я об этом написал в issue про font, но лучше этот момент отдельно вынести).

Для font всё просто: можно вырезать все значения normal:

  • font: normal normal 1em/2 Arial, sans-seriffont:1em/2 Arial,sans-serif

А вот у background уже дофига различных значений можно опустить:

  • background: none repeat scroll transparent 0 0background:0 0;

(Кстати, background:none можно легко сжимать до background:0 0 — получаем экономию на одну спичку)

…и т.д.

Ну и для кучи современных всяких CSS3 свойств часто не опускают какие-либо из значений (и вот их точно часто из генераторов вставляют), например:

  • у transition: all .3s ease недефолтное только указание времени, т.е. это можно сократить до transition:.3s
  • у box-shadow, увы, можно только ноли выкидывать до одного, и только если они идут в конце: box-shadow: 3px 0 0 0 redbox-shadow: 3px 0 red, но box-shadow: 3px 0 3px 0 redbox-shadow: 3px 0 3px red.

Правда, вот случай с box-shadow чуть сложнее: в старых вебкитах нельзя использовать четвёртую цифру — свойство не будет применено. Возможно, где-то кто-то может использовать это как хак для старых версий. Но по идее это актуально только для -webkit-box-shadow, для остальных пефиксных и без вариантов можно все ноли сокращать безопасно, кажется.

Хотя, для всех подобных шортхендов надо тестировать отдельно во всех актуальных браузерах, но, насколко я помню, там не так много проблем и спорных мест.

Пересчёт z-index

В CSS нередко встречаются "условно" большие z-index, когда верстальщик пишет "лишь бы большой", например, z-index: 9999. В погоне за байтами есть смысл собирать z-index по коду и вместо 1000, 2000, 9999 сжимать до 1, 2, 3.

forEach?

ext/csso/lib/cssoutils.js:69
        nodes.forEach(function(node) {
              ^
TypeError: Object #<Object> has no method 'forEach'
    at Object.min2string (/root/chrome-extension-builder/ext/csso/lib/cssoutils.js:69:15)
    at Object.compress (/root/chrome-extension-builder/lib/csso.js:11:9)

Оптимизация border при наличии short-hand свойства

Например,

.class {
    border: 0 solid;
    border-top-width: 10px;
    border-bottom-width: 10px;
    }

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

.class {
    border: solid;
    border-width: 10px 0;
    }

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

.class {
    border: 1px solid green;
    border-top: 1px solid red;
    border-bottom: 1px solid red;
    border-left: 1px solid red;
    border-right: 1px solid red;
    }

можно сократить вообще до

.class {
    border: 1px solid red;
    }

Анализ и валидация кода

Раз уж всё-равно весь CSS парсится, почему бы с каким-нибудь ключиком не выдавать всякую полезную информацию о коде?

Ну, например:

  1. Если селекторов больше 4095 — выдавать предупреждение, что в ие дальше какого-то селектора будут проблемы (как вариант — сразу предлагать засплитить файл).
  2. Пытаться отлавливать всякие ошибки (если этого до сих пор нет), которые могут привести к чему-нибудь плохому (многое из того, что w3cшный валидатор делает)
  3. Сообщать о всяких неоптимальных селекторах, влияющих на производительность (ховеры без элементов, звёздочки, cелектор + без родителя/элементов (опасно в фф <4) и т.д.)

В общем, попробовать в будущем сделать не просто оптимизатор, но и анализатор кода, кажется, это может быть вполне разумным развитием :)

Использование с jake / node

Использую сборщик csso со сборщиком https://github.com/mde/jake хотелось бы более простой способ подключения и парсинга из другого node app, сейчас использую так:

var csp  = require('csso/lib/cssp').parse,
    csm  = require('csso/lib/cssm').minimize,
    csu  = require('csso/lib/cssoutils');
...
var optimized_css = csu.min2string(
    csm(
      csp(
        fs.readFileSync('elfinder.css').toString()
      ),
      {}
    ).nodes,
    ''
  );

Так же хотелсь бы опцию которая добавляла \n после каждого rulset'а - таким образом оcтаётся читабильность css файла.

Оптимизация :first-child/:nth-child и т.д.

Мелочи, но всё же:

  1. :first-child короче чем :nth-child(1) на один символ.
  2. :last-child короче чем :nth-last-child(1) аж на семь символов.
  3. Аналогично и с …-of-type.

Единственный момент: есть версии браузеров, которые понимают :first-child, но не понимают nth-child.

Ну и представить такое в коде я могу только если например что-то или кто-то автоматически нагенерит стилей с …(1),…(2),…(3) и т.д. и не прооптимизирует соответствующие пункты с единичками.

оптимизация не совсем ясна

Попробуйте, пожалуйста, скомпилировать этот css-файлик (и обратите внимание на шрифт в body, input, textarea - он остается только в body в итоге)

body {
    -webkit-user-select: none;
    }

body, input, textarea {
    font-family: "Trebuchet MS", Ubuntu, "Droid Sans";
    font-size: 10pt;
    }

a.direct {
    opacity: .5;
    -webkit-user-select: none;
    }

#profile #followings p {
    -webkit-transition: background-color 1s ease-in-out;
    -webkit-user-select: none;
    }

Хак для Оперы

После такого невалидного хака для оперы, в процессе оптимизации, CSSO теряет все следующие после него стили.

/* Opera 9.5 > */ /* */
@media all and (resolution = 0dpi)
{
   #js:root .b-form-checkbox__bg 
   {
      background: #fff;
   }
   #js:root .b-form-checkbox
   {
      background: #9a9a9a;
   }
}

(Opera >= 9.5 и < 10.50 stackoverflow)

Подвисает при всяких ошибках

Например, попробовал в веб-версии прооптимизировать a{{} — зависает и выдаёт потом сообщение о «медленном скрипте». Возможно, могут встретиться и ещё подобные случаи.

@font-face removes multiple src attributes

Sometimes it is necessary to include multiple src attributes for a font (for a fallback for IE).

It would look something like this:

@font-face {
font-family: 'pictos';
src: url('../fonts/pictos-web.eot'); /* IE9 Compat Modes */
src: local('☺'), url(data:application/x-font-woff;charset=utf-8;base64,longbase64encodedstring) format('woff'), url(data:font/truetype;charset=utf-8;base64,otherlongbase64encodedstring) format('truetype'), url('pictos-web.svg#webfontIyfZbseF') format('svg');
font-weight: normal;
font-style: normal;
}

When compressed the first src: url should not be removed, but it is:

@font-face{font-family:'pictos';src:local('☺'),url(data:application/x-font-woff;charset=utf-8;base64,longbase64encodedstring) format('woff'),url(data:font/truetype;charset=utf-8;base64,otherlongbase64encodedstring) format('truetype'),url('pictos-web.svg#webfontIyfZbseF') format('svg');font-weight:400;font-style:normal}

Moving this into an IE specific stylesheet is a fix for now, but it shouldn't fail when compressed.

Минимизация background-position

Если задано только одно свойство, то второе по дефолту становится равным 50%.

Это можно использовать так:

  1. background-position:10px 50%background-position:10px
  2. background-position:50% 0background-position:top

И т.д.

P.S. Кстати, я заметил, что background с шорхендами и дефолтами вообще почти не оптимизируется — создать про это отдельный issue?

Класс в :not() «обнуляется»

Если в селекторе :not() будет находиться какой-то класс, то первая его часть будет заменена на 0. См. например,

:not(el.class-postfix)
{
    color: red;
}

«сжимается» в

:not(el0-postfix){color:red}

Баг при объединении `margin` и отрицательного `margin-blah`

При попытке внести отдельно стоящее свойство с отрицательным значением в шортхенд остаётся только дефис, само значение теряется. Например, можно попробовать сжать

.a{margin:0}
.a{margin-top: -1em}

результатом будет

.a{margin:- 0 0}

Аналогично для margin-left и прочих.

Простая минимизация margin / padding

Добавить минимизацию margin / padding, если есть все размерности. Генераторы любят лишнее писать. Ничего больше этого не надо, никаких перекрываемых fake и т.п.

keyframes

Будет отлично если CSSO научится понимать keyframe

#button_account_add.pulsate img {
    -webkit-animation-name: pulsate;
    -webkit-animation-duration: 1s;
    -webkit-animation-timing-function: ease-in-out;
    -webkit-animation-iteration-count: infinite;
    }
    @-webkit-keyframes pulsate {
        0% {
            opacity: .5;
            }
        50% {
            opacity: 1;
            }
        100% {
            opacity: .5;
            }
        }

Спасибо за отличный продукт!

Можно обрубать ноли в конце десятичных дробей

Сабж: width:10.1000emwidth:10.1em

Ещё можно подумать над тем, чтобы (опционально) сокращать излишне длинные дроби (2.222222222222222222), но тут надо исследовать после какого знака браузерам становится всё-равно.

Можно убирать несуществующие и никем не используемые свойства с префиксами

Вспомнил пару моментов из доклада Пепелсбея про префиксы (вот кадр, например).

Смысл в том, что многие автоматические раскрыватели префиксных кластеров, а также многие верстальщики могут часто писать CSS3-свойство в префиком, которое в том или ином браузере не существует (т.е. изначально было реализовано без префикса). Это -o- и -ms- для border-radius и box-shadow, -o- для свойств column-blah и background-size и многие другие (хорошим источником для нахождения свойств, для которых никогда не существовало префиксов можно считать http://caniuse.com/).

Кажется, что совершенно безвредно было бы вырезать подобные конструкции из кода, скажем, вот такой вот кусок

-webkit-box-shadow: 10px 10px 1px red;
   -moz-box-shadow: 10px 10px 1px red;
    -ms-box-shadow: 10px 10px 1px red;
     -o-box-shadow: 10px 10px 1px red;
        box-shadow: 10px 10px 1px red;

Можно было бы сократить до

-webkit-box-shadow: 10px 10px 0 red;
   -moz-box-shadow: 10px 10px 0 red;
        box-shadow: 10px 10px 0 red;

(А если бы можно было гибко настраивать CSSO, то в теории можно было бы предусмотреть настройки поддерживаемых браузеров, тогда можно было бы исключать и -khtml- и -webkit- с -moz- для border-radius и box-shadow. Или и вовсе, для мобильных устройств вырезать всё кроме -webkit- и безпрефиксного варианта, а для .ie.css —вообще вырезать все CSS3-свойства)

Кстати, кажется, имеет смысл как-нибудь посмотреть на код, который генерят всякие SASS, Less, Compass и прочие, наверняка там можно попробовать найти ещё аналогичные места, которые можно сократить.

Организационное

Пожалуйста:

— Переведите документацию или хотя бы описание на английский язык
— Оставьте всё на Github (Temporary CSS-optimizer repo?)

Пора бы уже демонстрировать такие вещи и западной аудитории.

Добавить аргумент для вывода в файл

Сейчас для вывода результата работы утилиты в файл используется следующая конструкция:

csso style.css > style.css

Предлагаю дать возможность делать так:

csso style.css style.min.css

что будет по-моему немного удобнее

'color' + 'border-X: .. color' = 'color' + 'border-X: ..'

Т.к. border-top (и т.п.) в случае отсутствия собственного цвета подхватывает цвет у color (см. [CSS 2.1 / 8.5.4 Border shorthand properties]), в случае совпадения цветов можно делать вот так...

Было:

.test {
    color: red;
    border-left: solid red;
}

Стало:

.test {
    color: red;
    border-left: solid;
}

Оптимизация font

Сейчас, кажется, заданные font и его свойства по отдельности не склеиваются: a{font:11px/2 Arial;font-size:.86em;font-family:Verdana}

Ещё согласно http://www.w3.org/TR/CSS2/fonts.html#font-shorthand в записи вроде
font: normal normal 12px/1 Arial;
можно опускать оба normal.

Ещё можно попробовать для font-size 1.5em преобразовывать в 150%, а 200% в 2em и т.д. — это почти безопасно.
Почти = единственная разница будет в ие при изменении в браузере размера шрифта, но и то обычно во всех ресетах пофикшено заданием для body фонт-сайза в процентах.

Подружиться с gzip

Чем плотнее CSSO сжимает, тем меньше работы gzip и тем хуже иногда сжатие пары CSSO+gzip. Т.к. алгоритм DEFLATE основан на повторяющихся последовательностях, CSSO следует составлять как можно более однообразные строки. Например, пересортировывать селекторы по алфавиту, в итоге a, b { .. } .. b, a { .. } превратится в a, b { .. } .. a, b { .. }.

Сохранять хаки вида "w3c {} w3c, vendor {}"

Сейчас CSSO угробит хаки вот такого вида:

.my { color: red }
.my, x:-vendor-pseudo { color: green }

до

.my, x:-vendor-pseudo { color:green }

Пожалуй, единственный правильный вариант такое спасать — составить список всех вендорных селекторов, определять такие хаки и не перекрывать.

Removes vendor-specific CSS (prefixed) rules

background: #eee; /* Old browsers */
background: -moz-linear-gradient(top, rgba(255,255,255,.2) 0%, rgba(0,0,0,.2) 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,.2)), color-stop(100%,rgba(0,0,0,.2))); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, rgba(255,255,255,.2) 0%,rgba(0,0,0,.2) 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, rgba(255,255,255,.2) 0%,rgba(0,0,0,.2) 100%); /* Opera11.10+ */
background: -ms-linear-gradient(top, rgba(255,255,255,.2) 0%,rgba(0,0,0,.2) 100%); /* IE10+ */
background: linear-gradient(top, rgba(255,255,255,.2) 0%,rgba(0,0,0,.2) 100%); /* W3C */

becomes:

background: linear-gradient(top,rgba(255,255,255,.2)0%,rgba(0,0,0,.2)100%);

Оптимизации @media

Склейка одинаковых @media наверняка же когда-нибудь будет?

Так что напишу пока про совсем простую их оптимизацию: вот тут написали про то, что если задаёшь @media all and (min-width: 500px), то по спецификации можно опустить all and т.к. это и так значение по дефолту. Проверил: в современных браузерах, действительно, всё с этим нормально.

Ну и наверняка в спецификациях есть ещё какие-то моменты с медиакверями, надо будет ещё покопаться.

Вернуть ключи -dp и -r

Для разработки (фиксы, дебаг) нужны ключи дампа парсера и передачи имени rule. Документировать не надо, чтобы не сбивать с толку пользователей, которым это не требуется.

Отладочный режим

Очень хочется режим, с которым кроме результата будет выдаваться статистика о том что именно было прооптимизированно:
— какие свойства были удалены как перекрытые;
— какие именно оптимизации оказались самыми эффективными;
Ну и всё в том же духе.
Помимо практической пользы (можно, например, искать где что перекрывается) было бы просто забавно смотреть на статистику по тому какие методы оптимизации какой прирост дают :)

Баг в сжатии background-position

background-position: 0 эквивалентен background-position: 0 50%, следовательно, ошибочно сжимать background-position: 0 0 до background-position: 0.

(создаю отдельным issue, а не комментирую сюда т.к. бага важнее, чем фича)

Add `max line length` option

  1. Опция которая бы доавляла \n после каждого rulset - сохранит читабильность css.

  2. В замечательном проектке UglifyJS, который мы используем вместе с вашим есть опция --max-line-len:

    (default 32K characters) — add a newline after around 32K characters. I’ve seen both FF and Chrome croak when all the code was on a single line of around 670K. Pass –max-line-len 0 to disable this safety feature.

Собственно при больших CSS имеет смысл так же как и в JS.

Учёт встречаемости свойств при определении нужно ли склеивать

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

Например, сейчас у

.block1 {
    text-shadow: 1px 0 2px red;
    }
.block2 {
    text-shadow: 1px 0 2px red;
    }
.block3 {
    color: red;
    }
.block4 {
    text-shadow: 1px 0 2px red;
    }

будут оптимизированы только первые два блока, тогда как если это и есть вся таблица стилей, то безопасно склеивать блоки с одинаковыми значениями. А вот если бы появился какой-то селектор .block4 {text-shadow: 0 -1px 1px green;} (причём только где-то между этими свойствами т.к. если он будет в конце или начале, то вес селектора не позволит потом им что-то переопределить), то всё, мы только тогда начинаем бояться и всё делаем как и сейчас.

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

Ошибка в сжатии background (IE 7, IE 8)

.node {
    background:url('img/image.png')  no-repeat;
}

После сжатия:

.node{background:url('img/image.png')no-repeat}

Сочетание "')no-repeat" вызывает ошибку и правило не обрабатывается (IE 7, IE 8)
Если поставить пробел после скобки, то все работает.

Минимизация clip

Вот такую запись:

clip:rect(auto,auto,auto,auto)

Можно заменить на:

clip:rect(0,auto,auto,0)

Т.к. по сути свойства и спецификациям, auto в начале и конце эквивалентны нолям (но не в середине!)

'background-position' compression

Для background-position со значениями вида right top (9 символов) возможно сжатие до 100% 0% (7). То же для остальных пар.

Хочется не склеивать значения со значениями, использующими инлайновые IE-хаки

Есть два конкретных широко используемых хака для IE8/IE9 (например, вот тут их упоминают).

Первый, для IE8 и IE9, в конце свойства ставится конструкция \0/ (без пробела это правило поймёт ещё и опера):

.a {
    color: lime;
    color: red \0/;
}

Второй, только для IE9, в конце свойства пишется \9:

.b {
    color: lime;
    color: red\9;
}

Сейчас CSSO оставляет только второе значение, что логично. Но на практике было бы здорово знать, если эти правила поймут только соответствующие версии IE и не сжимать их.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.