Анализ лучших методов CSS.

Примечание редактора: данная статья описывает методы, которые реально используются в практической деятельности Yahoo! и вопросы, касающиеся методики кодирования. Вам наверняка будет интересно познакомиться с работой Джонатана Снука «Отделение HTML от CSS» и работой Робина Рендла «Элементарный дизайн с Sass». Пожалуйста, имейте в виду: некоторые из описанных методов не считаются наиболее передовой практикой — Ред.

Когда дело касается CSS (Cascading Style Sheets – иерархические [каскадные] стилевые таблицы, каскадные таблицы стилей; платформонезависимая спецификация, разработанная W3C для расширения возможности форматирования HTML-документов; в этой модели документ состоит из набора объектов. Все объекты в документе взаимосвязаны и объединены древовидной структурой. Использование CSS позволяет отделить структуру и содержание документа от уровня его представления пользователю), мне кажется, что священный принцип «разделения проблем» (SoC) приводит нас к увеличению наворотов, использованию устаревших подходов, избыточности, плохому кэшированию и другим негативным последствиям. Так вот, я убежден, что единственный способ улучшить создание стилевых таблиц – уйти от этого принципа.

Для тех из вас, кто никогда не слышал о принципе SoC в контексте веб-дизайна, можно рассмотреть аналогичный и широко известный подход с «разделением трех слоев»:

  • структура,
  • представление,
  • поведение.

Речь идет о разделении основных направлений на отдельные ресурсы: HTML документ, одна или несколько каскадных таблиц стилей и один или более файл JavaScript.

Но когда дело доходит до слоя представления, «передовые практики» выходят за рамки разделения ресурсов. Разработчики выполняют стилизацию документов, основываясь на таблицах стилей. Этот подход был описан Дейвом Ши в превосходном проекте под названием CSS Zen Garden. CSS Zen Garden (сад для созерцания) является нечто таким, что большинство — если не все — разработчиков считают стандартом того, как нужно создавать таблицы стилей.

Стандарт.

Чтобы было легче представлять вопросы, связанные с наиболее известными на сегодняшний день методами, я буду использовать очень распространенную схему: медиаобъект. Сочетание разметки и CSS будет нашей отправной точкой.

Разметка.

В нашей разметке, оболочка (div.media) содержит изображение, размещённое в ссылке (a.img) перед тегом (div.bd):

<div class="media">
  <a href="http://twitter.com/thierrykoblentz" class="img">
        <img src="thierry.jpg" alt="me" width="40" />
  </a>
  <div class="bd">
    @thierrykoblentz 14 minutes ago
  </div>
</div>

CSS.

Давайте зададим 10 пиксельное поле в оболочке и стилизируем оболочку и тег div.bd как блок контекстного форматирования (BFC). Другими словами, оболочка будет содержать ссылку, а содержимое div.bd не будет обернуто вокруг указанной ссылки. Величина внутреннего поля между изображением и текстом будет равна 10 пикселям (со свободным перемещением):

.media {
    margin: 10px;
}
.media,
.bd {
    overflow: hidden;
    _overflow: visible;
    zoom: 1;
}
.media .img {
    float: left;
    margin-right: 10px;
}
.media .img img {
    display: block;
}

Результат.

Вот представление оболочки с именем изображения в ссылке и текстом:
me
@thierrykoblentz 14 minutes ago

Появление нового требования.

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

Разметка.

Благодаря возможностям BFC, все, что нам нужно сделать – это изменить стиль ссылки. Для этого мы используем новый класс под названием imgExt.

<div class="media">
    <a href="http://twitter.com/thierrykoblentz" class="imgExt">
        <img src="thierry.jpg" alt="me" width="40" />
  </a>
  <div class="bd">
    @thierrykoblentz 14 minutes ago
  </div>
</div>

CSS.

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

.media {
    margin: 10px;
}
.media,
.bd {
    overflow: hidden;
    _overflow: visible;
    zoom: 1;
}
.media .img {
    float: left;
    margin-right: 10px;
}
.media .img img {
    display: block;
}
.media .imgExt {
    float: right;
    margin-left: 10px;
}

Результат.

Изображение теперь отображается на противоположной стороне:

@thierrykoblentz 14 minutes ago
me

Появление еще одного требования.

Предположим, что мы должны сделать текст меньше, когда модуль находится в правой части страницы. Чтобы сделать это, мы воспользуемся контекстным селектором с именем #rightRail:

Разметка.

Теперь наш модуль будет находиться внутри div#rightRail контейнера:

<div id="rightRail">
    <div class="media">
        <a href="http://twitter.com/thierrykoblentz" class="img">
            <img src="thierry.jpg" alt="me" width="40" />
        </a>
        <div class="bd">
            @thierrykoblentz 14 minutes ago
        </div>
    </div>
</div>

CSS

Опять же, мы создаём дополнительное правило, на этот раз, используя наследственные селекторы, #rightRail .bd.

.media {
    margin: 10px;
}
.media,
.bd {
    overflow: hidden;
    _overflow: visible;
    zoom: 1;
}
.media .img {
    float: left;
    margin-right: 10px;
}
.media .img img {
    display: block;
}
.media .imgExt {
    float: right;
    margin-left: 10px;
}
#rightRail .bd {
    font-size: smaller;
}

Результат.

Вот наш оригинальный модуль, показанный внутри div#rightRail:
me
@thierrykoblentz 14 minutes ag

Что не так с этой моделью?

  • Простые изменения в стиле нашего модуля привели к появлению новых функций (правил) в таблице стилей. Должен быть способ изменения стиля без обязательного добавления CSS правил.
  • Мы сгруппировали селекторы для распространенных стилей (.media,.bd {}). Группирование селекторов, вместо использования классов, связанных с этими стилями, приведёт к увеличению CSS.
  • Из наших шести правил, четыре являются контекстно-ориентированными. Контекстно-зависимые правила довольно трудно поддерживать. Стили, связанные с такими правилами, не пригодны к многократному использованию.
  • Усложняются RTL и LTR интерфейсы. Чтобы изменить направление, мы должны были бы переписать некоторые из наших стилей (т.е. использовать больше правил). Например:
.rtl .media .img {
    margin-right: auto; /* reset */
    float: right;
    margin-left: 10px;
}
.rtl .media .imgExt {
    margin-left: auto; /* reset */
    float: left;
    margin-right: 10px;
}

Знакомство с элементарными каскадными таблицами стилей.

Atomic (a·tom·ic)

/ Ə’ tämik/

формирование единого не поддающегося улучшению блока или компонента в большей по размерам системе.

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

«Старайтесь организовывать программный код, подобно Lego. Разбивайте код на минимально возможные блоки» — @csswizardry (через @stubbornella) #btconf

— Smashing Magazine (@smashingmag) 27 мая, 2013 года.

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

Давайте вернемся к медиаобъекту, используя этот новый подход.

Разметка.

Мы используем пять классов, ни один из которых не связан с контентом:

<div class="Bfc M-10">
    <a href="http://twitter.com/thierrykoblentz" class="Fl-start Mend-10">
        <img src="thierry.jpg" alt="me" width="40" />
    </a>
    <div class="Bfc Fz-s">
        @thierrykoblentz 14 minutes ago
    </div>
</div>

CSS.

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

.Bfc {
    overflow: hidden;
    zoom: 1;
}
.M-10 {
    margin: 10px;
}
.Fl-start {
    float: left;
}
.Mend-10 {
    margin-right: 10px;
}
.Fz-s {
    font-size: smaller;
}

Результат.

me @thierrykoblentz 14 minutes ago

О чём мы говорим?

Давайте немного отвлечёмся от имен классов и сосредоточимся на выполняемых ими функциях (или не выполняемых):

  • Отсутствие контекстной стилизации. Мы не используем контекстные или наследственные селекторы, а это значит, что наша таблица стилей не имеет избыточного веса.
  • Области (левая и правая) «абстрагируются». Вместо перезаписывания стилей, мы создадим RTL таблицу стилей, которая содержит функции, наподобие следующих:
.Fl-start {
    float: right;
}
.Mend-10 {
    margin-left: 10px;
}

Те же классы, те же свойства, но различные значения.

Самое главное, что нужно отметить в этом случае, так это то, что мы выполняем стилизацию через разметку. Мы изменили контекст, в котором были стилизированы модули. Сейчас мы выполняем редактирование HTML шаблона вместо таблиц стилей.

Я считаю, что такой подход является довольно эффективным, поскольку значительно сужает область изменений. Мы выполняем стилизацию не глобальной области (таблица стилей), а уровня модулей и блоков. Мы можем изменить стиль конкретного модуля, и при этом не нужно беспокоиться о нарушении других элементов страницы. И мы можем сделать это без добавления каких-либо функций в таблицу стилей, не говоря уже об отсутствии необходимости создания нового класса:

.someBasicStyleForThisElementHere {...}

Мы уходим от избыточности. Селекторы не дублируется, а стили принадлежат одному правилу, а не целому множеству. Например, таблицы стилей, на которые ссылается эта страница, содержат 72 float объявления.

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

Насколько хорошо звучат имена?

Я слышал, как вы говорили: «Это противоречит каждому правилу, приведенному в книге. Это не лучше, чем использовать встроенный стиль. Ваши имена классов не только непонятны, но также неверны семантически».

Нужно во всём следовать логике. Давайте решать эти проблемы.

Информация, касающаяся семантически неправильных имен классов.

Вы можете ознакомиться с «Советами для веб-мастера» от W3C (консорциум World-Wide Web), где говорится: «Хорошие имена останутся без изменений». Вы поймете, что это обсуждение касается удобства обслуживания, а не семантики как таковой. Вполне очевидно, что изменения стиля проще выполнить в одном файле CSS, чем в нескольких HTML файлах. .border4px – это плохое имя, особенно в случае, если в стиле элемента потребуется изменить объявление, что это имя класса. Другими словами,

.border4px {border-width:2px;}

Непонятные имена классов.

По большей части, имена классов выбираются в соответствии с синтаксисом Zen Coding — вы можете посмотреть «Компактную пользовательскую инструкцию Zen Coding» (в формате PDF) — уже переименованный в Emmet. Другими словами, это простые аббревиатуры.

Есть исключения для стилей, связанных с определенными областями (левая и правая) и стилей, которые включают комбинацию областей. Например, Bfc устанавливается для «блока контекстного форматирования».


Если вы хотите прочитать полностью статью, посетите сайт наших спонсоров

Comments are closed.