--- title: Каскад и наследование slug: Learn/CSS/Building_blocks/Cascade_and_inheritance tags: - CSS - Каскад - Наследование - Начинающий - Обучение - Порядок следования - Правила - Специфичность translation_of: Learn/CSS/Building_blocks/Cascade_and_inheritance ---
Цель этого урока — углубить ваше понимание некоторых основополагающих концепций CSS — каскадов, спецификаций и наследования, — которые контролируют то, как CSS применяется к HTML и как разрешаются конфликты.
Хотя изучение этого урока может показаться менее актуальным и немного более академичным, чем некоторые другие части курса, понимание этих вещей спасёт вас от головной боли в дальнейшем! Мы рекомендуем вам внимательно изучить этот раздел и убедиться, что вы понимаете концепции, перед тем, как двигаться дальше.
Необходимые условия: | Базовая компьютерная грамотность, Установка базового ПО, базовые знания работы с файлами, основы HTML (Введение в HTML), и общее представление о том, как работает CSS (Введение в CSS.) |
---|---|
Цель: | Изучить понятие о каскаде и специфичности, и как работает наследование CSS. |
CSS (Cascading Style Sheets) означает Каскадные Таблицы Стилей и первое слово "каскадные" является невероятно важным для понимания: то, как ведёт себя каскад — ключевой момент в понимании CSS.
В какой-то момент, работая над проектом, вы обнаружите, что CSS, который, по-вашему, должен быть применён к элементу, не работает. Обычно проблема заключается в том, что вы создали два правила, которые могут потенциально применяться к одному и тому же элементу. Каскад и тесно связанная концепция специфичности — это механизмы, которые контролируют, какое именно правило применяется, когда имеется такой конфликт. Стиль вашего элемента может определять не то правило, на которое вы рассчитывали, поэтому вам необходимо понимать, как работают эти механизмы.
Также значимой является концепция наследования, которая заключается в том, что некоторые свойства CSS наследуют по умолчанию значения, установленные для родительского элемента текущего элемента, а некоторые не наследуют. Это также может стать причиной поведения, которое вы, возможно, не ожидаете.
Давайте начнём с краткого обзора ключевых моментов, которых мы касаемся, далее рассмотрим каждый из них по очереди и посмотрим, как они взаимодействуют друг с другом и с вашим CSS. Это может показаться набором сложных для понимания понятий. Однако, когда вы получите больше опыта в написании CSS, для вас станет более очевидным то, как это работает.
Каскад таблицы стилей, если говорить упрощённо, означает, что порядок следования правил в CSS имеет значение; когда применимы два правила, имеющие одинаковую специфичность, используется то, которое идёт в CSS последним.
В приведённом ниже примере у нас есть два правила, которые могут применяться к h1. В результате h1 окрасится синим цветом — эти правила имеют идентичный селектор и, следовательно, одинаковую специфичность, поэтому побеждает последний в порядке следования.
{{EmbedGHLiveSample("css-examples/learn/cascade/cascade-simple.html", '100%', 400)}}
Специфичность определяет, как браузер решает, какое именно правило применяется в случае, когда несколько правил имеют разные селекторы, но, тем не менее, могут быть применены к одному и тому же элементу. Различные типы селекторов ( селекторы элементов h1{...}
, селекторы классов, селекторы идентификаторов и т.д ) имеют разной степени влияние на элементы страницы. Чем более общее влияние оказывает селектор на элементы страницы тем меньше его специфичность, конкретность. По существу, это мера того, насколько специфическим будет отбор по селектору:
h1
) менее специфичен — он выберет все элементы этого типа на странице — поэтому получит меньше баллов.Селектор класса более специфичен — он выберет только те элементы на странице, которые имеют конкретное значение атрибута class
— поэтому получит больше баллов, селектор класса применится после селектора элемента и поэтому перекроет его стили.
Например. Как указано ниже, у нас опять есть два правила, которые могут применяться к h1
. h1
в результате будет окрашен красным цветом — селектор класса даёт своему правилу более высокую специфичность, поэтому он будет применён, несмотря на то, что правило для селектора элемента расположено ниже в таблице стилей.
{{EmbedGHLiveSample("css-examples/learn/cascade/specificity-simple.html", '100%', 500)}}
Позже мы объясним, как сделать оценку специфичности, и прочие детали.
Наследование также надо понимать в этом контексте — некоторые значения свойства CSS, установленные для родительских элементов наследуются их дочерними элементами, а некоторые нет.
Например, если вы установили значение color
и font-family
для элемента, то каждый элемент внутри него также будет иметь этот цвет и шрифт, если только вы не применили к ним напрямую стиль с другим цветом и шрифтом.
{{EmbedGHLiveSample("css-examples/learn/cascade/inheritance-simple.html", '100%', 550)}}
Некоторые свойства не наследуются — например, если вы установили для элемента {{cssxref("width")}} равным 50%, все его дочерние элементы не получат ширину в 50% от ширины своего родительского элемента. Если бы это было так, CSS было бы чрезвычайно трудно использовать!
Примечание: На страницах справочника CSS свойств вы можете найти окно технической информации, обычно в конце раздела спецификации, в котором перечислены некоторые технические данные об этом свойстве, в том числе наследуется оно или нет. Например, здесь: color property Specifications section.
Эти три концепции вместе определяют, какая CSS применяется и к какому элементу; в следующих разделах мы увидим, как они взаимодействуют. Это может показаться сложным, но вы начнёте лучше понимать их по мере приобретения опыта работы с CSS, и вы всегда можете обратиться к справочной информации, если что-то забыли. Даже опытные разработчики не помнят всех деталей!
Видео ниже показывает, как вы можете использовать Firefox DevTools для проверки каскада стилей, спецификации, и т.д. на странице:
{{EmbedYouTube("Sp9ZfSvpf7A")}}
Итак, наследование. В примере ниже мы имеем {{HTMLElement("ul")}} с двумя уровнями неупорядоченных списков, вложенных в него. Мы установили для внешнего <ul>
стиль границы, внутренние отступы и цвет шрифта.
Цвет шрифта применён к прямому потомку, но также и к непрямому потомку — к прямому потомку <li>
и к элементам внутри первого вложенного списка. Далее мы добавили класс special
ко второму вложенному списку и применили к нему другой цвет шрифта. Теперь это свойство наследуется всеми его потомками.
{{EmbedGHLiveSample("css-examples/learn/cascade/inheritance.html", '100%', 700)}}
Такие свойства, как ширина (как в примере выше), внутренние и внешние отступы и стиль границы не наследуются. Если бы потомки нашего списка наследовали бы границу, то каждый отдельный список и каждая позиция в списке получили бы такую же границу — вряд ли мы хотели бы получить такой эффект!
Какие свойства наследуются по умолчанию, а какие нет, чаще всего определяется здравым смыслом.
CSS предоставляет четыре специальных универсальных значения свойства для контроля наследования. Каждое свойство CSS принимает эти значения.
inherit
, иначе оно действует как initial
.Примечание: Существует также более новое значение {{cssxref("revert")}}, которое имеет ограниченную поддержку браузерами.
Примечание: Смотрите {{SectionOnPage("/ru-RU/docs/Web/CSS/Cascade", "Origin of CSS declarations")}} для более подробной информации о каждом из них, и о том, как они работают.
Можно посмотреть список ссылок и изучить, как работают универсальные значения. Пример, следующий ниже, позволяет вам поиграть с CSS и увидеть, что происходит, когда вы вносите изменения. Подобные эксперименты с кодом — лучший способ освоить HTML и CSS.
Например:
my-class-1
. Таким образом, цвет для следующего вложенного элемента a
устанавливается по наследству. Как изменится цвет, если это правило будет удалено?a
имеют именно такой цвет? Если нет, перечитайте описание значений, представленное выше.<a>
— например: a { color: red; }
?{{EmbedGHLiveSample("css-examples/learn/cascade/keywords.html", '100%', 700)}}
Стенографическое свойство CSS all
можно использовать для того, чтобы присвоить одно из значений наследования к (почти) всем свойствам одновременно. Это одно из четырёх значений (inherit
, initial
, unset
, или revert
). Это удобный способ для отмены изменений, внесённых в стили, для того, чтобы вы могли вернуться к стартовой точке перед внесением новых изменений.
В примере ниже имеются два блока <blockquote>
. Первый имеет стиль, который применён к самому элементу blockquote
, второй имеет класс fix-this
, который устанавливает значение all
в unset
.
{{EmbedGHLiveSample("css-examples/learn/cascade/all.html", '100%', 700)}}
Попробуйте установить для all
ещё одно из доступных значений и исследуйте, в чём заключается разница.
Теперь мы понимаем, почему параграф, следующий по глубине в структуре HTML документа, имеет тот же цвет, что CSS применяет к body, а вводные уроки дали понимание того, как изменить применение CSS к чему-либо в любой точке документа — или назначить CSS элементу, или создать класс. Теперь рассмотрим подробнее то, как каскад определяет выбор CSS правил, применяемых в случае влияния на стиль элемента нескольких объектов.
Вот три фактора, перечисленные в порядке возрастания важности. Следующий отменяет предыдущий.
Мы внимательно изучим их, чтобы увидеть, как именно браузеры определяют, какой CSS следует применить.
Мы уже видели, какое значение для каскада имеет порядок следования. Если у вас несколько правил, которые имеют одинаковую важность, то побеждает правило, которое идёт последним в CSS. Другими словами, правила, более близкие к самому элементу, переписывают более ранние, пока последнее не победит, оно и стилизует элемент.
Понимая, что порядок следования правил имеет значение, в какой-то момент вы окажетесь в ситуации, когда вы знаете, что правило появляется позже в таблице стилей, но применяется более раннее, конфликтующее правило. Это связано с тем, что более раннее правило имеет более высокую специфичность — оно более специфично и поэтому выбирается браузером как правило, которое должно стилизовать элемент.
Как мы видели ранее в этом уроке, селектор класса имеет больший вес, чем селектор элемента, поэтому свойства, определённые в классе, будут переопределять свойства, применённые непосредственно к элементу.
Здесь следует отметить, что, хотя мы думаем о селекторах и правилах, применяемых к объекту, который они выбирают, переписывается не всё правило, а только свойства, которые являются одинаковыми.
Такое поведение помогает избежать повторения в вашем CSS. Обычной практикой является определение общих стилей для базовых элементов, а затем создание классов для тех, которые отличаются. Например, в таблице стилей ниже мы определяем общие стили для заголовков второго уровня, а затем создаём несколько классов, которые изменяют только некоторые свойства и значения. Определённые вначале значения применяются ко всем заголовкам, затем к заголовкам с классами применяются более конкретные значения.
{{EmbedGHLiveSample("css-examples/learn/cascade/mixing-rules.html", '100%', 700)}}
Давайте теперь посмотрим, как браузер будет вычислять специфичность. Мы уже знаем, что селектор элемента имеет низкую специфичность и может быть перезаписан классом. По существу, значение в баллах присуждается различным типам селекторов, и их сложение даёт вам вес этого конкретного селектора, который затем может быть оценён в сравнении с другими потенциальными соперниками.
Степень специфичности, которой обладает селектор, измеряется с использованием четырёх различных значений (или компонентов), которые можно представить как тысячи, сотни, десятки и единицы — четыре однозначные цифры в четырёх столбцах:
Примечание: Универсальный селектор (*), комбинаторы (+, >, ~, '') и псевдокласс отрицания (:not) не влияют на специфичность.
Следующая таблица показывает несколько несвязанных примеров, которые помогут вам разобраться. Посмотрите их все и убедитесь, что вы понимаете, почему они обладают той специфичностью, которую мы им дали. Мы ещё не рассмотрели селекторы детально, но вы можете найти подробную информацию о каждом селекторе в справочнике селекторов MDN.
Селектор | Тысячи | Сотни | Десятки | Единицы | Специфичность |
---|---|---|---|---|---|
h1 |
0 | 0 | 0 | 1 | 0001 |
h1 + p::first-letter |
0 | 0 | 0 | 3 | 0003 |
li > a[href*="en-US"] > .inline-warning |
0 | 0 | 2 | 2 | 0022 |
#identifier |
0 | 1 | 0 | 0 | 0100 |
Без селектора, с правилом внутри атрибута {{htmlattrxref("style")}} элемента. | 1 | 0 | 0 | 0 | 1000 |
Прежде чем мы продолжим, давайте посмотрим на пример в действии.
{{EmbedGHLiveSample("css-examples/learn/cascade/specificity-boxes.html", '100%', 700)}}
Так что здесь происходит? Прежде всего, нас интересуют только первые семь правил этого примера, и, как вы заметите, мы включили их значения специфичности в комментарий перед каждым правилом.
Примечание: Это был условный пример для более простого усвоения. В действительности, каждый тип селектора имеет собственный уровень специфичности, который не может быть замещён селекторами с более низким уровнем специфичности. Например, миллион соединённых селекторов класса не способны переписать правила одного селектора id.
Более правильный способ вычисления специфичности состоит в индивидуальной оценке уровней специфичности, начиная с наивысшего и продвигаясь к самому нижнему, когда это необходимо. Только когда оценки уровня специфичности совпадают, следует вычислять следующий нижний уровень; в противном случае, вы можете пренебречь селекторами с меньшим уровнем специфичности, поскольку они никогда не смогут преодолеть уровни более высокой специфичности.
Существует специальный элемент CSS, который вы можете использовать для отмены всех вышеперечисленных вычислений, однако вы должны быть очень осторожны с его использованием — !important
. Он используется, чтобы сделать конкретное свойство и значение самыми специфичными, таким образом переопределяя нормальные правила каскада.
Взгляните на этот пример, где у нас есть два абзаца, один из которых имеет ID.
{{EmbedGHLiveSample("css-examples/learn/cascade/important.html", '100%', 700)}}
Давайте пройдёмся по этому примеру, чтобы увидеть, что происходит — попробуйте удалить некоторые свойства, чтобы увидеть, что получится, если вам трудно понять:
better
, но у второго также есть {{htmlattrxref("id")}} с названием winning
. Поскольку ID имеют ещё более высокую специфичность, чем классы (у вас может быть только один элемент с каждым уникальным ID на странице, но много элементов с одним и тем же классом — селекторы ID очень специфичны, на что они и нацелены), красный цвет фона и однопиксельная чёрная граница должны быть применены ко 2-му элементу, причём первый элемент получает серый фоновый цвет и отсутствие границы, как определено классом.!important
во втором правиле — размещение которого после border: none
означает, что это объявление перевесит значение границы в предыдущем правиле, даже если ID имеет более высокую специфичность.Примечание: Единственный способ переопределить объявление !important
– это включить другое объявление !important
в правило с такой же специфичностью позже или в правило с более высокой специфичностью.
Полезно знать о существовании !important
, чтобы вы понимали, что это такое, когда встретите в чужом коде. Тем не менее, мы настоятельно рекомендуем вам никогда не использовать его, если в этом нет острой необходимости. !important
меняет обычный порядок работы каскада, поэтому он может серьёзно затруднить отладку проблем CSS, особенно в большой таблице стилей.
Одна из ситуаций, в которой вам, возможно, придётся это использовать, — это когда вы работаете с CMS, где вы не можете редактировать модули CSS ядра, и вы действительно хотите переопределить стиль, который нельзя переопределить другим способом. Но, вообще говоря, не стоит использовать этот элемент, если можно этого избежать.
Наконец, также полезно отметить, что важность объявления CSS зависит от того, в какой таблице стилей оно указано — у пользователя есть возможность установить индивидуальные таблицы стилей для переопределения стилей разработчика, например, пользователь может иметь проблемы со зрением и захочет установить размер шрифта на всех посещаемых им веб-страницах в два раза больше нормального размера, чтобы облегчить чтение.
Конфликтующие объявления будут применяться в следующем порядке, с учётом замены более ранних более поздними:
Для таблиц стилей веб-разработчиков имеет смысл переопределить пользовательские таблицы стилей так, чтобы можно было сохранить запланированный дизайн, но иногда у пользователей есть веские причины для переопределения стилей веб-разработчика, как упомянуто выше — это может быть достигнуто с помощью использования !important
в их правилах.
Мы охватили много тем в этой статье. А вы смогли запомнить наиболее важную информацию? Можете пройти несколько дополнительных тестов для того чтобы убедиться в том, что вы усвоили эту информацию, прежде чем пойдёте дальше — смотрите Test your skills: the Cascade.
Если вы поняли большую часть этой статьи, отлично — вы начали знакомиться с фундаментальными механизмами CSS. Далее мы рассмотрим селекторы подробно.
Если вы не до конца поняли каскад, специфичность и наследование, не волнуйтесь! Это, безусловно, самая сложная вещь из тех, что мы до сих пор изучали в курсе, и даже профессиональные веб-разработчики иногда считают её коварной. Мы советуем вам вернуться к этой статье несколько раз в ходе изучения курса и продолжать обдумывать эту тему.
Обратитесь сюда, если вы столкнётесь со странными проблемами, когда стили применяются не так, как вы ожидаете. Это может быть проблемой специфичности.
{{NextMenu("Learn/CSS/Building_blocks/Selectors", "Learn/CSS/Building_blocks")}}