- CSS selectors and weights
- Parse order
- Selector weight
- The weight grade
- Inline style refers to the style defined in the HTML document
- The ID selector
- Class, property selector, and pseudo-class selector
- Element and pseudo-element
- Weight memorizing tips
- CSS Weight rules
- The weight of actual combat
- The resources
- Понимание веса CSS-селекторов
- Вес селекторов
- Что такое вес селектора?
- Как это читать?
- Как заполнять?
- А что, если вес селекторов одинаковый?
- Зачем это нужно?
- Специфичность селекторов
- Выводы
CSS selectors and weights
The HTML is parsed to generate a DOM Tree (which we’re familiar with); After the CSS is parsed, the results need to be analyzed together with the content of the DOM Tree to establish a Render Tree, which is finally used for drawing.
Elements in the Render Tree (called «renderers» in WebKit and «frames» in Firefox) correspond to DOM elements, but are not one-to-one: A DOM element may correspond to multiple renderers. For example, after text is folded, different «lines» become different renderers of the Render tree. There are also DOM elements that the Render Tree ignores completely, such as the display: None element.
When creating a Render Tree (WebKit’s «Attachment» process), the browser determines what renderer to generate for each DOM Tree element based on CSS Style Rules. For each DOM element, a matching selector must be found in all Style Rules and the corresponding Rules must be combined. This is where the «parsing» of the selector is actually performed, looking for the corresponding selector from the Style Rules as it traverses the DOM Tree.
Parse order
CSS matches are not found from left to right, but from right to left. In left-to-right order, each selector would need to traverse the entire DOM tree, and performance would suffer. Efficient CSS allows the browser to do as little searching as possible when looking for elements that match the style, so selectors should be written succinctly.
Selector weight
Each rule of a selector has its own weight. A rule with a high weight overwrites a rule with a low weight. Many CSS problems occur because a rule with a higher weight is defined somewhere, which makes the rule invalid.
Depending on where the style is located, the effect on the element is also relevant: inline style (style within the tag) style tag link tag.
Another thing to watch out for! Improtant, all attribute values added! Important, then its value will not be replaced by other values.
The weight grade
Each selector has its own distinct position in the weight level. According to the different types of selector can be divided into four categories, also determines the weight value of four different levels.
Inline style refers to the style defined in the HTML document
Inline styles included in your HTML have a direct effect on your elements, such as:
h1 style="color: #fff;"header/h1 Copy the code
The ID selector
Id is also an identifier for an element, such as #div
Class, property selector, and pseudo-class selector
This class includes various classes, attribute selectors, pseudo-class selectors such as hover,:focus, and so on.
Element and pseudo-element
Element and pseudo-element selectors, such as :before and :after.
Weight memorizing tips
Starting at 0, an inline style +1000, an ID +100, an attribute selector /class or pseudo-class +10, an element name, or pseudo-element +1
body #content .data img:hover Copy the code
The final weight is 0122; #content is an ID selector with 100,.data is a class selector with 10, the: hover pseudo-class selector with 10, and body and img elements with 1. See CSS Specificity in detail
CSS Weight rules
Equal weight: The selector that appears later is the final rule
Different weights: High weights take effect
section style .weight #weightP color: red; // 0110 > .weight p#weightP color: gray; // 0111 effective>#weightP color: green; // 0100 > /style p Title /p /sectionCopy the code
2. Id selectors have a higher weight than attribute selectors
A: a#a-02 < background-image : url(n.gif); >// The weight is high and B: a[id="a-02"] < background-image : url(n.png); >Copy the code
Contextual selectors are more important than pure element selectors
This rule also applies to selectors with multiple elements.
4. The «proximity» rule works
For example, in CSS we define the following rules,
#content h1 padding: 5px; > Copy the code
But rules are also defined in HTML:
style type="text/css" #content h1 padding: 10px; > /style Copy the code
Rules defined in Html take effect because they are close to elements.
5. The last rule defined overrides the conflicting rules above
Take the following example:
Paragraphs appear as green text. Of course, a yellow background also appears, because the first rule just overwrites the color attribute.
6. No class selector has a higher weight, no matter how many elements it consists of
For example, «.introduction «is higher than» HTML body div div H2 P «.
7. Wildcard selectors also have weights, which are considered 0,0,0,0
For example, *, body * inherits CSS attributes with weights, which are 0,0,0,0.
The weight of actual combat
1. Use LVHA to style links: If you want to display link styles in different states, remember the order link-visit-hover-active, or LVHA for short. 【Link Specificity】
2. Never use «! Important «:» If you have a weight problem, the first solution is to remove it! Important «, «! Important «overrides all style rules, but»! «Important» has no structure or context at all, so it is rarely used.
Select id from ul#blogroll a.highlight instead of a.highlight. The weight is 0, 0, 1, 1, 2.
4. Reduce the number of selectors: «Use as few selectors as possible in your CSS rules.»
The resources
1. Something you should know — CSS weights
Понимание веса CSS-селекторов
Как и любая моя статья, эта начинается с введения. Дабы не говорить на разных языках, начнём с самых основ в мире CSS, то есть с терминологии. Чувствую себя преподавателем в университете — как же это круто.
Для того чтобы успешно разбираться в CSS и стать крутым специалистом в этой области, нужно первым делом разобраться с тем, что называют селектором. На изображении ниже представлена простейшая структура CSS-правила.
Селектор — это строка, представляющая собой формальное описание структуры, на основе которого выбирается элемент или группа элементов в дереве документа и применяется объявленный блок свойств.
Селекторы бывают самые разные. Существуют простые селекторы, например, состоящие из одной буквы или одного слова, и сложные, состоящие из большого количества слов и различных синтаксических конструкций.
Я не буду вдаваться в подробности того, что селекторы должны начинаться с буквы и некоторых других символов. Я также не буду говорить про неинтересные прописные истины, которые можно найти в любой статье на тему основ CSS. Речь в этой статье пойдёт про вес CSS-селекторов, а если говорить простым языком — о его числовом представлении и понимании.
Вес селекторов
Нет, здесь не идёт речь об их реальном весе (его нет), а также о количестве символов. Такой вес нельзя измерить весами, так как он не вещественен в обычном понимании и вообще не существует в нашем с вами мире людей. Зато он есть в виде нулей и единиц. Получается, что селектор можно взвесить, используя некую систему, о которой мы и будем говорить дальше.
Что такое вес селектора?
Вес селектора — это условные четыре позиции x, x, x, x , которые заполняются нулями и единицами в соответствии с содержимым селектора. Каждая из позиций имеет своё содержимое:
- Инлайн стили
- Идентификаторы
- Классы, атрибуты и псевдоклассы
- Теги и псевдоэлементы
Как это читать?
Очень просто. Справа налево. Слева идут числа старшего разряда, поэтому они имеют больший вес, числа, идущие справа, наоборот, имеют наименьший вес. Всё это станет понятным дальше, поэтому можно даже не вдумываться в смысл этого абзаца.
Как заполнять?
Немного сложнее, чем читать. Рассмотрим предложенную систему четырёх позиций на реальном примере для того, чтобы понять всю технологию.
В этом примере селектором выступает заголовок h1 , который состоит из одного тега. Получается, что напротив столбца «тег» мы ставим единичку. Получается следующая картина: 0, 0, 0, 1 .
Всё это замечательно, но в реальных проектах встречается разве что в ядре стилей или normalize, а это значит, что нужно усложнить задачу.
#main .container article.post > header h1.giga
Пример получился хардкорнее, чем предыдущий и в реальной жизни достоин премии «самого избыточного селектора». Такая избыточность должна преследоваться по закону, но подробнее на эту тему мы поговорим в отдельной части статьи. Окей, вернёмся к примеру и немного поработаем весами.
Давайте начнём слева, так как в начале стоит единственный идентификатор #main . Далее мы видим три класса .container , .post и .giga , а также три тега article , header и h1 . Для ещё большей наглядности я распишу это в виде этапов:
// Селектор #main .container article.post > header h1.giga // Начальный вес 0, 0, 0, 0 // Идентификаторы #main 0, 1, 0, 0 // Классы, атрибуты и псевдоклассы .container 0, 1, 1, 0 .post 0, 1, 2, 0 .giga 0, 1, 3, 0 // Теги и псевдоэлементы article 0, 1, 3, 1 header 0, 1, 3, 2 h1 0, 1, 3, 3 // Итог #main .container article.post > header h1.giga => 0, 1, 3, 3
Давайте напишем какой-нибудь безбашенный селектор, который я, надеюсь, никогда не увижу ни у кого в коде:
// Селектор body.page-posts #main .container article.post ul.list-unstyled > li:first-child h2.article-title:hover < color: #333; >// Начальный вес 0, 0, 0, 0 // Идентификаторы #main 0, 1, 0, 0 // Классы, атрибуты и псевдоклассы .page-posts 0, 1, 1, 0 .container 0, 1, 2, 0 .post 0, 1, 3, 0 .list-unstyled 0, 1, 4, 0 :first-child 0, 1, 5, 0 .article-title 0, 1, 6, 0 :hover 0, 1, 7, 0 // Теги и псевдоэлементы body 0, 1, 7, 1 article 0, 1, 7, 2 ul 0, 1, 7, 3 li 0, 1, 7, 4 h2 0, 1, 7, 5 // Итог body.page-posts #main .container article.post ul.list-unstyled > li:first-child h2.article-title:hover => 0, 1, 7, 5
Ну и напоследок, для полного понимания темы, будет пример с атрибутами и псевдоэлементами.
// Селектор .main[data-columns]:before < content: "3 .column.size-1of3"; >// Начальный вес 0, 0, 0, 0 // Идентификаторы 0, 0, 0, 0 // Классы, атрибуты и псевдоклассы .main 0, 0, 1, 0 [data-columns] 0, 0, 2, 0 // Теги и псевдоэлементы :before 0, 0, 2, 1 // Итог .main[data-columns]:before => 0, 0, 2, 1
На самом деле, тема очень простая, но очень важная на практике для посредственного (минимального) понимания того, как браузер определяет какой блок объявлений необходимо применить к тому или иному элементу на странице.
А что, если вес селекторов одинаковый?
Допустим, что у вас есть два или несколько селекторов так или иначе указывающих на один и тот же элемент. И вот так сложилось, что вы посчитали или просто взглянули на них, и вес оказался одинаковым. Не стоит отчаиваться, просто блок объявлений последнего селектора в вашем CSS-коде из этой группы и будет применяться к элементу. Как-то так. Мне кажется это логичным. Прямо как в поговорке «кто не успел, тот опоздал», но наоборот: «кто опоздал, тот и успел».
Зачем это нужно?
Это очень интересный момент, ибо понять какой блок объявлений будет применяться к элементу, можно и без расчёта веса селектора, то есть просто посмотрев на него и слегка подумав. Однако, глазомер может подвести, а вот машина не подведёт, посчитает вес и испортит вёрстку. Ошибка, конечно, не машины, а прослойки между компьютером и стулом, но это уже совсем другая история.
Ещё одним применением такого вот расчёта являются сервисы или скрипты, которые строят диаграммы специфичности CSS. Это может быть очень удобно для анализа и оценки избыточности вашего кода.
Интересным фактом будет то, что единственный раз, когда мне приходилось считать вес селектора, был тестом от Mail.ru на какой-то сертификат. Если интересно, то я поищу этот тест у себя в истории.
Я ленивый и не хочу понимать, как считать вес селекторов, что тогда?
Ох, специально для вас у меня есть сервис, на который я наткнулся при подготовке к изложению этого материала: Specificity Calculator — это простой и эффективный калькулятор веса селекторов.
Специфичность селекторов
Раз уж зашла речь про вес CSS-селекторов, то неизбежно задумываешься о том, как бы его оценить: когда нужно ему худеть, а когда наоборот — поправляться. Как и у человека, у селекторов всё таки есть оптимальный вес.
Так сложилось, что многие веб-разработчики считают оптимальной специфичностью селекторов три вложения. Максимальной специфичностью селекторов называется пять вложений и рекомендуется стараться это число не превышать. Разумеется, вложений может быть и больше, так как в жизни всякое бывает. Хотя, лучше всего, если вы всё таки будете соблюдать эту рекомендацию хотя бы косвенно. Такой подход вам поможет сэкономить время в будущем.
Хорошо, всё это замечательно, но причём тут вес? — да очень просто, он напрямую от этого зависит. Чем больше вложений, тем больше вес. Логично, однако.
Оценить ваш CSS-код можно с помощью ресурса CSS Specificity Graph Generator. По предложенному вами CSS-коду строится интерактивный график специфичности вашего кода, на котором можно визуально определить проблемные участки ваших стилей.
Выводы
Постарайтесь поддерживать оптимальный вес селекторов и изредка проводите рефакторинг кода. Сначала это кажется избыточным и ненужным, но в итоге это может сыграть с вами плохую шутку.
Делимся на оплату хостинга или кофе.
Чем чаще пью кофе, тем чаще пишу статьи.