Skip to content
Tags

Специфичность правил в CSS

13/10/2009

Сегодня довелось познакомиться поближе с понятием CSS specificity. Началось всё со странного (с моей точки зрения) поведения браузеров. Код был примерно таким:

	<head>
	<style>

		table {
			width: 80%;
		}

		table.rating td {
			text-align: left;
			border: 1px solid gray;
			border-collapse: collapse;
		}

		td.number {
			text-align: center;
		}
	</style>
	</head>
	<body>

		<table class="rating">
			<tr>
				<th>Head 1</th>
				<th>Head 2</th>
				<th>Head 3</th>
			</tr>
			<tr>
				<td>10</td>
				<td class="number">20</td>
				<td class="number">30</td>
			</tr>
		</table>

	</body>
	</html>

По моей логике, раз оба правила обращаются к одной ячейке, применяться должно то которое стоит ниже в коде (CSS cascading). Однако браузеры упорно сдвигали цифры влево, а Firebug показывал что правило, стоящее выше в коде перекрывает то которое стоит ниже, никак это не объясняя.

Стало быть, проблема в стилях, а не в браузерах, решил я, и перед тем как постить вопрос на StackOverflow решил прошвырнуться по документам W3C о сортировке правил в CSS.

Итак, оказалось что правила сортируются в три этапа. Вначале — по источнику и важности, в таком порядке:

  • user-agent declarations
  • user normal declarations
  • author normal declarations
  • author important declarations
  • user important declarations

Чем правило ниже в этом списке, тем больше у него приоритет. Т.е. обычные стили сайта перекрывают обычные пользовательские стили, но перекрываются важными стилями автора и пользователя. Что меня тут удивило — то что правила автора вставлены «между» правилами пользователя. Я с пользовательскими правилами пока дела не имел, так что сталкиваться не приходилось, но поведение любопытное.

На втором этапе сортировки правила сортируются по специфичности (specificity). Специфичность считается так:

Сама специфичность состоит из трёх чисел: a,b,c,d , и рассматривается как четырёзначное число в большой системе счисления.

  • a принимается равной 1 если правило находится в атрибуте style в HTML и 0 в остальных случаях. Это сразу выделяет правила в style в «отдельный класс», всегда имеющий более высокий приоритет
  • b это число id-атрибутов в селекторе. При прочих равных правила с id-атрибутами всегда стоят выше чем правила без них
  • c это число других атрибутов и псевдоклассов
  • d — число имён элементов и псевдоэлементов

На третьем этапе правила с одинаковой важностью и специфичностью сортируются уже по позиции в CSS-файле или файлах. Чем ниже находится правило, тем выше его приоритет. Тут уже «ничьей» быть не может, даже если происхождение, приоритет и специфичность одинаковы одно из правил всегда окажется выше другого.

Итак, в моих стилях у селекторов одинаковое происхождение и важность. Посмотрим какая у них будет специфичность:

  • table: 0,0,0,1 (Одно имя элемента)
  • table.rating td: 0,0,1,2 (Один класс, два имени элемента)
  • td.number: 0,0,1,1 (Один класс, одно имя элемента)

Если вам понадобится вычислить специфичность правил (ни один из известных мне dev tools для браузеров этого не делает), можно воспользоваться онлайн-калькулятором.

Ну что ж, ещё один день прошёл не зря, я лучше понял CSS и в следующий раз уже не попадусь так просто на подобном поведении браузера. Чего и Вам желаю🙂

2 комментария
  1. Да есть такая штука. Поэтому всегда делаю полное наследование, т.е. типа:
    table.rating td{…}
    table.rating td.number{…}

    • kuroikaze85 permalink

      Да, тоже вариант🙂 Но всё равно полезно разбираться как оно внутри работает.

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s

%d такие блоггеры, как: