Звядзе каменяюцься значэння CSS, калі вы задаеце None: як працюе спадчына
Дазнайцеся, як прыгледчыкі выбіраюць, чы гуменніка спадчынаецца, чаму дзецяткі атрымоюць вырахаваную значэнне ад бацькі, і як методы inherit і initial даюць вам часткова кантроль.
Крыніцы: How Inheritance Works in CSS Internally at Algorithmic Level.
Вы задаеце color для обгорткі, і абзац усередине становіцца чырвоным, хоць жадныя правілы гэта не пазначалі. Таму ж адступы, якія вы задаеце для той самай обгорткі, застаюцца на своім месцы. Оба гэтыя явышчыны вынікаюць з наследавання ў CSS — процесу, калі задаецца значэнне, калі элемент не мае свайго сопанскага. У гэтым кяліку пояснюецца, якія атрыбуты наследуюцься, што самэе перадаецца далей (атаварда ўсіх здивуе, калі йдзе пра вялічыны у відсотках), як ключавыя слова inherit і initial змінююць стандартныя значэння, і як наследаванне впісваецца ў іншыя етапы, якія ператвараюць стайл-шіт на фінальныя значэння.
Значэнне, якое ніхто не задаў
Пачніце з правіла для элемента-родзіча:
.parent {
color: red;
}
і маркапу, дзе абзац знаходзіцца ўсередине гэтага родзіча:
<div class="parent">
<p>Hello World</p>
</div>
Няма ніякіх правіл, які бы задавалі color для элемента <p>, пры тым як тэкст выводзіцца чырвоным. Калі браузер дасягае этай часткі, ён вже рашыў спорныя заявлення праз каскадную працэю і обрабатав ўсія ўсунутыя значэння. Заставало толькі вырашыць, для кожнай властывасці кожного элемента, чы гэта значэння павінна якісць з сабеўных заявленняў элемента, чы то з якога-небудзь вышэй у іерархіі. Спадчына ёсць механізам, які дапамагае прымусіць такое рашэнне.
Калія значэння пераходзяць па іерархіі
Спадчына дазволяе певным значэнням властывасцяў пераходзіць ад элемента-родкі да яго дзецей, а з таму і да ўсіх іхніх дзецей:
Parent
↓
Child
↓
Grandchild
Не кожная властывасць берае участка. Властывасці, якія описваюць тэкст, ўсунуліся ў категорыю класычных спадчынных властывасцяў, такіх як:
font-family
font-size
color
Гэтая прычына, чаму рэдкая патрабуецца павтараць тыпаграфію для кожнага элемента. У замяну таго, каб задаць адны і той жа колер для body і пасля зноў для кожнага типу дзецячых элементаў:
body {
color: #333;
}
h1 {
color: #333;
}
p {
color: #333;
}
li {
color: #333;
}
магчыма задаць яго адназначна, у верхняй часты дрэва документа, і прабачыць спадчынае, каб ён перайшоў да інших элементаў. Рэзультатам яе є менш CSS і адна толькі точка, дзе можна зменіць параметры, калі зменяецца дизайн. Заданне базовага шрыфту і калеру для body або :root — это ўпрабаванне гэтай ідэі ў практыцы.
Рашэнне, якое браузер прыме для кожной власці
Логіка становіцца ясней, калі паглядзець на ситуацыю, калі няма жадных заданняў для аднаго элемента. Для кожной власці браузер фактычна ставя два запытанні адно за іншым.
Паўза першая: ці є каскадаваныя значэння? Якшто якае-небудзь заявленне для гэтай атрыбута выграў каскадаванне для гэтага элемента, то выкарыстоўваецца тое значэнне, і спадчына ніколі не прабывае ў прыменэ.
Паўза другая, толькі якшо адказ быў «нет»: ці гэты атрыбут спадчываецца? Гэта цалкам залежыць ад самага атрыбута, калькі кожны з іх ў спецыфікацыі визначаецца як спадчываючы або неспадчываючы. Калькі прыкладаў спадчываючых атрыбутаў:
color → inherited
font-family → inherited
font-size → inherited
і калькі тых, якія не спадчываюцца:
margin → not inherited
padding → not inherited
Такое рашэнне ўсвядомленае. Уявіце сяродавішы свет, у яком margin спадчынаўся: адны маржа для якога-небудзь разделу быў бы копіюваны ў кожны параграф, спіс і гачок, якія знаходзяцца ўнутрь яго, і адстані меў бы нарадзіцца на кожным роўні. Атрыбуты, якія стосуюцца кантэйнераў, такія як margin, padding, border і width, практычна завжды ўсё тое, што хочаце задаць для кожнага элемента окрема, тады як атрыбуты, якія стосуюцься тексту, зазвычай хочаце, каб яны дзейнуваліся ў всій рэгіяні. Якщо атрыбут не спадчынаецца і у яго няма каскадаванага значэння, ён берае свае пачатковае значэння, стандартнае, заданае для таго атрыбута.
Якщо вы не впевнены ў конкрэтным атрыбуте, пункт „Spadczynaўся“ у яго дакументацыі даходзіць да адпаведнай вопыткі безпосередна.
Дзецяві элементы спадчынаюць вырахаванае значэння, а не текст, які вы напісалі
Эта ўсё самая важная деталь у всім процесе, і яна стоіць за вядомым сюрпрызам. Падазраўцем, што адначасова задае розмер шрыфту і процэнтавы высоту лініі:
.parent {
font-size: 20px;
line-height: 150%;
}
а дзеціны элементы перакрываюць толькі розмер шрыфту:
.child {
font-size: 25px;
}
Якую ж высоту лініі будзе мяць дзеціны элемент? Інтуўытыўна можна запэўніцца, што дзеціны элементы отрымаюць сам працэнт:
150%
а пасля перакладзяць яго ў значэнне, адпаведнае своему, большаму розмеру шрыфту:
150% of 25px
Але так не працюе. Элемент успадковуе вычысленая значэння свайго адпаведнага элемента-родзіча, а не значэння, якое было заданае. Для line-height працэнт перакладзіцца ў дужэўную велічыну ў момент вычыслення значэння. У родзіча расчыт выглядае так:
150% of 20px = 30px
такім чынам, вычысленая высота лініі у родзіча є:
30px
Гэта абсалютная дыяўжына і ёст канкрэтны значэнне, яке пераходзіць да наступных элементаў. Дзеціны элементы, незважаючы на большы шрыфт, успадковуюць высоту лініі:
30px
а не:
150% of 25px
Практычны наследкі — лініі выглядаюць стиснутымі, калі наступны элемент выкарыстоўвае большы шрыфт, чым элемент, дзе была задана відсотковая ціннась. То ж самае адбываецца з значэннямі em для line-height, каліколькі яны таксама перакладаюцца у дыяўжыны пры успадкуванні. Самэ гэтая прычына, чаму рэкомендуецца вжываць высоты лініі без еўраноў, напрыклад line-height: 1.5: простая цыфра ёсць самае вычысленая значэнне, таму кожны наступны элемент умножае яе на свой сябеўшы шрыфт у размере, замест таго каб успадковаць фіксаваную дыяўжыну.
Атрыбуты, якія не успадковуюцься, вяртаюцца да свайго пачатковага значэння
Тепер возьмім атрыбут з іншай групы:
padding
Паддінг не спадчынаецца. Таму калі абяцель заявляе:
.parent {
padding: 20px;
}
дзецін не прыме це таямніча:
padding: 20px;
У замест на гэта, без каскадавання значэння і без спадчынаў, паддінг дзеціна вжывае пачатковае значэнне атрыбута, якое для паддінга ёсць:
0px
Гэта застаецца такім, якшо толькі іншая правіла не зададуць дзеціну іншы паддінг. Знаўленне пра тое, да каторага класу належыць атрыбут, дапамагае заэканоміць час пад час адлучэння бяга: якшо значэнне, здаецца, „трапляеся“ у дзецінах, то гэта спадчыны атрыбут; якшо ён, здаецца, „зникае“ у дзецінах, то гэта неспадчыны атрыбут. Інструменты разработчика прыгледу дапамагаюць у гэтым, таму што панель Computed можа паказаць спадчыны значэнняя разам з іх абяцелью.
Змусэнне спадчынаў за дапамою inherit
Можна зменіць стандартную працэю будзь-якай атрыбутаў. Ключавая слова inherit паведамляе браузеру прыняць значэнне родкі, нават для атрыбутаў, якія зазвычай не спадчыцуюць:
.child {
padding: inherit;
}
За дапамою гэтага правіла заполненне (padding) дзецявог элемента падабяжыцца да вырачанага заполнення родкі. Гэта корыстна, калі хочаце, каб аднос межаў родкі і дзецявог элемента быў ясны, напрыклад, калі хочаце, каб вярстак-элемент перыядзічваў колер або расстоянне межы свайго контейнера, або калі хочаце прымусіць элементы формы, якія зазвычай не спадчыцуюць шрыфты з стандартных таблиц стылю браузера, выкарыстоўваць шрыфты асупрачзіяго за дапамою font: inherit.
Это дае вам два разныя спосабу адпрыемства значэння з роднікавага элемента. Аўтаматычна спадчына прыменяецца толькі да спадчыных атрыбутаў і толькі тады, калі няма каскадавага значэння. Явная спадчына за дапамою inherit сама ёсць заявай, таму яна перамагае каскадавое значэння, як і будзь-яе інша значэнне, і прыменяецца да будзь-каго атрыбута.
Скасаванне за дапамою initial
Адпаведная ключавая слова ёсць:
initial
Прыменяючы яе да атрыбута, ён скасоўвае гэты атрыбут і вяртае яго да пачатковага значэння, заданага спецыфікацыяй:
.child {
color: initial;
}
Згадайце, што «initial» абазуецца на стандартных значэннях спефікацыі, а не на стандартных шаблонах стылю браузера чыраго значэнні, якое элемент мог бы успадкуваць інакш. Для color пачатковым значэннем ёсць кольора тексту системы (зазвычай чорны), таму color: initial не вярнае кольора абяцейкі; ён выключае элемент з яе. Для display пачатковым значэннем ёсць inline, таму display: initial для div ператварае яго на элемент урэжанага формата, а не зноў на блакітны.
Якщо парагональна рассматраць, гэтыя два ключавыя словы выканаюць працу, протыпадную:
inherit → use the parent's value
initial → reset to the property's initial value
Ўныя вядомасці даюць вам чыстае кантролле над тым, як вядомасці пераходзяць через дрэво. CSS таксама прымеўляе unset (які паводзіцца як inherit для спадчыных атрыбутаў і як initial для іншых) і revert (які вяртае стандартны шаблон дзеўайса), пры чым аба звычайна ўжоць карысныя для скасывання настроек компонентаў, чым initial.
Складанне цэлага картыну
Корыстна ўважаць спадчынае разам з практыкамі, якія выкананы ў яе падчас. Калі калькі правіла нацэленыя на адны і той жа элемент, дзеўайс пачынае з каскадавання, яке пораўнюе заявы ў такой спраўе:
Importance
↓
Specificity
↓
Source Order
Пераможцам являецца каскадаваная вядомасць. Потым гэтая вядомасць пераходзіць чераз ряд працэсавых стадзій, пакуль не стане чым-то, што можа быць выкарыстана для разметкі і адрасавання:
Declared Value
↓
Cascaded Value
↓
Specified Value
↓
Computed Value
↓
Used Value
↓
Actual Value
Калі не існуе каскадаванага значэння, спадчына замест таго задае вхідны даннэ для гэтай лінійкі:
No Cascaded Value
↓
Can Property Be Inherited?
↓
Yes
↓
Parent's Computed Value
↓
Child
Строга гаворачы, спецыфікацыя размешчае спадчыну там, дзе выканалікаўця вызначанага значэння: вызначанае значэнне ёст каскадаванае, якщо такое існуе; іншым чыным – вырахаванае значэнне абяцейкі для спадзячых атрыбутаў; яшчэ іншым чыным – пачатковае значэнне. Адтуда продолжаюцца звычныя этапы вырахавання, выкарыстоўвання і фактычнага значэння. Таму спрасаваныяе відображэнне этапа обрабоцкі CSS выглядае так:
CSS
↓
Cascade
↓
┌─────────────┴─────────────┐
↓ ↓
Importance Specificity
↓
Source Order
↓
Cascaded Value
↓
Value Processing
↓
Computed / Used / Actual
↓
Inheritance
↓
CSSOM
У тым дыяграме вертыкальны рэйхтар трэба спрыяць як групаванне канцэпцый, а не як строгі часовы лінію, калі ўжо спадчына задае вказаную значэнне, а не працюе пасля вычысленых значэнняў. Галоўная ідея застаецца тая ж: між шаблонам стылю і экранам відбываецца гораздаўна больш, чым проста „я напісаў правілу, а браузер яго застосаваў“.
З шаблону стылю да пікселей
Якщо адступіць на большую вялічыну, то тут паказана цэлая дорага з розглядам стадзій CSS:
HTML
↓
DOM
↓
CSS
↓
Cascade
↓
Specificity
↓
Value Processing
↓
Inheritance
↓
CSSOM
↓
DOM + CSSOM
↓
Render Tree
↓
Layout
↓
Paint
↓
Pixels
Якщо взяць у расчыт тую ланцюговую працэсу, нават маленькае правіле несе ў сабе вельмі большую колькасць неявнае працы:
.title {
font-size: 2rem;
color: blue;
}
Перш чым ўсё будзе накрэслана, браузер должен устанавіць:
- каторыя заявы паслужаюць для кожнага элемента;
- каторая з іх перамагае, калі ўсё суперчыць адзіна другаму;
- насколькі конкрэтныя ўсе супернічаючыя селектары;
2rem паводзіцца да пікселей);Толькі пасля всьго гэтага стораніца пераходзіць да форматавання і атрыбутавання.
CSS як система, а не як спіс правіл
Большая частка плутання ў зв’язку з CSS зніквае, калі перестаём супрацоўваць з яйным як з адзеленымі правіламі і пачынаем супрацоўваць з яйным як з адной системай з чыста визначанымі задачамі:
- Спецыфічнасць адказвае на пытанне, чаму адна заява перамагае іншую.
- Порядак выкарстання раз’яснюе суперечкі, калі спецыфічнасць аднакова.
- Обробка значэнняў ператварае тое, што вы напісалі, у значэнні, якія можа выкарыстоўваць браузер.
Разам яны ператвараюць стаяльнік стылю на цэлы набор фінальных значэнняў, якія вплываюць на макетаванне і атрыбуты візуальнага выгляду. Нават такая короткая декларацыя:
width: 66%;
праходзіць чераз усе яны. Браузер выбірае, якая правіла прыменяецца, обрабоўвае процэнт, асоюе яго з блокам, які ўтримвае елемент, і вылучае фінальную шыроў, усё гэта ўжо да таго, як з’явіцца хоць адзін піксель.
Пасля гэтага застаецца адзін дапаможны пытанне: дзе самэўсёды будзе распакаваны кожны элемент. Шыроў, высота, нормальны прайход дадзенняў, пазыціонаванне і модэль касеты належаюць да візуальнага модэля форматавання, наступнай стадзіі процесу, якая берае гэтыя фінальныя значэнні і ператварае іх у макет.
Ключовыя выводы
- Значэнне атрыбута спачатку отрымаецца з каскаду; пасвараванне выкарыстоўвается толькі, калі не існуе прыменяючайся декларацыі.
color, font-*) або неспадчая (здарожна для элемента-коробкі: margin, padding). em пераходзяць як фіксаваныя дужынкі; лепш выкарыстоўваць line-height без елементаў выражэння. 0 для padding. inherit прымусвае спадчае перанесенне для будзь-якай атрыбутнай характерыстыкі; initial вяртае значэнне за зразкам спецыфікацыі, а не значэнне бацькіх элементаў; unset і revert часта ўжоць кращыя засобы для скасавання настройкаў.