Pull to refresh

Unlimited IE one-time CSS expressions

Reading time 3 min
Views 1.4K
В поддержку дней CSS expressions на хабре

Думаю все, кто сталкивался с решением каких-нибудь проблем в IE<8 знает про CSS expressions и про «одноразовые» CSS expressions, которые применяются к элементу только один раз, тем самым не создавая постоянной нагрузки на процессор. Обычно это решается так:
.my-class {
    behavior: expression(someMagick(), runtimeStyle.behavior = 'none');
}

Чтобы использовать больше свойств помимо behavior обычно используют ещё какие-нибудь «бесполезные» свойства, или же свойства, на которые оказывает своё влияние expression.

А что если мы не знаем сколько и каких будет свойств и не можем это контролировать (не спрашивайте меня зачем и почему)? В добавок к этому элемент может попасть под условия нескольких селекторов и одинаковые свойства будут попросту затёрты теми, которые идут ниже в коде! Может начать выдумывать свои уникальные свойства? Expressions у нереальных свойств ведь тоже работают! Но всё не так просто: реальные (существующие) свойства используют только потому, что они доступны через runtimeStyle, где их можно переопределить; нереальные (выдуманные) свойства через runtimeStyle недоступны, но доступны только для чтения в currentStyle, что является довольно бесполезным в делах с one-time expressions (хотя кое-какая польза от этого может быть, но это отдельная тема).

Из этого не трудно догадаться, что задача звучит как: найти способ переопределения несуществующих свойств.

Изначально нам дано:
.cute-font {
    my-really-random-property: expression(style.fontFamily = 'Comic Sans MS');
}

Первое (на самом деле не первое, но это единственное, что я запомнил), что пришло мне в голову — это дать элементу дополнительный класс, в котором и обнулить свойство:
.cute-font {
    my-really-random-property: expression(
        style.fontFamily = 'Comic Sans MS',
        this.className += ' my-really-random-property-clear'
    );
}

.my-really-random-property-clear {
    my-really-random-property: none;
}

Но это не заработало. Всё дело в том, что expressions навешиваются особым образом, отличным от обычных свойств. Внутри браузера, конечно, может происходить иначе, но опять же наводит на мысли:
.cute-font {
    my-really-random-property: expression(
        style.fontFamily = 'Comic Sans MS',
        this.className += ' my-really-random-property-clear'
    );
}

.my-really-random-property-clear {
    my-really-random-property: expression();
}

Но и это не сработало, причём причина очевидна — т.к. expression пустой он был проигнорирован! Поэтому добавим туда простейшее выражение, которое никак не нагрузит процессор:
.cute-font {
    my-really-random-property: expression(
        style.fontFamily = 'Comic Sans MS',
        this.className += ' my-really-random-property-clear'
    );
}

.my-really-random-property-clear {
    my-really-random-property: expression('');
}

Теперь этот expression можно считать одноразовым. Чтобы визуально убедиться изменим код таким образом:
.cute-font {
    my-really-random-property: expression(
        style.fontFamily = 'Comic Sans MS',
        this.innerHTML += ' It Works!',
        this.className += ' my-really-random-property-clear'
    );
}

.my-really-random-property-clear {
    my-really-random-property: expression('');
}

Загрузка процессора при активности на странице (шевелении мышкой, скроллинге, ресайзе окна) ничем не отличается от загрузки процессора на такой же странице без expressions вообще при 100 элементах, больше проверять не стал, т.к. с рабочими (не one-time) expressions загрузка заметна.

Зачем такое может понадобиться решать вам, у меня были на то причины и возможно в скором времени я поведаю о них ; )

UPD: Мне на почту написал Павел Володько и предложил усовершенствованное решение, которое избавляет от создания дополнительного правила:
.cute-font {
    my-really-random-property: expression(
        style.fontFamily = 'Comic Sans MS',
        innerHTML += ' It Works!',
        runtimeStyle.cssText += 'my-really-random-property: expression("") !important;'
    );
}

Как видно, мы просто дописываем обнуление данного свойства прямо в это же правило! !important туда добавил уже я, по совету tenshi, хоть при таком раскладе для IE6 это и будет бесполезным : D
У Павла, кстати, нет аккаунта на Хабре, и было бы здорово, если кто-нибудь выслал ему инвайт (для этого напишите мне и я дам вам его e-mail).
Tags:
Hubs:
+29
Comments 11
Comments Comments 11

Articles