Какое максимальное значение специфичности css

CSS каскадирование, специфичность, наследование: что это и как правильно использовать?

Любой профессионал своего дела должен владеть терминологией. Если Вы занимаетесь версткой, можете ли без раздумий ответить на вопрос в заголовке статьи?

Возможно сейчас вы откроете для себя что-то новое. Давайте сделаем решительный шаг на пути к профессионализму:)

Наследование

Начнем с самой простой для понимания концепции CSS. Суть ее состоит в том, что стили, присвоенные некоторому элементу, наследуются всеми потомками (вложенными элементами), если они не переопределены явно. Например, размер шрифта и его цвет достаточно применить к дескриптору body чтобы все элементы внутри имели те же свойства. Но, для заголовков h1-h6 размер шрифта не будет присвоен, потому что у браузера для них есть своя таблица стилей по умолчанию, а наследованные стили имеют самый низкий приоритет. Аналогичная ситуация с цветом ссылок.

Таким образом, наследование позволяет сократить таблицу CSS. Но в то же время если стилей много, то отследить какой родительский элемент установил некоторое свойство, становится довольно сложно.

Каскадирование

Правила каскадирования позволяют разрешать ситуации, когда для одного элемента прописано несколько стилей. Каскадирование основано на присвоении некоторого приоритета каждому правилу. Авторские таблицы стилей имеют самый большой приоритет, меньший — пользовательские, самый низкий — таблицы стилей по умолчанию браузера. У пользователя есть возможность переопределить авторское правило путем добавления флага !important к своему.

Правила каскадирования определяют следующие приоритеты:

  1. пользовательские стили, отмеченные !important
  2. авторские стили, отмеченные !important
  3. авторские стили
  4. пользовательские стили
  5. стили по умолчанию

После каскадирования правила упорядочиваются на основе специфичности селекторов.

Специфичность

Специфичность — это некоторое число в системе с неопределенно высоким основанием, которое является отражением приоритета какого-либо правила. Вычисляется оно на основе специфичности каждого из селекторов, входящих в правило CSS.

Специфичность селектора разбивается на 4 группы — a b c d:

  • если стиль встроенный, т.е. определен как style="", то а=1
  • значение b равно количеству селекторов идентификаторов
  • значение c равно количеству классов, псевдоклассов и селекторов атрибутов
  • значение d равно количеству селекторов типов

Пример вычисления специфичности:

Селектор Специфичность Специфичность в системе
с основанием 10
Style="" 1,0,0,0 1000
#wrapper #content <> 0,2,0,0 200
#content .datePosted <> 0,1,1,0 110
div#content <> 0,1,0,1 101
#content <> 0,1,0,0 100
p.comment .datePosted <> 0,0,2,1 21
p.comment <> 0,0,1,1 11
div p <> 0,0,0,2 2
p <> 0,0,0,1 1

Неопределенно высокое основание системы счисления является следствием того, что неизвестно заранее, насколько большими будут числа a, b, c, d. Если они меньше 10, то удобно использовать десятичную СС.

  • если два правила имеют одинаковую специфичность, то приоритетным становится правило, определенное последним
  • наследованные стили имеют нулевую специфичность

На сегодня все. Комментируем, добавляем, исправляем:)

При подготовке статьи использовалась книга Энди Бадд: &#171;Мастерская CSS: профессиональное применение web-стандартов&#187;.

Проблема специфичности CSS и ключевое слово !important

Не так давно какой-то пользователь создал в Twitter опрос о CSS специфичности. Большинство ответило на него неверно. В статье мы расскажем про CSS детальнее.

В этой статье мы проведем рефакторинг CSS-кода одного проекта с проблемами специфичности.

CSS специфичность

Определение

MDN Web Docs описывает специфичность, как: способ, с помощью которого браузеры определяют, какие значения свойств CSS наиболее соответствуют элементу и, следовательно, будут применены.

Правила

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

В таком случае будет использоваться специфичность CSS-селектора. Чем выше его специфичность, тем больше шансов, что браузер применит именно это объявление CSS.

В примере выше оба CSS селектора нацелены на одинаковый HTML элемент – якорный тег. Для определения нужного правила браузер рассчитывает значения специфичности и проверяет, какое из них является наивысшим. В данном случае, высшее значение оказалось у первого селектора, поэтому к якорному тегу браузер применит именно его.

Важный момент: !important – это не CSS- селектор, а ключевое слово, которое принудительно переопределяет CSS-правила вне зависимости от значения специфичности, источника или исходного порядка следования селекторов. Несколько примеров использования:

  • Временные решения (пример: вы временно заматываете изолентой подтекающую трубу);
  • Переопределение встроенного стиля;
  • Тестирование/отладка.

Несмотря на кажущуюся важность !important проблем от него намного больше, чем пользы. Со временем осложняется поддержка CSS и ухудшается читаемость таблицы стилей. Особенно от этого страдают те, кто работает/будет работать с кодом в будущем.

Проект

Пара слов о проекте, который будем рефакторить: это лендинг в стиле Netflix с использованием интерфейса MovieDB.

Таблица стилей

Основная цель – удалить ключевое слово “!important” из CSS-правил и провести рефакторинг кода, чтобы он применял только правила специфичности.

Ниже представлена таблица стилей проекта.

Мы видим, что чаще всего !important используется в разделе с медиа-запросами, описывающими стили, которые браузер применяет при ширине экрана меньше 750 пикселей.

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

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

Если CSS-селекторы с конфликтными правилами обладают разной специфичностью, то браузер выбирает правило селектора с наивысшей специфичностью. Этот принцип подходит нашей таблице стилей. CSS-селекторы в медиа-запросах обладают более низкой специфичностью, чем CSS-селекторы в основной части таблицы стилей.

Проблема определена. Пора переходить к ее решению!

Для начала найдем CSS-селекторы, соответствующие селекторам медиа-запросов.

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

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

Конечный результат выглядит так:

Вот и все! Мы удалили все следы присутствия ключевого слова !important в стилях. Читаемость кода возрастает на глазах. После рефакторинга такую таблицу будет легче применять и поддерживать.

Заключение

Мы узнали о том, как именно браузеры выбирают CSS стилей по исходному порядку следования, специфичности и источникам селекторов. Познакомились с проблемами, возникающими при использовании !important в CSS, и научились сводить количество этих ключевых слов в коде к минимуму.

Больше не нужно добавлять !important для решения проблем – есть куда более достойные решения.

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

Больше интересных новостей

Лучшие языки для автоматизации тестирования в 2020 годуЛучшие языки для автоматизации тестирования в 2020 году
Как взять первый заказ на фрилансе? 10 советовКак взять первый заказ на фрилансе? 10 советов
Вот почему тебе не дано становиться программистом: 7 признаковВот почему тебе не дано становиться программистом: 7 признаков
Developer Survey 2020: результаты отчёта Stack OverflowDeveloper Survey 2020: результаты отчёта Stack Overflow

Специфика CSS специфичности

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

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

Теперь, допустим, мы хотим визуально выделить один из напитков, который является наиболее предпочтительным. Для этого нужно предусмотреть соответствующий инструмент – указать имя класса для требуемого элемента списка:

Далее необходимо просто определить нужные CSS свойства в рамках правила с соответствующим селектором:

Осталось лишь посмотреть на результат работы этого кода. Но увы, мы не получили ожидаемого эффекта – текст выбранного нами напитка ( Whiskey ) не будет выделен и отображается также, как и остальные элементы списка. В чем же дело?

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

Именно это CSS правило содержит определения, препятствующие визуальному выделению желаемого элемента списка. В используемом документе находится два различных CSS селектора, применяемых к одному элементу ( .favorite и ul#drinks li ), которые предусматривают различные значения для цвета и толщины шрифта, содержащегося в нем текста. Что касается размерности шрифта, то здесь все понятно – рассматриваемый код содержит лишь одно выражение, определяющее его значение ( font-size: 13px ), поэтому именно оно и будет использоваться. Проблема, в данном случае, заключается в том, что браузер должен определить, какому из конфликтующих правил отдать предпочтение в процессе обработки документа. Как раз для этих целей и предназначены значения CSS специфичности каждого из правил.

Большинство проблем возникает у начинающих веб-разработчиков, которые не понимают, по какому принципу производится выбор рабочего правила. Они, как правило, предполагают, что приоритетом должен обладать селектор .favorite , так как он находится ниже в структуре CSS кода или потому, что определение атрибута class="favorite" в HTML разметке документа находится ближе к текстовому содержимому интересующего нас элемента страницы ( <li> ). Но все это, конечно же, заблуждения.

Да, действительно, CSS спецификацией предусмотрено, что положение правила в структуре кода имеет значение. И то из них, которое расположено ниже, действительно обладает приоритетом, но только в том случае, если значения специфичности рассматриваемых выражений одинаковы. Вот пример:

В этом случае цвет шрифта выбранного элемента списка будет черным ( *поскольку последнее правило переопределяет значение первого ). Но мы немного отклонились от темы.

Здесь работает несколько иной принцип. Всякий раз, когда вы формируете селектор для CSS правила, всегда делайте его настолько специфичным (конкретным), насколько это возможно и оправданно. ( *Для этого необходимо применять более сложные селекторы ). При рассмотрении простейшего примера, приведенного выше, вы, вероятно, сами догадались, что использование лишь имени класса .favorite для селектора, выбирающего требуемый напиток из списка, будет недостаточным. И это не позволит извлечь из общего списка «нужный напиток» для его дальнейшего форматирования. А если это все-таки каким-то образом сработало один раз, то нет никакой гарантии, что в будущем все пройдет так же гладко. Для достижения желаемого результата необходимо использовать более конкретный селектор:

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

Такой селектор тоже допусти&#769;м, но он слишком «захламляет» CSS код, что значительно снижает его читабельность. К тому же от такой избыточности нет никакого толку. Существует и другой способ «вычленения» требуемого элемента, путем повышения значения CSS специфичности селектора .favorite при помощи декларации ! important :

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

Если использовать ключевое слово ! important не по назначению, то можно лишь усложнить себе задачу. В том случае, когда вы хорошо знакомы с определенным CSS кодом и знаете, для каких целей используется каждый, содержащийся в нем селектор, то применение декларации ! important вполне оправдано для упрощения структуры кода и повышения его читабельности. Но если же вы применяете его с целью быстрого переопределения свойств, предусмотренных другим автором, не вникая в структуру кода и принципы его работы, то это может привести к нежелательным последствиям.

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

Я применяю данный класс в тех случаях, когда на странице имеется несколько «плавающих» блоков ( *с установленным свойством float , в данном случае со значением left ), которые размещаются в один ряд. При этом, назначая это имя класса для последнего в ряду блока (самого правого), я полностью исключаю ситуацию, когда он неплотно прилегает к границе контейнера, что в моем случае недопустимо. Даже если где-то в структуре CSS кода, в рамках правила с более специфичным (конкретным) селектором определены другие значения свойства margin-right для используемых блоков, то применение класса .last-block к крайним элементам позволит обнулить их. При этом мы не используем никаких дополнительных составляющих селектора, конкретизирующих его, что упрощает представление кода.

Подсчет значения CSS специфичности.

Рассматривая предыдущий пример, мы с вами выяснили, что наша первая попытка определения цвета и жирности шрифта для элемента списка провалилась из-за того, что мы использовали селектор лишь с одним именем класса, который имеет меньшее значение CSS специфичности и был переопределен селектором, выбирающим неупорядоченный список по его идентификатору ID, который имеет большее значение специфичности. Ключевыми значениями в данном случае являются имена классов (class) и идентификаторы элементов (ID). Очень важно знать, что CSS стандарты предусматривают существенные различия в весовых значениях специфичности для селекторов классов class и идентификаторов ID. Селекторы, использующие идентификаторы элементов, имеют безупречное преимущество над теми, в которых применяются лишь имена классов. При любом количестве имен классов в селекторе, он будет переопределен другим селектором, имеющим в своем составе один идентификатор элемента.

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

  • Если в теге элемента предусмотрен атрибут style , то все определенные в его рамках свойства имеют максимальный приоритет (значение специфичности в этом случае получает высший разряд – 1,0,0,0 ).
  • Для каждого идентификатора элемента, используемого в рамках селектора прибавляется единица в соответствующий разряд специфичности – 0,1,0,0 .
  • Каждое имя класса, а также псевдокласса или селектор атрибута ( * element[attribute] ), присутствующий в селекторе правила добавляет единицу в следующий разряд специфичности – 0,0,1,0 .
  • И последний, самый младший разряд, получает по единице за каждое, присутствующее в селекторе имя элемента – 0,0,0,1 .

Вы можете избавиться от запятых и преобразовать значения CSS специфичности в более привычную для вас форму представления значений – обычные числа: 1,0,0,0 можно представить как 1000 , что значительно больше значения 0,1,0,0 или 100 . Используемые в этом случае запятые предназначены для четкого разделения значений различных разрядов специфичности. К примеру, если в CSS селекторе используется 13 имен классов, псевдоклассов и/или селекторов атрибутов (что маловероятно), то значение специфичности в этом случае может принять вид 0,1,13,4 , что невозможно представить в десятичном виде.

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *