Переменные в CSS

Давайте помечтаем вместе с Йенсом Майертом (Jens Meiert) о реализации механизма переменных в CSS: CSS: Selector Variables. Суть предложенного решения проста: мы просто задаём псевдоним группе селекторов: @E = F и дальше используем его в коде, избегая лишних повторений.

Типичный код до использования переменных:

.messages-list .highlighted,
.messages-list .highlighted LI {
    overflow:hidden;
    }
.messages-list .highlighted LI .email,
.messages-list .highlighted LI .phone {
    cursor:pointer;
    }

Теперь объявляем переменные:

@list = .messages-list .highlighted;
@list-item = @list LI;

…и получаем:

@list,
@list-item {
    overflow:hidden;
    }
@list-item .email,
@list-item .phone {
    cursor:pointer;
    }

Кстати говоря, это не единственные мысли на эту тему. Чуть больше месяца назад на форуме Вебмаскона было опубликовано довольно интересное предложение по решению той же проблемы. В нашем случае, часть примера выглядела бы так:

.messages-list {
     .highlighted {
        LI {
            .email,
            .phone {
                cursor:pointer;
            }
        }
    }
}

…правда становится не очень ясно, куда, при такой форме записи, вставлять правила для вышестоящих селекторов. Видимо, в отдельных конструкциях. Может и у вас есть свои предложения по оптимизации CSS, не противоречащие духу самого языка?

ps: а вот уже черновики возможной спецификации CSS Variables и Symbolic constants.

Комментарии

30

Octane, а как тогда обозначать селектор @article в HTML-коде?

kizu, свойство lalala:lalala повисает в воздухе. Имхо, не слишком удачно

Во втором варианте для вышестоящих селекторов можно было бы использовать что-то вроде

.messages-list {
    {
        lalala:lalala;
        }
    .highlighted {

        }
    }

Хотя все-равно первый вариант экономнее, легче для чтения и его можно использовать в разных местах.

на каком-то блоге видел такую мысль, что-то похожее на описание медиатайпов существующих сейчас:

Создаем какой-то класс таким образом:

@article { } допустим это будет блок нашей статьи и все элементы внутри него описываем следующим образом:

@article {

   /* свойства самого блока */
   border: 1px solid #ccc;
   background: #f0f0f0;

   /* свойства вложенных в него тегов */
   p { margin: 0; padding: 10px; }
   a:link, a:active, a:visited { text-decoration: none; }
   abbr { border-bottom: none; }

  и т.д. и т.п.

}

в отличие от существующего сейчас способа:

.article {
   border: 1px solid #ccc;
   background: #f0f0f0;
}
.article p { margin: 0; padding: 10px; }
.article a:link, .article a:active, .article a:visited { text-decoration: none; }
.article abbr { border-bottom: none; }
}

Помоему неплохая идея, очень удобно и значительно сокращает код.

Ну да, или же вводить что-то вроде псевдоселектора :self, но это тоже не совсем то.
С переменными удобнее, хотя использование @

(недописал, сглючило %))
…хотя импользование @ странно, т.к. оно уже есть в @media и @import, тогда уж лучше $, который много где переменные означает.

Меня использование собаки немного смущает: всё-таки есть @media, @import…

upd. Хе, ну вот и я говорю :)

Octane, а как тогда обозначать селектор @article в HTML-коде?

как класс например, ну или вообще обычным способом через точку писать, иде в том чтобы понимались конструкции такого типа:

.article {
           border: 1px solid #ccc;

          p { ... }
          a:link, a:active, a:visited { ... }
          abbr { ... }
}

Бесплатный прокси для сжатия траффика toonel.net. Хм у меня на вордпрессе работает норм, на этом блоге что-то мешает отправке сообщений.

Бесплатный прокси для сжатия траффика toonel.net. Хм у меня на вордпрессе работает норм, на этом блоге что-то мешает отправке сообщений. 3 раза проверил)

Я склонен подходить к вопросу с другой стороны и в качестве решения проблемы избыточного CSS-кода предпочёл бы наследование единожды определённого набора правил в рамках существующего синтаксиса CSS:

.example {rules: values; } /* селектор (не обязательно класс), от которого будем наследовать */
.another-1 {inherit-from: selector(.example); индивидуальные правила для .another-1; }
.another-2 {inherit-from: selector(.example, ещё какой-нибудь селектор, и ещё); индивидуальные правила для .another-2; }

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

MT, фактически ты предлагаешь ООП: базовый класс и его расширение-уточнение. Согласен — это гибко.

У Йенса и МТ хорошие предложения. Предложить бы w3c и подстегнуть процесс внесения изменений в браузеры.

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

Ну и цитату в дополнение к сказанному:
Programs must be written for people to read, and only incidentally for machines to execute. (Abelson & Sussman)

Уточнения:

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

Программы = код.

Что-то это все начинает немного напоминать JavaScript =-)
А раз начинает почему бы не писать CSS-функции, которые буду автоматически вызываться по названию классов и айдишников в html-коде?
@ - обозначение функции.
$ - условный оператор if.

@#commentDiv (a, p, strong) {
    a(:link,:visited,:hover,:active) {
        color:#00F;
    }
    p {
        font-size:1em;
    }
    strong {
        color:#0FF;
    }
    span {
         font-size:1.5em;
    }
    $a>span {
         font-size:1em;
    }
}

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

:D Вас наверное всякие вложенные много раз циклические и условные конструкции на таких языках как JavaScript, PHP, Perl, C++ и д.р. вообще отпугивают?) Если применять форматирование кода (делать отступы напиимер :)) то все прекрасно читаемо) или использовать подсветку синтаксиса...

Оффтопик
Вадим, а ссылочки ранее/позднее чуть ниже формы не перепутаны местами случайно?

«Вложенные много раз циклические и условные конструкции» мне говорят о том, что есть проблемы. Особенно, если вложенность превышает глубину примерно в три уровня.

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

Форматирование кода я использую с окончания школы. С первого курса у меня сложился определённый стиль написания кода. Но при этом я прошёл все этапы - писал ужасный код, похожий на описанный вами, неправильно понимал, что хочу сделать, не думал прежде чем писать код. Время прошло - выводы сделаны и приняты на вооружение. Поэтому я очень хорошо чувствую, где код эстетичен, а где - нет. И ещё лучше чувствую, что никакие подсветки и форматирование не спасут от проблем, если вы будете писать огромные портянки кода с ужасающей вложенностью. Проблемы при этом будут самые простые, например проблемы координации - ведь очень легко забыть, где ты находишься, если не видно начала. Да и поддерживать такое чудовище я и врагу не пожелаю.

Вадим, а почему в комментариях такой маленький отступ перед абзацем? Межстрочный интервал в тексте и в коментариях одинаковый (на глаз), а вот отступ перед абзацем как-то маловат, тяжело для глаза.

czerny_angel, спасибо! Плагин для вывода этих вещей дописывался в 5 утра, так что меня можно понять )

Про константы в CSS-файлах впервые я прочёл на 24ways.org. Автор говорит, что есть пара решений на PHP. Одно придумал аж сам Шон Инман.

Сам не использую. :-) Ничего не могу сказать.

Вопрос про первый вариант.
Как его правильно реализовать? Просто в цсс написать @list = .messages-list .highlighted; разве достаточно?

Сергей, пока ни один браузер не поддерживает переменные в CSS, более того — даже нет внятной спецификации, только предположения.

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

$color1 = #345678;
$color2 = #abcdef;
...
#selector1 {color:$color1; background-color:$color2; border:1px solid $color1}
#selector2 {color:$color2; background-color:$color1; border:1px solid $color2}

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

А еще, как мне кажется, незаслуженно зарубили идею с expression. Все-таки было бы здорово иметь возможность выставить ширину блока 100%-200px.

иметь возможность выставить ширину блока 100%-200px.

Если не ошибаюсь, такая возможность будет в спецификации CSS3 без всяких expression и выглядеть будет так:

#conteiner {
width: calc(100% - 200px);
}

такая возможность будет в спецификации CSS3 без всяких expression

Ну, собственно, это и есть expression, только порезанный и называется по-другому. :)
Нормальные браузеры будут поддерживать такой синтаксис, а для ИЕ можно будет писать expression-ы.

Но по-настоящему полезными вычисления будут если в них можно будет использовать вычисляемые размеры других блоков. Что-то вроде:

#container {height:calc(100%-height(#footer));}

@property {
    codeFont {
        font: 12px "Courier New", Courier, monospace;
        color: #666;
    }
}

pre {
    border:1px dotted #F96;
    background:#eee;
    codeFont;
}