Каскадные Таблицы Стилей

индекс
323,95

Unlimited IE one-time CSS expressions

В поддержку дней 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).
+29
18 марта 2010, 14:17
45

комментарии (11)

+3
WilliamKidd #
Интересное исследование! Даже как-то не задумывался о нехватке свойств для одноразовых expression)
+1
ArtyV #
Главная проблема всё-же в переопределении. Если один и тот же элемент попадёт под 2 правила у которых expression в behavior, то сработает только последнее.
0
WilliamKidd #
Ну да, я понимаю, поэтому и используются для expression всяческие странные свойства для каждого нового правила.
НЛО прилетело и опубликовало эту надпись здесь
+1
ArtyV #
Что что? Вы никогда не слышали про то, что CSS кидает эксепшены? Ну вы даёте! Все об этом знают ещё с первого класса!
НЛО прилетело и опубликовало эту надпись здесь
+1
tenshi #
только для переопределения лучше !important задать, чтобы точно переопределить
0
ArtyV #
Как раз переопределять то и не хочется : D
+1
ArtyV #
А, понял, не про то переопределение подумал. Да, наверное так будет надёжнее
+2
egorinsk #
Я экспериментировал, есть интересная особенность у ИЕ: для не-существующих свойств он *всегда* будет перевычислять expression при любом движении мыши. Особенно если вы пишете код типа _width: expression() для ИЕ6 — ИЕ7 *всегда* будет вычислять этот expression.
+1
ArtyV #
Да, даже тогда когда этот элемент не будет уже подпадать под селектор, поэтому удаление класса, как решение, сразу было откинуто

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