Как структурировать классы CSS? Субъектами или аспектами?

Интересно, что лучше подходит для философии CSS:

  • Классы CSS отмечают объекты - ИЛИ -
  • Классы CSS отмечают аспекты

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

В первом случае каждая из ячеек будет иметь только один класс: product-price resp. product-price-sum (или price, а строка, например, имеет класс product) Другими словами: Классы идентифицируют вещи.

В случае двух ячеек будет иметь много классов, которые определяют свойства/аспекты цены продукта, например numeric и currency, и дополнительный класс sum для нижнего колонтитула. numeric будет определять выравниваемый текст, sum будет отмечать ячейку жирным шрифтом. Другими словами: Классы описывают вещи.

Я не могу решить, какой подход лучше. В прошлом я использовал смесь обоих, которая быстро привела к уродливой куче неструктурированных классов CSS с противоречивыми стилями и некоторыми уродливыми взломами !important.

Первый подход, очевидно, имеет некоторую избыточность, потому что у него будет много классов (product-*), и большинство из них будут иметь общие свойства CSS.

У второго есть проблемы, когда дело доходит до формата только одного места по-разному, скажем, цена цены продукта. Возможно, что есть и другие места, которые также имеют одинаковые три класса, но не имеют ничего общего с ценой продукта. В этом случае вам придется использовать окружающие теги HTML, чтобы каким-то образом "указать" конкретное место в файле HTML.

Существуют ли какие-либо эмпирические правила, рекомендации, проверенные концепции и т.д. о том, как справиться с этой проблемой?

Ответ 1

Просто наблюдение... Люди склонны забывать, что CSS является иерархическим. Позвольте мне дать вам очень простой пример (пожалуйста, теги сводятся к минимуму):

<table class="product">
    <thead>
        <tr><th>Name</th><th class="price">Price</th></tr>
    </thead>
    <tbody>
        <tr><td>Product 1</td><td class="price">1</td></tr>
        <tr><td>Product 2</td><td class="price">2</td></tr>
        <tr><td>Product 3</td><td class="price">3</td></tr>
    </tbody>
    <tfoot>
        <tr><td>Total</td><td class="price">6</td></tr>
    </tfoot>
</table>

вы можете создавать стили классов со стилем тега, чтобы указать, где будет использоваться стиль:

table { /* styles for all tables */ }
.product { /* styles for the product table */ }
.product thead { /* styles for the all product table header row */ }
.product thead th{ /* styles for header row generic column */ }
.product thead .price { /* styles for header row price column */ }
.product tbody { /* styles for the all product table data row */ }
.product tbody td { /* styles for data row generic column */ }
.product tbody .price { /* styles for data row price column */ }
.product tfoot { /* styles for the all product table summarize row */ }
.product tfoot td { /* styles for summarize row generic column */ }
.product tfoot .price { /* styles summarize row price column */ }

Или вы можете использовать только простые теги таблицы (теги th, thead, tbody и tfoot) следующим образом:

<table class="product">
    <tr class="header"><td>Name</td><td class="price">Price</td></tr>
    <tr class="data"><td>Product 1</td><td class="price">1</td></tr>
    <tr class="data"><td>Product 2</td><td class="price">2</td></tr>
    <tr class="data"><td>Product 3</td><td class="price">3</td></tr>
    <tr class="footer"><td>Total</td><td class="price">6</td></tr>
</table>

И CSS будет

.product { /* styles for the product table */ }
.product .header { /* styles for the all product table header row */ }
.product .header td{ /* styles for header row generic column */ }
.product .header .price { /* styles for header row price column */ }
.product .data { /* styles for the all product table data row */ }
.product .data td { /* styles for data row generic column */ }
.product .data .price { /* styles for data row price column */ }
.product .footer { /* styles for the all product table summarize row */ }
.product .footer td { /* styles for summarize row generic column */ }
.product .footer .price { /* styles summarize row price column */ }

Это не окончательное решение. Просто новый подход к проблеме.

Помните также, что вы можете указать некоторые состояния или дополнительную информацию в CSS с использованием пользовательских атрибутов. См. Этот пример:

<table class="product">
    <tr class="header"><td>Name</td><td class="price">Price</td></tr>
    <tr class="data"><td>Product 1</td><td class="price">1</td></tr>
    <tr class="data" selected="selected"><td>Product 2</td><td class="price">2</td></tr>
    <tr class="data"><td>Product 3</td><td class="price">3</td></tr>
    <tr class="footer"><td>Total</td><td class="price">6</td></tr>
</table>

Посмотрите, что атрибут "выбран" в теге "tr" не влияет на стандартную визуализацию таблицы, поскольку он не является признанным атрибутом тега, но может быть идентифицирован с помощью CSS (а также с помощью javascript, что здесь не так). Вот так:

.product tr[selected=selected] { /* styles for the selected row */ }

Ответ 2

Я бы рекомендовал пометку по объекту (атрибуту, а не отдельному элементу), поэтому class= "цена продукта" (2 тега), а не class= "цена продукта" (1 тэг). Если вы будете осторожны, это приведет к более чистым, легче поддерживать код. Если у вас возникли проблемы с! Important, попробуйте создать дерево того, как будут структурированы теги. Это поможет решить, на каком уровне дерева объявить определенные свойства, и в результате минимальное использование важности.

Ответ 3

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

Если я правильно понимаю ваши описания, с одним вариантом у вас будет что-то вроде этого:

<table>
  <tr> 
    <td>Product A</td>
    <td class="price">£1</td>
  </tr>
  <tr>
    <td>Product B</td>
    <td class="price">£2</td>
  </tr>
  <tr>
    <td>Total</td>
    <td class="price-sum">£3</td>
  </tr>
</table>

а затем CSS:

.price {
   text-align: right;
}

.price-sum {
   text-align: right;
   font-weight: bold;
}

а второй вариант будет примерно таким:

<table>
  <tr> 
    <td>Product A</td>
    <td class="numeric currency">£1</td>
  </tr>
  <tr>
    <td>Product B</td>
    <td class="numeric currency">£2</td>
  </tr>
  <tr>
    <td>Total</td>
    <td class="numeric currency sum">£3</td>
  </tr>
</table>

но почему бы и нет:

<table>
  <tr> 
    <td>Product A</td>
    <td class="price">£1</td>
  </tr>
  <tr>
    <td>Product B</td>
    <td class="price">£2</td>
  </tr>
  <tr>
    <td>Total</td>
    <td class="price sum">£3</td>
  </tr>
</table>

и

.price {
   text-align: right;
}

.sum {
   font-weight: bold;
}

Нет смысла указывать ячейку как "numeric", так и "currency", если все поля валюты всегда будут иметь оба класса - лучше дать валюте те же стили, что и числовые в таблице стилей, а затем просто использовать валюту в источнике:

.numeric, .currency {
    // etc.
}

.currency {
    // etc.
}

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

Единственное, что я могу сказать, это то, что если вам нужно использовать! важно переопределить свои собственные стили, вы делаете что-то неправильно!

Ответ 4

У второго есть проблемы, когда дело доходит до формата только одного места по-разному, скажем, цена цены продукта. Возможно, что есть и другие места, которые также имеют одинаковые три класса, но не имеют ничего общего с ценой продукта. В этом случае вам придется использовать окружающие теги HTML, чтобы каким-то образом "указать" конкретное место в файле HTML.

Разве это не означает "адресация" всей цели правил CSS и specificity? Я думаю, что это меньше, чем "обращение" и больше похоже на "namespacing";)

Лично я предпочитаю второй метод; Я предпочитаю использовать атрибут id для определения вещей;)
... но атрибут class тем не менее считается идентификатором элемента.

В конце концов, цель атрибута класса используется " для обработки общего назначения агентами пользователя." Я интерпретирую это как что значения, которые вы им даете, должны соответствовать потребностям вашего приложения.

Итак, если ваше приложение должно идентифицировать все цены на продукт - будь то для стилей CSS или для jQuery script или для чтения с экрана или любого другого - идентифицируйте их с атрибутом класса product-prices.

Если вашему приложению необходимо описать все числовые значения - опять же, будь то стилистика CSS или для jQuery script или программа чтения с экрана или что-то еще - укажите их с атрибутом класса numeric.

PS Не называйте это CSS class; назовите его просто атрибутом <<21 > . Если вы не работаете в Asp.NET, нет такой вещи, как CSS class и даже в Asp.NET - не должно быть CSS class.

Извините за несколько бесстыдных ссылок на мой собственный веб-сайт.

Ответ 5

Я думаю, что это немного личный подход. Мне также нравится иерархия, и я использую это много. Но я больше использую вариант сущности, но стараюсь избегать как можно большего количества разметки. Правило, которое я использую, - это названия, которые всегда идут с h1 или h2. И вы можете соответствующим образом подстроить свой объект. Так, например:

.product               { }
.product h1            { }
.product span.price    { }
.product span.discount { }

То же самое можно сказать о навигации:

ul.navigation          { }
ul.navigation li       { }
ul.navigation li.first { }
ul.navigation li.last  { }

И с учетом сказанного, я бы всегда говорил, иди за вариантом, у которого есть наименьшая сумма разметки, не теряя ваш обзор. Чистый код хорош.