[{"data":1,"prerenderedAt":14930},["ShallowReactive",2],{"\u002Ftutorials\u002Fcss":3,"tutorials-search\u002Ftutorials\u002Fcss":14391},{"id":4,"title":5,"body":6,"category":377,"cover":14381,"date":14382,"description":14383,"extension":14384,"meta":14385,"navigation":85,"path":14386,"seo":14387,"sitemap":14388,"stem":14389,"__hash__":14390},"tutorials\u002Ftutorials\u002Fcss.md","CSS 教程：从选择器到容器查询",{"type":7,"value":8,"toc":14170},"minimark",[9,14,23,28,218,303,309,312,315,358,365,369,373,433,453,458,461,480,495,524,528,531,580,591,594,680,694,698,702,780,784,788,873,884,887,983,990,993,1084,1087,1126,1130,1134,1200,1204,1207,1248,1252,1262,1276,1279,1282,1371,1374,1411,1444,1448,1478,1482,1485,1500,1630,1634,1685,1688,1779,1783,1808,1812,1832,1848,1851,1937,1944,1948,1951,1955,1966,1978,2032,2045,2076,2086,2089,2113,2121,2133,2136,2178,2182,2193,2216,2233,2240,2246,2327,2339,2342,2345,2380,2384,2406,2411,2415,2475,2485,2515,2520,2531,2541,2603,2624,2628,2657,2667,2670,2706,2715,2759,2772,2778,2781,2822,2825,2865,2868,2916,2927,2930,2973,2977,2982,2991,3015,3059,3086,3095,3104,3183,3196,3200,3388,3398,3406,3418,3529,3533,3541,3665,3685,3698,3704,3715,3833,3840,3849,3853,3894,3905,3915,3920,3932,3941,4038,4048,4060,4064,4143,4146,4261,4267,4279,4282,4361,4370,4374,4396,4403,4410,4449,4453,4464,4468,4472,4495,4520,4549,4576,4582,4619,4642,4653,4658,4661,4702,4707,4783,4801,4809,4818,4858,4866,4873,4888,4983,5007,5010,5143,5160,5164,5167,5172,5180,5229,5255,5272,5301,5305,5437,5448,5454,5458,5463,5477,5486,5498,5581,5602,5615,5618,5625,5663,5670,5674,5712,5726,5729,5822,5826,5838,5843,5850,5957,5981,5992,5998,6011,6158,6168,6174,6191,6194,6262,6281,6297,6310,6316,6337,6340,6512,6531,6535,6542,6546,6550,6557,6566,6569,6636,6643,6752,6758,6762,6864,6867,6941,6954,6958,6964,7073,7084,7091,7176,7184,7201,7283,7303,7318,7322,7325,7329,7333,7417,7424,7427,7451,7454,7480,7487,7600,7606,7613,7617,7710,7713,7752,7763,7773,7777,7830,7836,7894,7897,7900,8043,8049,8053,8129,8132,8156,8194,8204,8282,8288,8291,8351,8355,8358,8363,8371,8444,8447,8467,8478,8496,8503,8612,8627,8636,8642,8723,8729,8733,8892,8898,9043,9066,9088,9091,9117,9123,9134,9138,9146,9316,9329,9342,9350,9392,9398,9402,9435,9441,9459,9465,9561,9567,9578,9598,9602,9605,9651,9654,9663,9675,9678,9706,9710,9717,9721,9727,9768,9777,9783,9969,9976,10090,10112,10115,10119,10232,10236,10657,10663,10666,10707,10719,10723,10733,10737,10743,10787,10798,10811,10862,10871,10874,10915,10926,10932,11050,11053,11081,11091,11099,11165,11173,11297,11301,11311,11427,11430,11465,11472,11481,11485,11563,11569,11589,11597,11613,11617,11656,11663,11666,11689,11693,11703,11707,11711,11714,11774,11777,11959,11965,11971,11980,12038,12048,12054,12175,12185,12193,12262,12404,12414,12422,12464,12495,12504,12507,12536,12543,12547,12550,12611,12620,12627,12633,12692,12706,12722,12762,12828,12849,12852,12915,12918,12924,13011,13014,13018,13024,13109,13112,13133,13136,13287,13291,13378,13392,13395,13529,13536,13627,13630,13633,13740,13744,13747,13751,13755,13758,13872,13876,13880,13883,14011,14015,14131,14135,14164,14167],[10,11,13],"h2",{"id":12},"一css-是什么三种引入方式与层叠起点","一、CSS 是什么：三种引入方式与层叠起点",[15,16,17,18,22],"p",{},"HTML 决定「这是什么内容」，CSS 决定「它怎么呈现」。CSS 的全部机制都建立在一个前提上：",[19,20,21],"strong",{},"同一个元素的同一个属性可以被多条规则命中，最终只有一条赢","。理解这场裁决（层叠，cascade），后面所有「我明明写了却没生效」的问题都有了解法。",[24,25,27],"h3",{"id":26},"外链内联块与-import各自的代价","外链、内联块与 @import：各自的代价",[29,30,35],"pre",{"className":31,"code":32,"language":33,"meta":34,"style":34},"language-html shiki shiki-themes github-dark","\u003C!-- ① 外链样式表：正式项目的唯一正确做法 -->\n\u003Clink rel=\"stylesheet\" href=\"\u002Fcss\u002Fmain.css\">\n\n\u003C!-- ② 页面内 style 块：单页 demo、首屏关键 CSS -->\n\u003Cstyle> body { max-width: 700px; margin: 0 auto; } \u003C\u002Fstyle>\n\n\u003C!-- ③ @import：写在 CSS 文件顶部 -->\n\u003Cstyle> @import url(\"\u002Fcss\u002Freset.css\"); \u003C\u002Fstyle>\n\n\u003C!-- ④ 元素上的 style 属性：权重最高，只用于必须动态计算的值 -->\n\u003Cdiv style=\"width: 42%\">…\u003C\u002Fdiv>\n","html","",[36,37,38,47,80,87,93,145,150,156,184,189,195],"code",{"__ignoreMap":34},[39,40,43],"span",{"class":41,"line":42},"line",1,[39,44,46],{"class":45},"sAwPA","\u003C!-- ① 外链样式表：正式项目的唯一正确做法 -->\n",[39,48,50,54,58,62,65,69,72,74,77],{"class":41,"line":49},2,[39,51,53],{"class":52},"s95oV","\u003C",[39,55,57],{"class":56},"s4JwU","link",[39,59,61],{"class":60},"svObZ"," rel",[39,63,64],{"class":52},"=",[39,66,68],{"class":67},"sU2Wk","\"stylesheet\"",[39,70,71],{"class":60}," href",[39,73,64],{"class":52},[39,75,76],{"class":67},"\"\u002Fcss\u002Fmain.css\"",[39,78,79],{"class":52},">\n",[39,81,83],{"class":41,"line":82},3,[39,84,86],{"emptyLinePlaceholder":85},true,"\n",[39,88,90],{"class":41,"line":89},4,[39,91,92],{"class":45},"\u003C!-- ② 页面内 style 块：单页 demo、首屏关键 CSS -->\n",[39,94,96,98,101,104,107,110,114,117,120,124,127,130,132,135,138,141,143],{"class":41,"line":95},5,[39,97,53],{"class":52},[39,99,100],{"class":56},"style",[39,102,103],{"class":52},"> ",[39,105,106],{"class":56},"body",[39,108,109],{"class":52}," { ",[39,111,113],{"class":112},"sDLfK","max-width",[39,115,116],{"class":52},": ",[39,118,119],{"class":112},"700",[39,121,123],{"class":122},"snl16","px",[39,125,126],{"class":52},"; ",[39,128,129],{"class":112},"margin",[39,131,116],{"class":52},[39,133,134],{"class":112},"0",[39,136,137],{"class":112}," auto",[39,139,140],{"class":52},"; } \u003C\u002F",[39,142,100],{"class":56},[39,144,79],{"class":52},[39,146,148],{"class":41,"line":147},6,[39,149,86],{"emptyLinePlaceholder":85},[39,151,153],{"class":41,"line":152},7,[39,154,155],{"class":45},"\u003C!-- ③ @import：写在 CSS 文件顶部 -->\n",[39,157,159,161,163,165,168,171,174,177,180,182],{"class":41,"line":158},8,[39,160,53],{"class":52},[39,162,100],{"class":56},[39,164,103],{"class":52},[39,166,167],{"class":122},"@import",[39,169,170],{"class":112}," url",[39,172,173],{"class":52},"(",[39,175,176],{"class":67},"\"\u002Fcss\u002Freset.css\"",[39,178,179],{"class":52},"); \u003C\u002F",[39,181,100],{"class":56},[39,183,79],{"class":52},[39,185,187],{"class":41,"line":186},9,[39,188,86],{"emptyLinePlaceholder":85},[39,190,192],{"class":41,"line":191},10,[39,193,194],{"class":45},"\u003C!-- ④ 元素上的 style 属性：权重最高，只用于必须动态计算的值 -->\n",[39,196,198,200,203,206,208,211,214,216],{"class":41,"line":197},11,[39,199,53],{"class":52},[39,201,202],{"class":56},"div",[39,204,205],{"class":60}," style",[39,207,64],{"class":52},[39,209,210],{"class":67},"\"width: 42%\"",[39,212,213],{"class":52},">…\u003C\u002F",[39,215,202],{"class":56},[39,217,79],{"class":52},[219,220,221,237],"table",{},[222,223,224],"thead",{},[225,226,227,231,234],"tr",{},[228,229,230],"th",{},"方式",[228,232,233],{},"优点",[228,235,236],{},"代价",[238,239,240,258,272,289],"tbody",{},[225,241,242,248,255],{},[243,244,245,247],"td",{},[36,246,57],{}," 外链",[243,249,250,251,254],{},"多页共享、可长期缓存、与 HTML ",[19,252,253],{},"并行","下载",[243,256,257],{},"多一次请求",[225,259,260,266,269],{},[243,261,262,265],{},[36,263,264],{},"\u003Cstyle>"," 内联块",[243,267,268],{},"零请求，适合把首屏关键 CSS 直接嵌进 HTML",[243,270,271],{},"不随页面复用，改一次要动 HTML",[225,273,274,278,281],{},[243,275,276],{},[36,277,167],{},[243,279,280],{},"组织上像 include",[243,282,283,286,287],{},[19,284,285],{},"被引入的文件要等主 CSS 下载完才开始下载","（串行），首屏变慢；生产环境几乎总该换成 ",[36,288,57],{},[225,290,291,297,300],{},[243,292,293,296],{},[36,294,295],{},"style=\"\""," 属性",[243,298,299],{},"能被 JS 单点修改、权重最高",[243,301,302],{},"无法复用、写不了伪类、难以维护",[304,305],"demo-html",{"height":306,"src":307,"title":308},560,"\u002Ftutorials\u002Fcss\u002Fdemos\u002F01-three-ways.html","示例 01：三种引入方式与层叠起点",[24,310,311],{"id":311},"一条声明怎么胜出",[15,313,314],{},"浏览器对每个元素的每个属性只保留一条获胜声明，裁判顺序是：",[316,317,318,332,346,352],"ol",{},[319,320,321,324,325,328,329,331],"li",{},[19,322,323],{},"重要性与来源","：用户带 ",[36,326,327],{},"!important"," 的样式 > 作者带 ",[36,330,327],{}," 的 > 作者普通 > 用户普通 > 浏览器默认。",[319,333,334,341,342,345],{},[19,335,336,337,340],{},"层（",[36,338,339],{},"@layer","）","：未分层的声明，优先级",[19,343,344],{},"高于","所有分层的声明（第十六章）。",[319,347,348,351],{},[19,349,350],{},"权重（specificity）","：id \u002F class \u002F 元素三个数量级比较（第四章）。",[319,353,354,357],{},[19,355,356],{},"书写顺序","：前三步比不出结果时，写在后面的赢。",[15,359,360,361,364],{},"「后写的覆盖先写的」只在",[19,362,363],{},"权重相同","的前提下成立——这是新手最容易记错的一条。",[10,366,368],{"id":367},"二语法与书写规范","二、语法与书写规范",[24,370,372],{"id":371},"规则的结构选择器-声明块","规则的结构：选择器 + 声明块",[29,374,378],{"className":375,"code":376,"language":377,"meta":34,"style":34},"language-css shiki shiki-themes github-dark","\u002F*  选择器（命中谁）  *\u002F\nh1, .title {\n  color: #24292f;      \u002F* 声明 = 属性 + 冒号 + 值 + 分号 *\u002F\n  line-height: 1.3;\n}\n","css",[36,379,380,385,399,415,428],{"__ignoreMap":34},[39,381,382],{"class":41,"line":42},[39,383,384],{"class":45},"\u002F*  选择器（命中谁）  *\u002F\n",[39,386,387,390,393,396],{"class":41,"line":49},[39,388,389],{"class":56},"h1",[39,391,392],{"class":52},", ",[39,394,395],{"class":60},".title",[39,397,398],{"class":52}," {\n",[39,400,401,404,406,409,412],{"class":41,"line":82},[39,402,403],{"class":112},"  color",[39,405,116],{"class":52},[39,407,408],{"class":112},"#24292f",[39,410,411],{"class":52},";      ",[39,413,414],{"class":45},"\u002F* 声明 = 属性 + 冒号 + 值 + 分号 *\u002F\n",[39,416,417,420,422,425],{"class":41,"line":89},[39,418,419],{"class":112},"  line-height",[39,421,116],{"class":52},[39,423,424],{"class":112},"1.3",[39,426,427],{"class":52},";\n",[39,429,430],{"class":41,"line":95},[39,431,432],{"class":52},"}\n",[434,435,436,443,450],"ul",{},[319,437,438,439,442],{},"逗号是「或」：",[36,440,441],{},"h1, .title { }"," 等于两条规则合并。",[319,444,445,446,449],{},"最后一条的分号可以省略，但",[19,447,448],{},"别省","：追加声明、被压缩工具合并时会出错。",[319,451,452],{},"花括号内一条声明缺分号会吞掉下一条；少一个花括号，破坏面能扩到整段样式表。",[304,454],{"height":455,"src":456,"title":457},620,"\u002Ftutorials\u002Fcss\u002Fdemos\u002F02-syntax-conventions.html","示例 02：语法结构、简写与命名约定",[24,459,460],{"id":460},"注释与分组",[15,462,463,464,467,468,471,472,475,476,479],{},"CSS 只有 ",[36,465,466],{},"\u002F* … *\u002F"," 一种注释，",[36,469,470],{},"\u002F\u002F"," 是 Sass\u002FLess 的能力。错误恢复是",[19,473,474],{},"整块规则","级别的：一个选择器解析失败，浏览器会丢弃直到下一个 ",[36,477,478],{},"}"," 为止的全部内容，所以一个拼错的选择器影响的往往不止它自己。",[15,481,482,483,486,487,490,491,494],{},"声明简写有个必须知道的隐藏行为：",[19,484,485],{},"简写会把没提到的分量重置为初始值","。写了 ",[36,488,489],{},"background: red"," 之后再单写 ",[36,492,493],{},"background-position","，位置可能已经被前一条清掉了——这是「明明写了却不生效」的高频原因之一。",[29,496,498],{"className":375,"code":497,"language":377,"meta":34,"style":34},"margin: 10px 20px;               \u002F* 上下 10，左右 20（顺序：上 右 下 左，顺时针） *\u002F\nborder: 1px solid #d0d7de;       \u002F* 宽度 样式 颜色 *\u002F\nbackground: #f6f8fa url(a.png) no-repeat center \u002F cover;  \u002F* 一行写完多个分量 *\u002F\n",[36,499,500,508,516],{"__ignoreMap":34},[39,501,502,505],{"class":41,"line":42},[39,503,504],{"class":52},"margin: 10px 20px;               ",[39,506,507],{"class":45},"\u002F* 上下 10，左右 20（顺序：上 右 下 左，顺时针） *\u002F\n",[39,509,510,513],{"class":41,"line":49},[39,511,512],{"class":52},"border: 1px solid #d0d7de;       ",[39,514,515],{"class":45},"\u002F* 宽度 样式 颜色 *\u002F\n",[39,517,518,521],{"class":41,"line":82},[39,519,520],{"class":52},"background: #f6f8fa url(a.png) no-repeat center \u002F cover;  ",[39,522,523],{"class":45},"\u002F* 一行写完多个分量 *\u002F\n",[24,525,527],{"id":526},"命名约定bem-风格","命名约定：BEM 风格",[15,529,530],{},"本站所有组件用这一套：",[29,532,534],{"className":375,"code":533,"language":377,"meta":34,"style":34},".chip            { }  \u002F* 块：组件本体 *\u002F\n.chip__count     { }  \u002F* 元素：块内部的组成部分，双下划线 *\u002F\n.chip--primary   { }  \u002F* 修饰符：同一种东西的变体，双连字符 *\u002F\n.chip.is-disabled{ }  \u002F* 状态：由 JS 加上的类，配 is-\u002Fhas- 前缀 *\u002F\n",[36,535,536,547,558,569],{"__ignoreMap":34},[39,537,538,541,544],{"class":41,"line":42},[39,539,540],{"class":60},".chip",[39,542,543],{"class":52},"            { }  ",[39,545,546],{"class":45},"\u002F* 块：组件本体 *\u002F\n",[39,548,549,552,555],{"class":41,"line":49},[39,550,551],{"class":60},".chip__count",[39,553,554],{"class":52},"     { }  ",[39,556,557],{"class":45},"\u002F* 元素：块内部的组成部分，双下划线 *\u002F\n",[39,559,560,563,566],{"class":41,"line":82},[39,561,562],{"class":60},".chip--primary",[39,564,565],{"class":52},"   { }  ",[39,567,568],{"class":45},"\u002F* 修饰符：同一种东西的变体，双连字符 *\u002F\n",[39,570,571,574,577],{"class":41,"line":89},[39,572,573],{"class":60},".chip.is-disabled",[39,575,576],{"class":52},"{ }  ",[39,578,579],{"class":45},"\u002F* 状态：由 JS 加上的类，配 is-\u002Fhas- 前缀 *\u002F\n",[15,581,582,583,586,587,590],{},"BEM 不是标准，而是一种能防止选择器膨胀的命名纪律。三条收益：看类名就知道归属、每条规则能单独读懂、权重始终是「单个 class」因此永远低位、方便覆盖。命名带用途而不是带外观：",[36,584,585],{},"is-error"," 好于 ",[36,588,589],{},"red-text","。",[24,592,593],{"id":593},"常见语法错误与排查",[219,595,596,606],{},[222,597,598],{},[225,599,600,603],{},[228,601,602],{},"写法",[228,604,605],{},"后果",[238,607,608,619,630,641,654,665],{},[225,609,610,616],{},[243,611,612,615],{},[36,613,614],{},"colo: red","（属性拼错）",[243,617,618],{},"该声明被忽略，块内其余照常",[225,620,621,627],{},[243,622,623,626],{},[36,624,625],{},"color red;","（漏冒号）",[243,628,629],{},"该声明被忽略",[225,631,632,638],{},[243,633,634,637],{},[36,635,636],{},"margin: 10px 20px","（漏分号）",[243,639,640],{},"下一条声明被吞",[225,642,643,648],{},[243,644,645,646],{},"少一个 ",[36,647,478],{},[243,649,650,651,653],{},"直到下一个 ",[36,652,478],{}," 的整块内容失效",[225,655,656,662],{},[243,657,658,661],{},[36,659,660],{},"width: 100","（长度漏单位）",[243,663,664],{},"除 0 和单位无关关键字外，长度必须带单位",[225,666,667,677],{},[243,668,669,670,673,674],{},"中文全角分号 ",[36,671,672],{},"；","、全角冒号 ",[36,675,676],{},"：",[243,678,679],{},"中文输入法下的第一大坑，症状同上",[15,681,682,683,686,687,689,690,693],{},"排查只用 DevTools 的 Styles 面板：",[19,684,685],{},"被划掉的规则","说明被更高权重或 ",[36,688,327],{}," 压制（面板会标出是谁压的），",[19,691,692],{},"根本没出现的规则","说明没命中或整块解析失败。",[10,695,697],{"id":696},"三选择器基础","三、选择器基础",[24,699,701],{"id":700},"类型classid-与通配","类型、class、id 与通配",[29,703,705],{"className":375,"code":704,"language":377,"meta":34,"style":34},"p { }        \u002F* 类型选择器：命中所有 p，权重 0,0,1 *\u002F\n.card { }    \u002F* class：权重 0,1,0 —— 日常主力 *\u002F\n#header { }  \u002F* id：权重 1,0,0 —— 别拿它写样式（第四章） *\u002F\n* { }        \u002F* 通配：权重 0，唯一正当用途是重置 *\u002F\n*, *::before, *::after { box-sizing: border-box; }\n",[36,706,707,717,728,739,749],{"__ignoreMap":34},[39,708,709,711,714],{"class":41,"line":42},[39,710,15],{"class":56},[39,712,713],{"class":52}," { }        ",[39,715,716],{"class":45},"\u002F* 类型选择器：命中所有 p，权重 0,0,1 *\u002F\n",[39,718,719,722,725],{"class":41,"line":49},[39,720,721],{"class":60},".card",[39,723,724],{"class":52}," { }    ",[39,726,727],{"class":45},"\u002F* class：权重 0,1,0 —— 日常主力 *\u002F\n",[39,729,730,733,736],{"class":41,"line":82},[39,731,732],{"class":60},"#header",[39,734,735],{"class":52}," { }  ",[39,737,738],{"class":45},"\u002F* id：权重 1,0,0 —— 别拿它写样式（第四章） *\u002F\n",[39,740,741,744,746],{"class":41,"line":89},[39,742,743],{"class":56},"*",[39,745,713],{"class":52},[39,747,748],{"class":45},"\u002F* 通配：权重 0，唯一正当用途是重置 *\u002F\n",[39,750,751,753,755,757,760,762,764,767,769,772,774,777],{"class":41,"line":95},[39,752,743],{"class":56},[39,754,392],{"class":52},[39,756,743],{"class":56},[39,758,759],{"class":60},"::before",[39,761,392],{"class":52},[39,763,743],{"class":56},[39,765,766],{"class":60},"::after",[39,768,109],{"class":52},[39,770,771],{"class":112},"box-sizing",[39,773,116],{"class":52},[39,775,776],{"class":112},"border-box",[39,778,779],{"class":52},"; }\n",[304,781],{"height":455,"src":782,"title":783},"\u002Ftutorials\u002Fcss\u002Fdemos\u002F03-selectors.html","示例 03：五组必会选择器",[24,785,787],{"id":786},"组合子空格-与","组合子：空格、>、+ 与 ~",[29,789,791],{"className":375,"code":790,"language":377,"meta":34,"style":34},".card p       { }   \u002F* 空格 = 后代，任意深度 *\u002F\n.card > p     { }   \u002F* > = 子代，只下一层 *\u002F\nh4 + h4       { }   \u002F* + = 紧邻兄弟，紧跟在后面的那一个 *\u002F\np ~ span      { }   \u002F* ~ = 后续兄弟，之后的所有同级 *\u002F\nA B C > D     { }   \u002F* 混用；从右往左读：D 是 C 的子，C 是 B 的后代 *\u002F\n",[36,792,793,806,821,837,853],{"__ignoreMap":34},[39,794,795,797,800,803],{"class":41,"line":42},[39,796,721],{"class":60},[39,798,799],{"class":56}," p",[39,801,802],{"class":52},"       { }   ",[39,804,805],{"class":45},"\u002F* 空格 = 后代，任意深度 *\u002F\n",[39,807,808,810,813,815,818],{"class":41,"line":49},[39,809,721],{"class":60},[39,811,812],{"class":122}," >",[39,814,799],{"class":56},[39,816,817],{"class":52},"     { }   ",[39,819,820],{"class":45},"\u002F* > = 子代，只下一层 *\u002F\n",[39,822,823,826,829,832,834],{"class":41,"line":82},[39,824,825],{"class":56},"h4",[39,827,828],{"class":122}," +",[39,830,831],{"class":56}," h4",[39,833,802],{"class":52},[39,835,836],{"class":45},"\u002F* + = 紧邻兄弟，紧跟在后面的那一个 *\u002F\n",[39,838,839,841,844,847,850],{"class":41,"line":89},[39,840,15],{"class":56},[39,842,843],{"class":122}," ~",[39,845,846],{"class":56}," span",[39,848,849],{"class":52},"      { }   ",[39,851,852],{"class":45},"\u002F* ~ = 后续兄弟，之后的所有同级 *\u002F\n",[39,854,855,858,861,864,867,870],{"class":41,"line":95},[39,856,857],{"class":56},"A",[39,859,860],{"class":56}," B",[39,862,863],{"class":52}," C ",[39,865,866],{"class":122},">",[39,868,869],{"class":52}," D     { }   ",[39,871,872],{"class":45},"\u002F* 混用；从右往左读：D 是 C 的子，C 是 B 的后代 *\u002F\n",[15,874,875,876,879,880,883],{},"选择器",[19,877,878],{},"从右往左","匹配，所以最右侧的「关键选择器」越具体越快。长链 ",[36,881,882],{},"body > div .box ul li a"," 既慢又脆，DOM 一调整就断——这是重构时最先该删的东西。",[24,885,886],{"id":886},"属性选择器全家福",[219,888,889,899],{},[222,890,891],{},[225,892,893,896],{},[228,894,895],{},"语法",[228,897,898],{},"含义",[238,900,901,911,925,935,945,955,965],{},[225,902,903,908],{},[243,904,905],{},[36,906,907],{},"[href]",[243,909,910],{},"存在该属性",[225,912,913,922],{},[243,914,915,918,919],{},[36,916,917],{},"[href=\"x\"]"," \u002F ",[36,920,921],{},"[href=\"x\" i]",[243,923,924],{},"精确等于 \u002F 忽略大小写",[225,926,927,932],{},[243,928,929],{},[36,930,931],{},"[href^=\"https\"]",[243,933,934],{},"前缀",[225,936,937,942],{},[243,938,939],{},[36,940,941],{},"[href$=\".pdf\"]",[243,943,944],{},"后缀",[225,946,947,952],{},[243,948,949],{},[36,950,951],{},"[href*=\"docs\"]",[243,953,954],{},"包含",[225,956,957,962],{},[243,958,959],{},[36,960,961],{},"[rel~=\"noopener\"]",[243,963,964],{},"空格分隔的值列表中含某项",[225,966,967,972],{},[243,968,969],{},[36,970,971],{},"[class|=\"btn\"]",[243,973,974,975,978,979,982],{},"等于 ",[36,976,977],{},"btn"," 或以 ",[36,980,981],{},"btn-"," 开头",[15,984,985,986,989],{},"它们配合 ",[36,987,988],{},"data-*","（HTML 教程第十五章）能实现「数据驱动样式」：JS 只改属性，样式跟着变。",[24,991,992],{"id":992},"结构伪类",[29,994,996],{"className":375,"code":995,"language":377,"meta":34,"style":34},":first-child \u002F :last-child          \u002F* 首尾 *\u002F\n:nth-child(2n)  \u002F  :nth-child(even) \u002F* 偶数；也可 (2n+1)、odd、from-end(2) *\u002F\n:nth-child(-n+3)                    \u002F* 前 3 个 *\u002F\n:only-child                         \u002F* 独子 *\u002F\n:empty                              \u002F* 无子节点也无文本（空白符也算文本，格式化容易破坏它） *\u002F\n:not(.is-done)                      \u002F* 排除 *\u002F\n",[36,997,998,1011,1037,1052,1060,1068],{"__ignoreMap":34},[39,999,1000,1003,1005,1008],{"class":41,"line":42},[39,1001,1002],{"class":60},":first-child",[39,1004,918],{"class":52},[39,1006,1007],{"class":60},":last-child",[39,1009,1010],{"class":45},"          \u002F* 首尾 *\u002F\n",[39,1012,1013,1016,1018,1021,1024,1026,1028,1031,1034],{"class":41,"line":49},[39,1014,1015],{"class":60},":nth-child",[39,1017,173],{"class":52},[39,1019,1020],{"class":112},"2n",[39,1022,1023],{"class":52},")  \u002F  ",[39,1025,1015],{"class":60},[39,1027,173],{"class":52},[39,1029,1030],{"class":112},"even",[39,1032,1033],{"class":52},") ",[39,1035,1036],{"class":45},"\u002F* 偶数；也可 (2n+1)、odd、from-end(2) *\u002F\n",[39,1038,1039,1041,1043,1046,1049],{"class":41,"line":82},[39,1040,1015],{"class":60},[39,1042,173],{"class":52},[39,1044,1045],{"class":112},"-n+3",[39,1047,1048],{"class":52},")                    ",[39,1050,1051],{"class":45},"\u002F* 前 3 个 *\u002F\n",[39,1053,1054,1057],{"class":41,"line":89},[39,1055,1056],{"class":60},":only-child",[39,1058,1059],{"class":45},"                         \u002F* 独子 *\u002F\n",[39,1061,1062,1065],{"class":41,"line":95},[39,1063,1064],{"class":60},":empty",[39,1066,1067],{"class":45},"                              \u002F* 无子节点也无文本（空白符也算文本，格式化容易破坏它） *\u002F\n",[39,1069,1070,1073,1075,1078,1081],{"class":41,"line":147},[39,1071,1072],{"class":60},":not",[39,1074,173],{"class":52},[39,1076,1077],{"class":60},".is-done",[39,1079,1080],{"class":52},")                      ",[39,1082,1083],{"class":45},"\u002F* 排除 *\u002F\n",[24,1085,1086],{"id":1086},"伪类与伪元素的分界",[15,1088,1089,1092,1093,1092,1096,1092,1099,1102,1103,1106,1107,1092,1109,1092,1111,1092,1114,1117,1118,1121,1122,1125],{},[36,1090,1091],{},":hover","、",[36,1094,1095],{},":focus",[36,1097,1098],{},":focus-visible",[36,1100,1101],{},":active"," 描述",[19,1104,1105],{},"状态","（单冒号）；",[36,1108,759],{},[36,1110,766],{},[36,1112,1113],{},"::placeholder",[36,1115,1116],{},"::selection"," 创建 DOM 里",[19,1119,1120],{},"不存在的额外内容","（双冒号，第十七章展开）。历史单冒号写法（",[36,1123,1124],{},":before","）仍兼容，新代码请统一双冒号——这样一眼能看出这条规则到底有没有真的往页面里加东西。",[10,1127,1129],{"id":1128},"四层叠优先级与继承","四、层叠、优先级与继承",[24,1131,1133],{"id":1132},"权重计算三个数字","权重计算：三个数字",[219,1135,1136,1149],{},[222,1137,1138],{},[225,1139,1140,1143,1146],{},[228,1141,1142],{},"成分",[228,1144,1145],{},"来自",[228,1147,1148],{},"记为",[238,1150,1151,1164,1186],{},[225,1152,1153,1156,1161],{},[243,1154,1155],{},"id 的个数",[243,1157,1158],{},[36,1159,1160],{},"#buy",[243,1162,1163],{},"1,0,0",[225,1165,1166,1169,1183],{},[243,1167,1168],{},"class \u002F 属性 \u002F 伪类的个数",[243,1170,1171,1092,1174,1092,1177,1092,1179,1182],{},[36,1172,1173],{},".btn",[36,1175,1176],{},"[type=text]",[36,1178,1091],{},[36,1180,1181],{},":not()"," 的参数",[243,1184,1185],{},"0,1,0",[225,1187,1188,1191,1197],{},[243,1189,1190],{},"类型与伪元素的个数",[243,1192,1193,1092,1195],{},[36,1194,15],{},[36,1196,759],{},[243,1198,1199],{},"0,0,1",[304,1201],{"height":455,"src":1202,"title":1203},"\u002Ftutorials\u002Fcss\u002Fdemos\u002F04-cascade.html","示例 04：权重、!important 与继承",[15,1205,1206],{},"三个常见误解：",[316,1208,1209,1216,1239],{},[319,1210,1211,1212,1215],{},"权重",[19,1213,1214],{},"不是十进制","，不会进位：11 个 class（0,11,0）也压不过 1 个 id（1,0,0）。",[319,1217,1218,1220,1221,1223,1224,1223,1227,1230,1231,1234,1235,1238],{},[36,1219,743],{}," 和组合子（",[36,1222,866],{}," ",[36,1225,1226],{},"+",[36,1228,1229],{},"~"," 空格）权重为 0；",[36,1232,1233],{},":where()"," 权重为 0，而 ",[36,1236,1237],{},":is()"," 取参数里最高的那个。",[319,1240,1241,1242,1244,1245,1247],{},"元素的 ",[36,1243,295],{}," 不参与这套计数，它高于所有规则（带 ",[36,1246,327],{}," 的声明除外）。",[24,1249,1251],{"id":1250},"important-的代价","!important 的代价",[15,1253,1254,1255,1257,1258,1261],{},"用了它，唯一的反制手段是「更具体的选择器 + 另一个 ",[36,1256,327],{},"」。项目里一旦开始出现「为了盖住一行 !important 再加一行 !important」，样式表就已经失控。合理用法只有三类：第三方样式表的临时补丁、工具类（如 ",[36,1259,1260],{},".visually-hidden","）、用户自己写的无障碍样式表。",[15,1263,1264,1265,1267,1268,1271,1272,1275],{},"顺带一条：",[36,1266,327],{}," 只影响",[19,1269,1270],{},"这一条声明","，但简写的每个分量都会变得重要——",[36,1273,1274],{},"margin: 0 !important"," 同时锁死四个方向。",[24,1277,1278],{"id":1278},"继承与四个关键字",[15,1280,1281],{},"只有「与文字相关」的大多数属性会继承：",[219,1283,1284,1296],{},[222,1285,1286],{},[225,1287,1288,1291],{},[228,1289,1290],{},"继承",[228,1292,1293,1290],{},[19,1294,1295],{},"不",[238,1297,1298],{},[225,1299,1300,1326],{},[243,1301,1302,1092,1305,1092,1308,1092,1311,1092,1314,1092,1317,1092,1320,1092,1323],{},[36,1303,1304],{},"color",[36,1306,1307],{},"font-*",[36,1309,1310],{},"line-height",[36,1312,1313],{},"text-*",[36,1315,1316],{},"letter-spacing",[36,1318,1319],{},"visibility",[36,1321,1322],{},"cursor",[36,1324,1325],{},"writing-mode",[243,1327,1328,1329,1331,1332,1331,1335,1331,1338,1331,1341,1344,1345,1092,1348,1092,1351,1354,1355,1331,1358,1361,1362,1092,1365,1092,1368],{},"盒模型（",[36,1330,129],{},"\u002F",[36,1333,1334],{},"padding",[36,1336,1337],{},"border",[36,1339,1340],{},"width",[36,1342,1343],{},"height","）、",[36,1346,1347],{},"background",[36,1349,1350],{},"display",[36,1352,1353],{},"position"," 与定位、",[36,1356,1357],{},"flex",[36,1359,1360],{},"grid"," 全部、",[36,1363,1364],{},"overflow",[36,1366,1367],{},"opacity",[36,1369,1370],{},"transform",[15,1372,1373],{},"四个随时手动改变继承行为的关键字：",[29,1375,1377],{"className":375,"code":1376,"language":377,"meta":34,"style":34},"color: inherit;   \u002F* 强制继承父元素的值 *\u002F\ncolor: initial;   \u002F* 强制回到该属性的初始值（切断继承） *\u002F\ncolor: unset;     \u002F* 可继承属性 = inherit，不可继承属性 = initial *\u002F\ncolor: revert;    \u002F* 回到上一层来源的值，通常是浏览器默认样式表 *\u002F\n",[36,1378,1379,1387,1395,1403],{"__ignoreMap":34},[39,1380,1381,1384],{"class":41,"line":42},[39,1382,1383],{"class":52},"color: inherit;   ",[39,1385,1386],{"class":45},"\u002F* 强制继承父元素的值 *\u002F\n",[39,1388,1389,1392],{"class":41,"line":49},[39,1390,1391],{"class":52},"color: initial;   ",[39,1393,1394],{"class":45},"\u002F* 强制回到该属性的初始值（切断继承） *\u002F\n",[39,1396,1397,1400],{"class":41,"line":82},[39,1398,1399],{"class":52},"color: unset;     ",[39,1401,1402],{"class":45},"\u002F* 可继承属性 = inherit，不可继承属性 = initial *\u002F\n",[39,1404,1405,1408],{"class":41,"line":89},[39,1406,1407],{"class":52},"color: revert;    ",[39,1409,1410],{"class":45},"\u002F* 回到上一层来源的值，通常是浏览器默认样式表 *\u002F\n",[15,1412,1413,1416,1417,1420,1421,1423,1424,1427,1428,1430,1431,1433,1434,1436,1437,1440,1441,1443],{},[36,1414,1415],{},"revert"," 与 ",[36,1418,1419],{},"unset"," 的区别很实用：浏览器给 ",[36,1422,434],{}," 的默认 ",[36,1425,1426],{},"padding-inline-start: 40px","，写 ",[36,1429,1419],{}," 得 0，写 ",[36,1432,1415],{}," 也回到默认——但当你要「撤销用户样式覆盖」或恢复用户代理样式时，只有 ",[36,1435,1415],{}," 语义正确。另有 ",[36,1438,1439],{},"revert-layer","，用于撤销当前 ",[36,1442,339],{}," 内的结果（第十六章）。",[24,1445,1447],{"id":1446},"后写的为什么没生效四条排查思路","后写的为什么没生效：四条排查思路",[316,1449,1450,1457,1464,1471],{},[319,1451,1452,1453,1456],{},"Styles 面板看那条规则",[19,1454,1455],{},"有没有被划掉","，划掉会附带「被谁压制」的提示。",[319,1458,1459,1460,1463],{},"规则",[19,1461,1462],{},"根本没出现","在面板里 → 选择器没命中，或整块解析失败。",[319,1465,1466,1467,1470],{},"用 ",[19,1468,1469],{},"Computed"," 面板搜属性名，能看到最终值来自哪一条声明。",[319,1472,1473,1474,1477],{},"怀疑是继承：给元素显式写 ",[36,1475,1476],{},"color: initial","，值变了说明原先那个值是继承来的。",[10,1479,1481],{"id":1480},"五单位与颜色","五、单位与颜色",[24,1483,1484],{"id":1484},"绝对单位与相对单位",[15,1486,1487,1489,1490,1331,1493,1331,1496,1499],{},[36,1488,123],{}," 是屏幕上最稳的长度单位（1px = 一个设备像素，高倍屏由浏览器处理）。",[36,1491,1492],{},"cm",[36,1494,1495],{},"in",[36,1497,1498],{},"pt"," 属于打印样式世界，别拿来做网页布局。",[219,1501,1502,1515],{},[222,1503,1504],{},[225,1505,1506,1509,1512],{},[228,1507,1508],{},"单位",[228,1510,1511],{},"相对什么",[228,1513,1514],{},"典型用途",[238,1516,1517,1533,1546,1563,1583,1596,1613],{},[225,1518,1519,1524,1527],{},[243,1520,1521],{},[36,1522,1523],{},"rem",[243,1525,1526],{},"根元素字号",[243,1528,1529,1532],{},[19,1530,1531],{},"字号与间距的首选","：改根字号即全站等比缩放",[225,1534,1535,1540,1543],{},[243,1536,1537],{},[36,1538,1539],{},"em",[243,1541,1542],{},"当前元素的字号（继承类属性看父元素）",[243,1544,1545],{},"组件内部尺寸随自身字号走，例如按钮内边距",[225,1547,1548,1553,1560],{},[243,1549,1550],{},[36,1551,1552],{},"%",[243,1554,1555,1556,1559],{},"视属性而定：宽度对父宽、高度对父高、",[19,1557,1558],{},"padding 对父元素宽度","、字号对父字号",[243,1561,1562],{},"栅格、流体容器",[225,1564,1565,1573,1576],{},[243,1566,1567,918,1570],{},[36,1568,1569],{},"vw",[36,1571,1572],{},"vh",[243,1574,1575],{},"视口宽 \u002F 高",[243,1577,1578,1579,1582],{},"整屏高度建议用 ",[36,1580,1581],{},"svh","（小视口），避开手机地址栏收起造成的跳动",[225,1584,1585,1590,1593],{},[243,1586,1587],{},[36,1588,1589],{},"ch",[243,1591,1592],{},"「0」字符宽度",[243,1594,1595],{},"限制正文行长（一屏 45–75 字符最易读）",[225,1597,1598,1603,1606],{},[243,1599,1600],{},[36,1601,1602],{},"ic",[243,1604,1605],{},"一个「水」字宽度",[243,1607,1608,1609,1612],{},"中文排版很直观：",[36,1610,1611],{},"max-width: 38ic"," ≈ 一行 38 字",[225,1614,1615,1620,1623],{},[243,1616,1617],{},[36,1618,1619],{},"fr",[243,1621,1622],{},"Grid 的剩余空间",[243,1624,1625,1626,1629],{},"只出现在 ",[36,1627,1628],{},"grid-template-*","（第十一章）",[304,1631],{"height":455,"src":1632,"title":1633},"\u002Ftutorials\u002Fcss\u002Fdemos\u002F05a-units.html","示例 05a：rem \u002F em \u002F % \u002F vw \u002F ch 的差异",[15,1635,1636,1637,1640,1641,1644,1645,1648,1649,1092,1652,1092,1655,1092,1657,1660,1661,1331,1664,1331,1667,1670,1671,1674,1675,1678,1679,1331,1682,590],{},"还有几类不需要长度单位：",[36,1638,1639],{},"line-height: 1.6","（无单位数字 = 字号倍数，比 ",[36,1642,1643],{},"1.6em"," 安全，不会随继承重复相乘）、",[36,1646,1647],{},"margin: 0","（0 不需要单位）、",[36,1650,1651],{},"flex-grow",[36,1653,1654],{},"z-index",[36,1656,1367],{},[36,1658,1659],{},"font-weight","。角度有 ",[36,1662,1663],{},"deg",[36,1665,1666],{},"turn",[36,1668,1669],{},"rad","（转 90° 写 ",[36,1672,1673],{},".25turn"," 比 ",[36,1676,1677],{},"90deg"," 更直观），时间有 ",[36,1680,1681],{},"s",[36,1683,1684],{},"ms",[24,1686,1687],{"id":1687},"颜色的六种写法",[29,1689,1691],{"className":375,"code":1690,"language":377,"meta":34,"style":34},"#0969da             \u002F* RRGGBB *\u002F\n#0969da80           \u002F* RRGGBBAA：最后两位是透明度，00 全透明 *\u002F\n#069                \u002F* 三位缩写 = #006699，只有每对数字相同才能缩写；#069da（5 位）非法 *\u002F\nrgb(9 105 218)      \u002F* 现代语法用空格分隔，逗号写法同样支持 *\u002F\nrgb(9 105 218 \u002F .5) \u002F* 透明度单独给 *\u002F\nhsl(212 92% 45% \u002F 50%)\nhwb(212 4% 15%)     \u002F* 白量、黑量，比 hsl 更符合「调深浅」的直觉 *\u002F\noklch(52% 0.19 253) \u002F* 感知均匀 *\u002F\nroyalblue           \u002F* 147 个 CSS 命名色之一，正式项目不建议 *\u002F\ntransparent  currentColor  inherit\n",[36,1692,1693,1702,1710,1718,1726,1739,1744,1752,1766,1774],{"__ignoreMap":34},[39,1694,1695,1699],{"class":41,"line":42},[39,1696,1698],{"class":1697},"s6RL2","#0969da",[39,1700,1701],{"class":45},"             \u002F* RRGGBB *\u002F\n",[39,1703,1704,1707],{"class":41,"line":49},[39,1705,1706],{"class":1697},"#0969da80",[39,1708,1709],{"class":45},"           \u002F* RRGGBBAA：最后两位是透明度，00 全透明 *\u002F\n",[39,1711,1712,1715],{"class":41,"line":82},[39,1713,1714],{"class":1697},"#069",[39,1716,1717],{"class":45},"                \u002F* 三位缩写 = #006699，只有每对数字相同才能缩写；#069da（5 位）非法 *\u002F\n",[39,1719,1720,1723],{"class":41,"line":89},[39,1721,1722],{"class":52},"rgb(9 105 218)      ",[39,1724,1725],{"class":45},"\u002F* 现代语法用空格分隔，逗号写法同样支持 *\u002F\n",[39,1727,1728,1731,1734,1736],{"class":41,"line":95},[39,1729,1730],{"class":52},"rgb(9 105 218 \u002F ",[39,1732,1733],{"class":1697},".5",[39,1735,1033],{"class":52},[39,1737,1738],{"class":45},"\u002F* 透明度单独给 *\u002F\n",[39,1740,1741],{"class":41,"line":147},[39,1742,1743],{"class":52},"hsl(212 92% 45% \u002F 50%)\n",[39,1745,1746,1749],{"class":41,"line":152},[39,1747,1748],{"class":52},"hwb(212 4% 15%)     ",[39,1750,1751],{"class":45},"\u002F* 白量、黑量，比 hsl 更符合「调深浅」的直觉 *\u002F\n",[39,1753,1754,1757,1760,1763],{"class":41,"line":158},[39,1755,1756],{"class":52},"oklch(52% 0",[39,1758,1759],{"class":60},".19",[39,1761,1762],{"class":52}," 253) ",[39,1764,1765],{"class":45},"\u002F* 感知均匀 *\u002F\n",[39,1767,1768,1771],{"class":41,"line":186},[39,1769,1770],{"class":52},"royalblue           ",[39,1772,1773],{"class":45},"\u002F* 147 个 CSS 命名色之一，正式项目不建议 *\u002F\n",[39,1775,1776],{"class":41,"line":191},[39,1777,1778],{"class":52},"transparent  currentColor  inherit\n",[304,1780],{"height":455,"src":1781,"title":1782},"\u002Ftutorials\u002Fcss\u002Fdemos\u002F05b-colors.html","示例 05b：颜色写法与透明度",[15,1784,1785,1786,1789,1790,1793,1794,1797,1798,672,1801,1807],{},"选写法的依据：固定品牌色用 ",[36,1787,1788],{},"#RRGGBB","；要成组调明暗、生成色阶用 ",[36,1791,1792],{},"hsl()"," 或 ",[36,1795,1796],{},"hwb()","（改一个数字出一系列）；JS 计算出的色值用 ",[36,1799,1800],{},"rgb(… \u002F a)",[19,1802,1803,1804],{},"做色阶系统用 ",[36,1805,1806],{},"oklch()","——HSL 的「50% 亮度」在不同色相下视觉明度差很多（黄色亮、蓝紫暗），OKLCH 是感知均匀的，同一 L 值的各色看起来真的同样亮。",[24,1809,1811],{"id":1810},"透明度currentcolor-与暗色主题","透明度、currentColor 与暗色主题",[15,1813,1814,1416,1817,1819,1820,1823,1824,1827,1828,1831],{},[36,1815,1816],{},"alpha",[36,1818,1367],{}," 不是一件事：",[36,1821,1822],{},"background: rgb(9 105 218 \u002F .5)"," 只让这一层背景透明，文字仍然清晰；",[36,1825,1826],{},"opacity: .5"," 把整层（含子元素、边框）一起透明，并且",[19,1829,1830],{},"会创建层叠上下文","（第十二章）。",[15,1833,1834,1837,1838,1840,1841,1092,1844,1847],{},[36,1835,1836],{},"currentColor"," 取当前元素的 ",[36,1839,1304],{}," 值，于是 ",[36,1842,1843],{},"border-color: currentColor",[36,1845,1846],{},"box-shadow: 0 0 0 3px currentColor"," 会随主题自动跟随，不必额外维护变量。",[15,1849,1850],{},"暗色主题的正解是把颜色收进自定义属性（第十四章）：",[29,1852,1854],{"className":375,"code":1853,"language":377,"meta":34,"style":34},":root { --c-bg: #fff; --c-text: #24292f; --c-primary: #0969da; }\nhtml[data-theme='dark'] { --c-bg: #0d1117; --c-text: #e6edf3; --c-primary: #6aa8ff; }\n",[36,1855,1856,1892],{"__ignoreMap":34},[39,1857,1858,1861,1863,1867,1869,1872,1874,1877,1879,1881,1883,1886,1888,1890],{"class":41,"line":42},[39,1859,1860],{"class":60},":root",[39,1862,109],{"class":52},[39,1864,1866],{"class":1865},"s9osk","--c-bg",[39,1868,116],{"class":52},[39,1870,1871],{"class":112},"#fff",[39,1873,126],{"class":52},[39,1875,1876],{"class":1865},"--c-text",[39,1878,116],{"class":52},[39,1880,408],{"class":112},[39,1882,126],{"class":52},[39,1884,1885],{"class":1865},"--c-primary",[39,1887,116],{"class":52},[39,1889,1698],{"class":112},[39,1891,779],{"class":52},[39,1893,1894,1896,1899,1902,1904,1907,1910,1912,1914,1917,1919,1921,1923,1926,1928,1930,1932,1935],{"class":41,"line":49},[39,1895,33],{"class":56},[39,1897,1898],{"class":52},"[",[39,1900,1901],{"class":60},"data-theme",[39,1903,64],{"class":122},[39,1905,1906],{"class":67},"'dark'",[39,1908,1909],{"class":52},"] { ",[39,1911,1866],{"class":1865},[39,1913,116],{"class":52},[39,1915,1916],{"class":112},"#0d1117",[39,1918,126],{"class":52},[39,1920,1876],{"class":1865},[39,1922,116],{"class":52},[39,1924,1925],{"class":112},"#e6edf3",[39,1927,126],{"class":52},[39,1929,1885],{"class":1865},[39,1931,116],{"class":52},[39,1933,1934],{"class":112},"#6aa8ff",[39,1936,779],{"class":52},[15,1938,1939,1940,1943],{},"不要把颜色简单取反：深蓝底配高饱和品牌色会「发光」刺眼，通常要降饱和、提明度。另外 ",[36,1941,1942],{},"color-scheme: light dark"," 这一行能让浏览器的默认控件、滚动条、表单底色一起切换——成本极低，收益明显（本站全站样式里就有这一条）。",[10,1945,1947],{"id":1946},"六盒模型所有尺寸问题最后都回到这四层","六、盒模型：所有尺寸问题最后都回到这四层",[15,1949,1950],{},"前面五章解决的是「谁生效」。从这一章起解决「生效成多大」，而元素的大小由盒模型（box model）决定：内容盒（content）→ 内边距（padding）→ 边框（border）→ 外边距（margin），由内向外四层。",[304,1952],{"height":455,"src":1953,"title":1954},"\u002Ftutorials\u002Fcss\u002Fdemos\u002F06-box-model.html","示例 06：两种盒模型、边距塌陷与负 margin",[24,1956,1958,1416,1961,676,1963,1965],{"id":1957},"content-box-与-border-boxwidth-到底指哪一层",[36,1959,1960],{},"content-box",[36,1962,776],{},[36,1964,1340],{}," 到底指哪一层",[15,1967,1968,1969,676,1971,1973,1974,1977],{},"浏览器默认是 ",[36,1970,1960],{},[36,1972,1340],{}," 只描述",[19,1975,1976],{},"内容区","，padding 和 border 在它外面往外撑。于是这个经典事故：",[29,1979,1981],{"className":375,"code":1980,"language":377,"meta":34,"style":34},".card { width: 100%; padding: 16px; border: 1px solid #ddd; }  \u002F* 实际占位 = 100% + 34px，横向溢出 *\u002F\n",[36,1982,1983],{"__ignoreMap":34},[39,1984,1985,1987,1989,1991,1993,1996,1998,2000,2002,2004,2007,2009,2011,2013,2015,2018,2020,2023,2026,2029],{"class":41,"line":42},[39,1986,721],{"class":60},[39,1988,109],{"class":52},[39,1990,1340],{"class":112},[39,1992,116],{"class":52},[39,1994,1995],{"class":112},"100",[39,1997,1552],{"class":122},[39,1999,126],{"class":52},[39,2001,1334],{"class":112},[39,2003,116],{"class":52},[39,2005,2006],{"class":112},"16",[39,2008,123],{"class":122},[39,2010,126],{"class":52},[39,2012,1337],{"class":112},[39,2014,116],{"class":52},[39,2016,2017],{"class":112},"1",[39,2019,123],{"class":122},[39,2021,2022],{"class":112}," solid",[39,2024,2025],{"class":112}," #ddd",[39,2027,2028],{"class":52},"; }  ",[39,2030,2031],{"class":45},"\u002F* 实际占位 = 100% + 34px，横向溢出 *\u002F\n",[15,2033,2034,2035,2037,2038,2040,2041,2044],{},"改成 ",[36,2036,776],{}," 之后，",[36,2039,1340],{}," 变成「最终占位宽」，padding 和 border 从里面扣，",[36,2042,2043],{},"width: 100%"," 就真的是 100%。所以现代项目的第一行几乎都写成：",[29,2046,2048],{"className":375,"code":2047,"language":377,"meta":34,"style":34},"*, *::before, *::after { box-sizing: border-box; }\n",[36,2049,2050],{"__ignoreMap":34},[39,2051,2052,2054,2056,2058,2060,2062,2064,2066,2068,2070,2072,2074],{"class":41,"line":42},[39,2053,743],{"class":56},[39,2055,392],{"class":52},[39,2057,743],{"class":56},[39,2059,759],{"class":60},[39,2061,392],{"class":52},[39,2063,743],{"class":56},[39,2065,766],{"class":60},[39,2067,109],{"class":52},[39,2069,771],{"class":112},[39,2071,116],{"class":52},[39,2073,776],{"class":112},[39,2075,779],{"class":52},[15,2077,2078,2079,2082,2083,2085],{},"选择器里的 ",[36,2080,2081],{},"*::before, *::after"," 不能省：伪元素同样是盒子，用 ",[36,2084,743],{}," 选不到它们，很多「加了装饰就溢出」的问题出在这。",[15,2087,2088],{},"两条边界情况值得提前知道：",[434,2090,2091,2102],{},[319,2092,2093,2095,2096,2098,2099,672],{},[36,2094,776],{}," 下 ",[36,2097,1340],{}," 不再等于内容宽。文字类容器要保底，用 ",[36,2100,2101],{},"min-width",[319,2103,2104,2105,2108,2109,2112],{},"全局 ",[36,2106,2107],{},"box-sizing: border-box"," 之后，某些第三方 CSS（老式表单样式、部分日历组件）会算错尺寸，这时对那几个选择器单独写回 ",[36,2110,2111],{},"box-sizing: content-box","，不要反过来取消全局声明。",[24,2114,2116,1416,2118,2120],{"id":2115},"margin-与-padding一个占外面一个占里面",[36,2117,129],{},[36,2119,1334],{},"：一个占外面、一个占里面",[15,2122,2123,2124,2127,2128,2130,2131,590],{},"判断标准很简单：",[19,2125,2126],{},"背景色要不要覆盖这块区域","。要覆盖（内文离边缘的距离、可点击区域的大小）就用 ",[36,2129,1334],{},"；只是把邻居推开就用 ",[36,2132,129],{},[15,2134,2135],{},"由此引出几条实用的差别：",[434,2137,2138,2148,2165],{},[319,2139,2140,2142,2143,2145,2146,672],{},[36,2141,1334],{}," 会扩大背景与点击热区，导航项的可点击范围不足时，先加 ",[36,2144,1334],{}," 而不是加 ",[36,2147,129],{},[319,2149,2150,2152,2153,2156,2157,2160,2161,2164],{},[36,2151,1334],{}," 不吃百分比的高度语义：",[36,2154,2155],{},"padding: 5%"," 的",[19,2158,2159],{},"上下","部分也是按父元素",[19,2162,2163],{},"宽度","算的（历史上为了做等高列），这条最容易记错；",[319,2166,2167,2169,2170,2173,2174,2177],{},[36,2168,129],{}," 有 ",[36,2171,2172],{},"auto"," 这个特殊值：",[36,2175,2176],{},"margin-inline: auto"," 让块级元素在父容器里水平居中，这是「不定宽容器居中」的最短写法。",[24,2179,2181],{"id":2180},"外边距塌陷16px-16px-为什么只有-16px","外边距塌陷：16px + 16px 为什么只有 16px",[15,2183,2184,2185,2188,2189,2192],{},"两个相邻",[19,2186,2187],{},"块级","元素的垂直 margin 会合并成一个，取绝对值较大的那个。所以「上下相邻的两个卡片各写 ",[36,2190,2191],{},"margin: 16px","」得到的间距是 16px，不是 32px。合并规则有三种情形：正正取大、负负取绝对值大的、正负相加。",[15,2194,2195,2196,2199,2200,2203,2204,2207,2208,2211,2212,2215],{},"更常见的是第二种塌陷——",[19,2197,2198],{},"父与子的 margin 穿透","：父元素没有 ",[36,2201,2202],{},"padding-top","、没有 ",[36,2205,2206],{},"border-top","、且不是 BFC 时，子的 ",[36,2209,2210],{},"margin-top"," 会把父元素一起推下去，看起来像「margin 加到了父身上」。老代码里给父容器随手写 ",[36,2213,2214],{},"overflow: hidden"," 就是在处理这个问题（它在创建 BFC）。",[15,2217,2218,2219,2225,2226,2228,2229,2232],{},"今天的最优解不是背塌陷规则，而是",[19,2220,2221,2222],{},"改用 Flex\u002FGrid 的 ",[36,2223,2224],{},"gap","：Flex 与 Grid 的子项之间不发生 margin 合并，间距由 ",[36,2227,2224],{}," 一处声明，首尾不会多出空白，也不需要 ",[36,2230,2231],{},":last-child { margin: 0 }","。这一条能消掉大部分「间距玄学」。",[24,2234,2236,2237,2239],{"id":2235},"负-margin合法但危险","负 ",[36,2238,129],{},"：合法但危险",[15,2241,2242,2245],{},[36,2243,2244],{},"margin-left: -12px"," 能把元素往左拽回 12px，头像列表相互叠压、把内容对齐到视觉基线（数字悬挂在标点左侧）都会用到。风险是它把元素推到容器之外，窄屏会直接产生横向滚动条。",[29,2247,2249],{"className":375,"code":2248,"language":377,"meta":34,"style":34},".avatars img { margin-left: -8px; }             \u002F* 叠压效果 *\u002F\n.avatars img:first-child { margin-left: 0; }    \u002F* 第一个不叠，否则整体左移 *\u002F\n.avatars img { border: 2px solid #fff; }        \u002F* 必须给描边，否则叠在一起看不出层次 *\u002F\n",[36,2250,2251,2277,2299],{"__ignoreMap":34},[39,2252,2253,2256,2259,2261,2264,2266,2269,2271,2274],{"class":41,"line":42},[39,2254,2255],{"class":60},".avatars",[39,2257,2258],{"class":56}," img",[39,2260,109],{"class":52},[39,2262,2263],{"class":112},"margin-left",[39,2265,116],{"class":52},[39,2267,2268],{"class":112},"-8",[39,2270,123],{"class":122},[39,2272,2273],{"class":52},"; }             ",[39,2275,2276],{"class":45},"\u002F* 叠压效果 *\u002F\n",[39,2278,2279,2281,2283,2285,2287,2289,2291,2293,2296],{"class":41,"line":49},[39,2280,2255],{"class":60},[39,2282,2258],{"class":56},[39,2284,1002],{"class":60},[39,2286,109],{"class":52},[39,2288,2263],{"class":112},[39,2290,116],{"class":52},[39,2292,134],{"class":112},[39,2294,2295],{"class":52},"; }    ",[39,2297,2298],{"class":45},"\u002F* 第一个不叠，否则整体左移 *\u002F\n",[39,2300,2301,2303,2305,2307,2309,2311,2314,2316,2318,2321,2324],{"class":41,"line":82},[39,2302,2255],{"class":60},[39,2304,2258],{"class":56},[39,2306,109],{"class":52},[39,2308,1337],{"class":112},[39,2310,116],{"class":52},[39,2312,2313],{"class":112},"2",[39,2315,123],{"class":122},[39,2317,2022],{"class":112},[39,2319,2320],{"class":112}," #fff",[39,2322,2323],{"class":52},"; }        ",[39,2325,2326],{"class":45},"\u002F* 必须给描边，否则叠在一起看不出层次 *\u002F\n",[15,2328,2329,2330,2333,2334,1793,2336,590],{},"只在一维上用负 margin。两列布局用负 margin 拼间距是二十年前的做法（",[36,2331,2332],{},"float"," + 负 margin 的栅格），今天写 ",[36,2335,2224],{},[36,2337,2338],{},"minmax()",[24,2340,2341],{"id":2341},"自查清单",[15,2343,2344],{},"排「尺寸不对」时按这个顺序看：",[316,2346,2347,2353,2363,2371],{},[319,2348,2349,2350,2352],{},"Computed 面板的盒子图，确认 ",[36,2351,771],{}," 生效（被 reset 文件覆盖是常见事故）；",[319,2354,2355,2357,2358,2357,2360,2362],{},[36,2356,1340],{}," + ",[36,2359,1334],{},[36,2361,1337],{}," 是否超过父容器；",[319,2364,2365,2366,1793,2368,2370],{},"上下间距不对时，先确认有没有塌陷（把 margin 换成 ",[36,2367,2224],{},[36,2369,1334],{},"，如果问题消失，就是塌陷）；",[319,2372,2373,2374,1331,2376,2379],{},"内容把容器撑爆时，查 ",[36,2375,2101],{},[36,2377,2378],{},"min-height","（Flex\u002FGrid 子项的自动最小尺寸，见第十章与十一章）。",[10,2381,2383],{"id":2382},"七文本与字体中文排版的三个特殊点","七、文本与字体：中文排版的三个特殊点",[15,2385,2386,2387,2390,2391,2393,2394,2390,2397,1092,2399,1092,2402,2405],{},"文字是网页的主要内容，而 CSS 里跟文字有关的属性分两组：一组决定",[19,2388,2389],{},"用什么样的字","（",[36,2392,1307],{},"），一组决定",[19,2395,2396],{},"这些字怎么排",[36,2398,1313],{},[36,2400,2401],{},"white-space",[36,2403,2404],{},"word-break","）。",[304,2407],{"height":2408,"src":2409,"title":2410},700,"\u002Ftutorials\u002Fcss\u002Fdemos\u002F07-text-font.html","示例 07：字体栈、行高、换行与截断",[24,2412,2414],{"id":2413},"字体栈与-fallback-顺序","字体栈与 fallback 顺序",[29,2416,2418],{"className":375,"code":2417,"language":377,"meta":34,"style":34},"body {\n  font-family: system-ui, -apple-system, \"Segoe UI\", \"PingFang SC\",\n               \"Hiragino Sans GB\", \"Microsoft YaHei\", sans-serif;\n}\n",[36,2419,2420,2426,2454,2471],{"__ignoreMap":34},[39,2421,2422,2424],{"class":41,"line":42},[39,2423,106],{"class":56},[39,2425,398],{"class":52},[39,2427,2428,2431,2433,2436,2438,2441,2443,2446,2448,2451],{"class":41,"line":49},[39,2429,2430],{"class":112},"  font-family",[39,2432,116],{"class":52},[39,2434,2435],{"class":112},"system-ui",[39,2437,392],{"class":52},[39,2439,2440],{"class":112},"-apple-system",[39,2442,392],{"class":52},[39,2444,2445],{"class":67},"\"Segoe UI\"",[39,2447,392],{"class":52},[39,2449,2450],{"class":67},"\"PingFang SC\"",[39,2452,2453],{"class":52},",\n",[39,2455,2456,2459,2461,2464,2466,2469],{"class":41,"line":82},[39,2457,2458],{"class":67},"               \"Hiragino Sans GB\"",[39,2460,392],{"class":52},[39,2462,2463],{"class":67},"\"Microsoft YaHei\"",[39,2465,392],{"class":52},[39,2467,2468],{"class":112},"sans-serif",[39,2470,427],{"class":52},[39,2472,2473],{"class":41,"line":89},[39,2474,432],{"class":52},[15,2476,2477,2480,2481,2484],{},[36,2478,2479],{},"font-family"," 是",[19,2482,2483],{},"一个候选列表","，浏览器从左往右取第一个「本机装有」的字体，全部落空才用最后的通用族关键字。因此三条规则：",[434,2486,2487,2501,2504],{},[319,2488,2489,2490,2492,2493,1092,2495,1092,2497,2500],{},"带空格的名字必须加引号（",[36,2491,2450],{},"），关键字（",[36,2494,2468],{},[36,2496,2435],{},[36,2498,2499],{},"monospace","）不加；",[319,2502,2503],{},"末尾一定要放通用族兜底；",[319,2505,2506,2507,2510,2511,2514],{},"中文站一定要写中文族名。只写 ",[36,2508,2509],{},"Arial"," 时中文交给浏览器随机 fallback，Windows 与 macOS 的字重表现差别很大，",[36,2512,2513],{},"bold"," 在一种系统上偏细、在另一种上糊成一团。",[15,2516,2517,2519],{},[36,2518,2435],{}," 取操作系统界面字体，优点是零下载、风格与用户设备一致；缺点是各平台长得不一样，做品牌感强的标题时通常换成西文品牌字体 + 中文族名的组合。",[15,2521,2522,2523,2526,2527,2530],{},"网络字体用 ",[36,2524,2525],{},"@font-face"," 声明，配 ",[36,2528,2529],{},"font-display: swap","（先回退字显示、下载完再换），否则首屏会出现一段纯白文字（FOIT）。中文字体动辄几 MB，务必只加载需要的字重，或按章节做子集化。",[24,2532,2534,1092,2537,1092,2539],{"id":2533},"font-sizefont-weightline-height",[36,2535,2536],{},"font-size",[36,2538,1659],{},[36,2540,1310],{},[434,2542,2543,2551,2582],{},[319,2544,2545,2550],{},[19,2546,2547,2548],{},"字号用 ",[36,2549,1523],{},"：根字号是用户\u002F浏览器设置的入口，全站用 rem 时这一设置才真的起作用。正文不小于 14px，可点击文字建议 16px。",[319,2552,2553,2390,2556,1331,2559,1331,2562,2564,2565,2567,2568,2570,2571,2574,2575,2578,2579,2581],{},[19,2554,2555],{},"字重优先用数字",[36,2557,2558],{},"400",[36,2560,2561],{},"600",[36,2563,119],{},"），别依赖 ",[36,2566,2513],{}," 关键字：",[36,2569,2513],{}," 固定映射到 700，而中文字体常常只有 400 与 700 两档，浏览器会",[19,2572,2573],{},"合成","加粗（人为描边），中文一多就糊。中文正文里 ",[36,2576,2577],{},"font-weight: 600"," 往往比 ",[36,2580,2513],{}," 更耐看。",[319,2583,2584,676,2587,2590,2591,2594,2595,2598,2599,2602],{},[19,2585,2586],{},"行高写无单位数字",[36,2588,2589],{},"line-height: 1.7"," 相对",[19,2592,2593],{},"本元素字号","计算且继承的是这个数字；写成 ",[36,2596,2597],{},"1.7em"," 时子元素会按",[19,2600,2601],{},"自己的字号","再乘一次，嵌套层级一深就翻倍。中文正文建议 1.6–1.8，标题 1.2–1.3。",[15,2604,2605,2608,2609,2612,2613,1416,2616,2619,2620,2623],{},[36,2606,2607],{},"font"," 简写顺序固定：",[36,2610,2611],{},"font: style variant weight size\u002Fline-height family","，",[36,2614,2615],{},"size",[36,2617,2618],{},"family"," 必填，缺省时其余部分会被重置为初始值——这也是为什么「只想要 ",[36,2621,2622],{},"font: 16px sans-serif"," 而不重置行高」是错的写法。",[24,2625,2627],{"id":2626},"字距词距与大小写","字距、词距与大小写",[15,2629,2630,2632,2633,2635,2636,2390,2639,2642,2643,2390,2646,2649,2650,2405,2653,2656],{},[36,2631,1316],{}," 用 ",[36,2634,1539],{}," 为单位才随字号变化：大标题需要",[19,2637,2638],{},"负字距",[36,2640,2641],{},"-0.02em","）才不显松散，全大写的小标签需要",[19,2644,2645],{},"正字距",[36,2647,2648],{},".08em","–",[36,2651,2652],{},".12em",[36,2654,2655],{},"word-spacing"," 只影响词间空白，中文几乎没有词，主要作用于西文。",[15,2658,2659,2662,2663,2666],{},[36,2660,2661],{},"text-transform: uppercase"," 只改显示、不改 DOM 文本，因此对搜索、复制、读屏都可能造成偏差；中文还有 ",[36,2664,2665],{},"full-width"," 值。做小标签时用它，但正文内容不要用（英语句首大写规则会丢失）。",[24,2668,2669],{"id":2669},"对齐与装饰",[15,2671,2672,2675,2676,1331,2679,1331,2682,1331,2685,590,2688,2690,2691,2694,2695,2698,2699,2701,2702,2705],{},[36,2673,2674],{},"text-align"," 管行内内容在块里的对齐：",[36,2677,2678],{},"left",[36,2680,2681],{},"right",[36,2683,2684],{},"center",[36,2686,2687],{},"justify",[36,2689,2687],{}," 在西文里要配 ",[36,2692,2693],{},"hyphens: auto"," 和正确的 ",[36,2696,2697],{},"lang","，否则词间空隙会夸张到出现「河流」；中文用 ",[36,2700,2687],{}," 效果接近两端对齐但没有连字符机制。",[36,2703,2704],{},"text-align-last"," 单独控制最后一行。",[15,2707,2708,2711,2712,676],{},[36,2709,2710],{},"text-decoration"," 家族需要注意它是",[19,2713,2714],{},"画在文字上而非盒子下",[29,2716,2718],{"className":375,"code":2717,"language":377,"meta":34,"style":34},"a { text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; }\n",[36,2719,2720],{"__ignoreMap":34},[39,2721,2722,2725,2727,2729,2731,2734,2736,2739,2741,2744,2746,2748,2751,2753,2755,2757],{"class":41,"line":42},[39,2723,2724],{"class":56},"a",[39,2726,109],{"class":52},[39,2728,2710],{"class":112},[39,2730,116],{"class":52},[39,2732,2733],{"class":112},"underline",[39,2735,126],{"class":52},[39,2737,2738],{"class":112},"text-underline-offset",[39,2740,116],{"class":52},[39,2742,2743],{"class":112},"3",[39,2745,123],{"class":122},[39,2747,126],{"class":52},[39,2749,2750],{"class":112},"text-decoration-thickness",[39,2752,116],{"class":52},[39,2754,2017],{"class":112},[39,2756,123],{"class":122},[39,2758,779],{"class":52},[15,2760,2761,2763,2764,2767,2768,2771],{},[36,2762,2738],{}," 让下划线离开基线，中文尤其需要（汉字下沿低，默认位置容易贴着笔画）。删除上下划线时写 ",[36,2765,2766],{},"text-decoration-line: none"," 而不是 ",[36,2769,2770],{},"text-decoration: none","，后者会重置整族属性。",[24,2773,2775,2777],{"id":2774},"white-space断行与截断",[36,2776,2401],{},"、断行与截断",[15,2779,2780],{},"这一组属性治的是「文字撑破容器」：",[434,2782,2783,2789,2795,2801,2815],{},[319,2784,2785,2788],{},[36,2786,2787],{},"white-space: nowrap"," 禁止折行（表格单元格里让数字成行最方便）；",[319,2790,2791,2794],{},[36,2792,2793],{},"white-space: pre-wrap"," 保留用户输入的换行和空格（评论区必需）；",[319,2796,2797,2800],{},[36,2798,2799],{},"overflow-wrap: anywhere"," 让超长单词（长 URL、base64）强制拆断；",[319,2802,2803,2806,2807,2810,2811,2814],{},[36,2804,2805],{},"word-break: break-all"," 允许在任意字符间断行，中英混排有时需要，但纯西文会拆得很丑；",[36,2808,2809],{},"keep-all"," 禁止中文断行（避免句首出现孤立标点时可用 ",[36,2812,2813],{},"line-break: strict","）；",[319,2816,2817,2819,2820,590],{},[36,2818,2693],{}," 需要元素或祖先有正确的 ",[36,2821,2697],{},[15,2823,2824],{},"单行截断是固定的三件套：",[29,2826,2828],{"className":375,"code":2827,"language":377,"meta":34,"style":34},".truncate { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n",[36,2829,2830],{"__ignoreMap":34},[39,2831,2832,2835,2837,2839,2841,2844,2846,2848,2850,2853,2855,2858,2860,2863],{"class":41,"line":42},[39,2833,2834],{"class":60},".truncate",[39,2836,109],{"class":52},[39,2838,2401],{"class":112},[39,2840,116],{"class":52},[39,2842,2843],{"class":112},"nowrap",[39,2845,126],{"class":52},[39,2847,1364],{"class":112},[39,2849,116],{"class":52},[39,2851,2852],{"class":112},"hidden",[39,2854,126],{"class":52},[39,2856,2857],{"class":112},"text-overflow",[39,2859,116],{"class":52},[39,2861,2862],{"class":112},"ellipsis",[39,2864,779],{"class":52},[15,2866,2867],{},"多行截断目前仍是带前缀的写法（但所有主流内核都支持，属事实标准）：",[29,2869,2871],{"className":375,"code":2870,"language":377,"meta":34,"style":34},".clamp-2 { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }\n",[36,2872,2873],{"__ignoreMap":34},[39,2874,2875,2878,2880,2882,2884,2887,2889,2892,2894,2896,2898,2901,2903,2906,2908,2910,2912,2914],{"class":41,"line":42},[39,2876,2877],{"class":60},".clamp-2",[39,2879,109],{"class":52},[39,2881,1350],{"class":112},[39,2883,116],{"class":52},[39,2885,2886],{"class":112},"-webkit-box",[39,2888,126],{"class":52},[39,2890,2891],{"class":112},"-webkit-line-clamp",[39,2893,116],{"class":52},[39,2895,2313],{"class":112},[39,2897,126],{"class":52},[39,2899,2900],{"class":112},"-webkit-box-orient",[39,2902,116],{"class":52},[39,2904,2905],{"class":112},"vertical",[39,2907,126],{"class":52},[39,2909,1364],{"class":112},[39,2911,116],{"class":52},[39,2913,2852],{"class":112},[39,2915,779],{"class":52},[15,2917,2918,2919,2922,2923,2926],{},"被截断的文字仍在 DOM 里：读屏会念全文，用户选中复制也能拿到全文，但",[19,2920,2921],{},"看不见的那部分等于不存在","——关键信息不要靠截断承载，配合 ",[36,2924,2925],{},"title"," 属性或「展开」按钮。",[24,2928,2929],{"id":2929},"中文排版的三个特殊点",[316,2931,2932,2947,2953],{},[319,2933,2934,2390,2937,2940,2941,2390,2944,2946],{},[19,2935,2936],{},"标点悬挂",[36,2938,2939],{},"hanging-punctuation","）与",[19,2942,2943],{},"行首禁止字符",[36,2945,2813],{},"）能消掉中文段落「行首一个逗号」的难看；Safari 支持较好，Chrome 一线在演进，写它属于渐进增强。",[319,2948,2949,2952],{},[19,2950,2951],{},"行高与视觉密度","：汉字是方块字，没有西文的上伸下延，同样行高下中文显得更密。中文段落行高比同字号西文再加大约 0.1–0.2 才舒服。",[319,2954,2955,2963,2964,2967,2968,2390,2970,2972],{},[19,2956,2957,2958,1793,2960,2962],{},"行长用 ",[36,2959,1589],{},[36,2961,1602],{}," 限制","：西文正文一行 45–75 字符最易读，",[36,2965,2966],{},"max-width: 65ch","；中文可以用 ",[36,2969,1611],{},[36,2971,1602],{}," = 一个「水」字的宽度）达到同样效果。",[10,2974,2976],{"id":2975},"八背景边框与阴影视觉层次靠这三样","八、背景、边框与阴影：视觉层次靠这三样",[304,2978],{"height":2979,"src":2980,"title":2981},760,"\u002Ftutorials\u002Fcss\u002Fdemos\u002F08-background-border.html","示例 08：background 各轴、多层背景、圆角与阴影",[24,2983,2985,1416,2988],{"id":2984},"background-image-与-background-size",[36,2986,2987],{},"background-image",[36,2989,2990],{},"background-size",[15,2992,2993,2994,2997,2998,1092,3000,1092,3002,1092,3005,1092,3008,1092,3011,3014],{},"背景的多条轴各自独立：",[36,2995,2996],{},"image","（图或渐变）、",[36,2999,1353],{},[36,3001,2615],{},[36,3003,3004],{},"repeat",[36,3006,3007],{},"origin",[36,3009,3010],{},"clip",[36,3012,3013],{},"attachment","。最常配的是封面图三件套：",[29,3016,3018],{"className":375,"code":3017,"language":377,"meta":34,"style":34},".hero { background-image: url(hero.jpg); background-size: cover; background-position: center; }\n",[36,3019,3020],{"__ignoreMap":34},[39,3021,3022,3025,3027,3029,3031,3034,3036,3039,3042,3044,3046,3049,3051,3053,3055,3057],{"class":41,"line":42},[39,3023,3024],{"class":60},".hero",[39,3026,109],{"class":52},[39,3028,2987],{"class":112},[39,3030,116],{"class":52},[39,3032,3033],{"class":112},"url",[39,3035,173],{"class":52},[39,3037,3038],{"class":1865},"hero.jpg",[39,3040,3041],{"class":52},"); ",[39,3043,2990],{"class":112},[39,3045,116],{"class":52},[39,3047,3048],{"class":112},"cover",[39,3050,126],{"class":52},[39,3052,493],{"class":112},[39,3054,116],{"class":52},[39,3056,2684],{"class":112},[39,3058,779],{"class":52},[15,3060,3061,3063,3064,3067,3068,3070,3071,2357,3074,3077,3078,3081,3082,3085],{},[36,3062,3048],{}," 铺满且不变形，代价是可能裁掉内容；",[36,3065,3066],{},"contain"," 完整显示，代价是可能留白。人物照片做背景时 ",[36,3069,3048],{}," 常把脸裁掉，用 ",[36,3072,3073],{},"object-fit",[36,3075,3076],{},"\u003Cimg>","（第十三章）比背景图更好控制，因为可以用 ",[36,3079,3080],{},"object-position"," 精确指定保留区域，且图片能被 ",[36,3083,3084],{},"alt"," 与懒加载覆盖。",[15,3087,3088,3090,3091,3094],{},[36,3089,493],{}," 的百分比语义容易记错：",[36,3092,3093],{},"50% 50%"," 是「图片的 50% 处对齐容器的 50% 处」，不是「距左 50%」。",[15,3096,3097,1331,3100,3103],{},[36,3098,3099],{},"background-origin",[36,3101,3102],{},"background-clip"," 决定绘制从哪算起、画到哪结束。最常用的是文字裁切：",[29,3105,3107],{"className":375,"code":3106,"language":377,"meta":34,"style":34},".gradient-text {\n  background: linear-gradient(90deg, #0969da, #8250df);\n  -webkit-background-clip: text;\n  background-clip: text;\n  color: transparent;\n}\n",[36,3108,3109,3116,3145,3157,3168,3179],{"__ignoreMap":34},[39,3110,3111,3114],{"class":41,"line":42},[39,3112,3113],{"class":60},".gradient-text",[39,3115,398],{"class":52},[39,3117,3118,3121,3123,3126,3128,3131,3133,3135,3137,3139,3142],{"class":41,"line":49},[39,3119,3120],{"class":112},"  background",[39,3122,116],{"class":52},[39,3124,3125],{"class":112},"linear-gradient",[39,3127,173],{"class":52},[39,3129,3130],{"class":112},"90",[39,3132,1663],{"class":122},[39,3134,392],{"class":52},[39,3136,1698],{"class":112},[39,3138,392],{"class":52},[39,3140,3141],{"class":112},"#8250df",[39,3143,3144],{"class":52},");\n",[39,3146,3147,3150,3152,3155],{"class":41,"line":82},[39,3148,3149],{"class":112},"  -webkit-background-clip",[39,3151,116],{"class":52},[39,3153,3154],{"class":112},"text",[39,3156,427],{"class":52},[39,3158,3159,3162,3164,3166],{"class":41,"line":89},[39,3160,3161],{"class":112},"  background-clip",[39,3163,116],{"class":52},[39,3165,3154],{"class":112},[39,3167,427],{"class":52},[39,3169,3170,3172,3174,3177],{"class":41,"line":95},[39,3171,403],{"class":112},[39,3173,116],{"class":52},[39,3175,3176],{"class":112},"transparent",[39,3178,427],{"class":52},[39,3180,3181],{"class":41,"line":147},[39,3182,432],{"class":52},[15,3184,2390,3185,3188,3189,3192,3193,3195],{},[36,3186,3187],{},"background-clip: text"," 现在主流内核都支持，但",[19,3190,3191],{},"必须保证文字有回退色","，且它会让真实 ",[36,3194,1304],{}," 失效——不要对正文大范围使用，装饰标题为宜。）",[24,3197,3199],{"id":3198},"多层背景先写的在上面","多层背景：先写的在上面",[29,3201,3203],{"className":375,"code":3202,"language":377,"meta":34,"style":34},".card-hero {\n  background-image:\n    radial-gradient(circle at 20% 30%, rgba(255,255,255,.35), transparent 40%),\n    repeating-linear-gradient(90deg, rgba(255,255,255,.12) 0 6px, transparent 6px 14px),\n    linear-gradient(135deg, #0969da, #8250df);\n  background-size: auto, auto, 100% 100%;\n}\n",[36,3204,3205,3212,3220,3280,3336,3358,3384],{"__ignoreMap":34},[39,3206,3207,3210],{"class":41,"line":42},[39,3208,3209],{"class":60},".card-hero",[39,3211,398],{"class":52},[39,3213,3214,3217],{"class":41,"line":49},[39,3215,3216],{"class":112},"  background-image",[39,3218,3219],{"class":52},":\n",[39,3221,3222,3225,3227,3230,3233,3236,3238,3241,3243,3245,3248,3250,3253,3256,3258,3260,3262,3264,3267,3270,3272,3275,3277],{"class":41,"line":82},[39,3223,3224],{"class":112},"    radial-gradient",[39,3226,173],{"class":52},[39,3228,3229],{"class":112},"circle",[39,3231,3232],{"class":122}," at",[39,3234,3235],{"class":112}," 20",[39,3237,1552],{"class":122},[39,3239,3240],{"class":112}," 30",[39,3242,1552],{"class":122},[39,3244,392],{"class":52},[39,3246,3247],{"class":112},"rgba",[39,3249,173],{"class":52},[39,3251,3252],{"class":112},"255",[39,3254,3255],{"class":52},",",[39,3257,3252],{"class":112},[39,3259,3255],{"class":52},[39,3261,3252],{"class":112},[39,3263,3255],{"class":52},[39,3265,3266],{"class":112},".35",[39,3268,3269],{"class":52},"), ",[39,3271,3176],{"class":112},[39,3273,3274],{"class":112}," 40",[39,3276,1552],{"class":122},[39,3278,3279],{"class":52},"),\n",[39,3281,3282,3285,3287,3289,3291,3293,3295,3297,3299,3301,3303,3305,3307,3309,3312,3314,3316,3319,3321,3323,3325,3327,3329,3332,3334],{"class":41,"line":89},[39,3283,3284],{"class":112},"    repeating-linear-gradient",[39,3286,173],{"class":52},[39,3288,3130],{"class":112},[39,3290,1663],{"class":122},[39,3292,392],{"class":52},[39,3294,3247],{"class":112},[39,3296,173],{"class":52},[39,3298,3252],{"class":112},[39,3300,3255],{"class":52},[39,3302,3252],{"class":112},[39,3304,3255],{"class":52},[39,3306,3252],{"class":112},[39,3308,3255],{"class":52},[39,3310,3311],{"class":112},".12",[39,3313,1033],{"class":52},[39,3315,134],{"class":112},[39,3317,3318],{"class":112}," 6",[39,3320,123],{"class":122},[39,3322,392],{"class":52},[39,3324,3176],{"class":112},[39,3326,3318],{"class":112},[39,3328,123],{"class":122},[39,3330,3331],{"class":112}," 14",[39,3333,123],{"class":122},[39,3335,3279],{"class":52},[39,3337,3338,3341,3343,3346,3348,3350,3352,3354,3356],{"class":41,"line":95},[39,3339,3340],{"class":112},"    linear-gradient",[39,3342,173],{"class":52},[39,3344,3345],{"class":112},"135",[39,3347,1663],{"class":122},[39,3349,392],{"class":52},[39,3351,1698],{"class":112},[39,3353,392],{"class":52},[39,3355,3141],{"class":112},[39,3357,3144],{"class":52},[39,3359,3360,3363,3365,3367,3369,3371,3373,3375,3377,3380,3382],{"class":41,"line":147},[39,3361,3362],{"class":112},"  background-size",[39,3364,116],{"class":52},[39,3366,2172],{"class":112},[39,3368,392],{"class":52},[39,3370,2172],{"class":112},[39,3372,392],{"class":52},[39,3374,1995],{"class":112},[39,3376,1552],{"class":122},[39,3378,3379],{"class":112}," 100",[39,3381,1552],{"class":122},[39,3383,427],{"class":52},[39,3385,3386],{"class":41,"line":152},[39,3387,432],{"class":52},[15,3389,3390,3391,3393,3394,3397],{},"逗号分隔的每一层对应一组值；某一层少写的值会往回取该属性的第一个值（所以只写一个 ",[36,3392,493],{}," 时所有层共用它）。层与层之间可以用 ",[36,3395,3396],{},"background-blend-mode"," 指定混合方式。这个「一层高光 + 一层纹理 + 一层底色」的结构，就是不用图片做出有质感封面的标准配方。",[24,3399,3401,3402,3405],{"id":3400},"渐变它是-image不是颜色","渐变：它是 ",[36,3403,3404],{},"\u003Cimage>","，不是颜色",[15,3407,3408,1092,3411,1092,3414,3417],{},[36,3409,3410],{},"linear-gradient()",[36,3412,3413],{},"radial-gradient()",[36,3415,3416],{},"conic-gradient()","（第十九章细讲）都能出现在任何接受图片值的地方。两个高频技巧：",[29,3419,3421],{"className":375,"code":3420,"language":377,"meta":34,"style":34},"\u002F* 硬切色带：同一位置写两次色标 *\u002F\n.progress { background: linear-gradient(90deg, var(--c-primary) 62%, #eaeef2 62%); }\n\u002F* 斜纹\u002F斑马线：repeating-linear-gradient *\u002F\n.zebra { background: repeating-linear-gradient(45deg, #fff8c5 0 10px, transparent 10px 20px); }\n",[36,3422,3423,3428,3476,3481],{"__ignoreMap":34},[39,3424,3425],{"class":41,"line":42},[39,3426,3427],{"class":45},"\u002F* 硬切色带：同一位置写两次色标 *\u002F\n",[39,3429,3430,3433,3435,3437,3439,3441,3443,3445,3447,3449,3452,3454,3456,3458,3461,3463,3465,3468,3471,3473],{"class":41,"line":49},[39,3431,3432],{"class":60},".progress",[39,3434,109],{"class":52},[39,3436,1347],{"class":112},[39,3438,116],{"class":52},[39,3440,3125],{"class":112},[39,3442,173],{"class":52},[39,3444,3130],{"class":112},[39,3446,1663],{"class":122},[39,3448,392],{"class":52},[39,3450,3451],{"class":112},"var",[39,3453,173],{"class":52},[39,3455,1885],{"class":1865},[39,3457,1033],{"class":52},[39,3459,3460],{"class":112},"62",[39,3462,1552],{"class":122},[39,3464,392],{"class":52},[39,3466,3467],{"class":112},"#eaeef2",[39,3469,3470],{"class":112}," 62",[39,3472,1552],{"class":122},[39,3474,3475],{"class":52},"); }\n",[39,3477,3478],{"class":41,"line":82},[39,3479,3480],{"class":45},"\u002F* 斜纹\u002F斑马线：repeating-linear-gradient *\u002F\n",[39,3482,3483,3486,3488,3490,3492,3495,3497,3500,3502,3504,3507,3510,3513,3515,3517,3519,3521,3523,3525,3527],{"class":41,"line":89},[39,3484,3485],{"class":60},".zebra",[39,3487,109],{"class":52},[39,3489,1347],{"class":112},[39,3491,116],{"class":52},[39,3493,3494],{"class":112},"repeating-linear-gradient",[39,3496,173],{"class":52},[39,3498,3499],{"class":112},"45",[39,3501,1663],{"class":122},[39,3503,392],{"class":52},[39,3505,3506],{"class":112},"#fff8c5",[39,3508,3509],{"class":112}," 0",[39,3511,3512],{"class":112}," 10",[39,3514,123],{"class":122},[39,3516,392],{"class":52},[39,3518,3176],{"class":112},[39,3520,3512],{"class":112},[39,3522,123],{"class":122},[39,3524,3235],{"class":112},[39,3526,123],{"class":122},[39,3528,3475],{"class":52},[24,3530,3532],{"id":3531},"边框宽度样式圆角","边框：宽度、样式、圆角",[15,3534,3535,3537,3538,3540],{},[36,3536,1337],{}," 是盒子的一部分（",[36,3539,776],{}," 下从宽度里扣），改宽度会挤动内容。四条规则：",[29,3542,3544],{"className":375,"code":3543,"language":377,"meta":34,"style":34},".card:hover { border-color: #0969da; }        \u002F* 只换色不换宽：避免 hover 时内容跳动 *\u002F\n.card { border: 1px solid #d0d7de; border-left: 4px solid #0969da; }  \u002F* 左侧强调条 *\u002F\n.pill { border-radius: 999px; }               \u002F* 胶囊 *\u002F\n.leaf { border-radius: 12px 4px 12px 4px; }   \u002F* 四角不同：左上 右上 右下 左下 *\u002F\n",[36,3545,3546,3565,3606,3629],{"__ignoreMap":34},[39,3547,3548,3551,3553,3556,3558,3560,3562],{"class":41,"line":42},[39,3549,3550],{"class":60},".card:hover",[39,3552,109],{"class":52},[39,3554,3555],{"class":112},"border-color",[39,3557,116],{"class":52},[39,3559,1698],{"class":112},[39,3561,2323],{"class":52},[39,3563,3564],{"class":45},"\u002F* 只换色不换宽：避免 hover 时内容跳动 *\u002F\n",[39,3566,3567,3569,3571,3573,3575,3577,3579,3581,3584,3586,3589,3591,3594,3596,3598,3601,3603],{"class":41,"line":49},[39,3568,721],{"class":60},[39,3570,109],{"class":52},[39,3572,1337],{"class":112},[39,3574,116],{"class":52},[39,3576,2017],{"class":112},[39,3578,123],{"class":122},[39,3580,2022],{"class":112},[39,3582,3583],{"class":112}," #d0d7de",[39,3585,126],{"class":52},[39,3587,3588],{"class":112},"border-left",[39,3590,116],{"class":52},[39,3592,3593],{"class":112},"4",[39,3595,123],{"class":122},[39,3597,2022],{"class":112},[39,3599,3600],{"class":112}," #0969da",[39,3602,2028],{"class":52},[39,3604,3605],{"class":45},"\u002F* 左侧强调条 *\u002F\n",[39,3607,3608,3611,3613,3616,3618,3621,3623,3626],{"class":41,"line":82},[39,3609,3610],{"class":60},".pill",[39,3612,109],{"class":52},[39,3614,3615],{"class":112},"border-radius",[39,3617,116],{"class":52},[39,3619,3620],{"class":112},"999",[39,3622,123],{"class":122},[39,3624,3625],{"class":52},"; }               ",[39,3627,3628],{"class":45},"\u002F* 胶囊 *\u002F\n",[39,3630,3631,3634,3636,3638,3640,3643,3645,3648,3650,3653,3655,3657,3659,3662],{"class":41,"line":89},[39,3632,3633],{"class":60},".leaf",[39,3635,109],{"class":52},[39,3637,3615],{"class":112},[39,3639,116],{"class":52},[39,3641,3642],{"class":112},"12",[39,3644,123],{"class":122},[39,3646,3647],{"class":112}," 4",[39,3649,123],{"class":122},[39,3651,3652],{"class":112}," 12",[39,3654,123],{"class":122},[39,3656,3647],{"class":112},[39,3658,123],{"class":122},[39,3660,3661],{"class":52},"; }   ",[39,3663,3664],{"class":45},"\u002F* 四角不同：左上 右上 右下 左下 *\u002F\n",[15,3666,3667,3669,3670,3673,3674,3677,3678,590],{},[36,3668,3615],{}," 可以写 ",[36,3671,3672],{},"12px \u002F 24px","（水平\u002F垂直半径不同）做出椭圆角；",[36,3675,3676],{},"border-radius: 50%"," 得到圆（元素必须是正方形，否则是椭圆）。",[19,3679,3680,3681,3684],{},"圆形头像更稳的做法是图片自身保持正方形 + ",[36,3682,3683],{},"object-fit: cover"," + 圆角",[15,3686,3687,3688,3691,3692,3694,3695,590],{},"边框想「不占空间」时用 ",[36,3689,3690],{},"outline","：它在盒子外绘制、不影响布局，但保持矩形（新内核已跟随圆角）。所以焦点环用 ",[36,3693,3690],{},"，装饰用 ",[36,3696,3697],{},"box-shadow",[24,3699,3701,3703],{"id":3700},"box-shadow-的四个可省参数",[36,3702,3697],{}," 的四个可省参数",[15,3705,3706,3707,3710,3711,3714],{},"语法 ",[36,3708,3709],{},"inset? offset-x offset-y blur? spread? color","。模糊半径为 0 时得到硬阴影，做复古\u002F新粗野风格；",[36,3712,3713],{},"inset"," 得到内阴影，可当描边；一个选择器里可以叠多层：",[29,3716,3718],{"className":375,"code":3717,"language":377,"meta":34,"style":34},".tile { box-shadow: inset 0 0 0 1px #d0d7de; }              \u002F* 不占布局的 1px 描边 *\u002F\n.pop  { box-shadow: 0 1px 3px rgba(0,0,0,.12), 0 8px 24px rgba(0,0,0,.14); }  \u002F* 近处锐利 + 远处扩散 *\u002F\n",[36,3719,3720,3752],{"__ignoreMap":34},[39,3721,3722,3725,3727,3729,3731,3733,3735,3737,3739,3742,3744,3746,3749],{"class":41,"line":42},[39,3723,3724],{"class":60},".tile",[39,3726,109],{"class":52},[39,3728,3697],{"class":112},[39,3730,116],{"class":52},[39,3732,3713],{"class":112},[39,3734,3509],{"class":112},[39,3736,3509],{"class":112},[39,3738,3509],{"class":112},[39,3740,3741],{"class":112}," 1",[39,3743,123],{"class":122},[39,3745,3583],{"class":112},[39,3747,3748],{"class":52},"; }              ",[39,3750,3751],{"class":45},"\u002F* 不占布局的 1px 描边 *\u002F\n",[39,3753,3754,3757,3760,3762,3764,3766,3768,3770,3773,3775,3778,3780,3782,3784,3786,3788,3790,3792,3794,3796,3798,3801,3803,3806,3808,3810,3812,3814,3816,3818,3820,3822,3824,3827,3830],{"class":41,"line":49},[39,3755,3756],{"class":60},".pop",[39,3758,3759],{"class":52},"  { ",[39,3761,3697],{"class":112},[39,3763,116],{"class":52},[39,3765,134],{"class":112},[39,3767,3741],{"class":112},[39,3769,123],{"class":122},[39,3771,3772],{"class":112}," 3",[39,3774,123],{"class":122},[39,3776,3777],{"class":112}," rgba",[39,3779,173],{"class":52},[39,3781,134],{"class":112},[39,3783,3255],{"class":52},[39,3785,134],{"class":112},[39,3787,3255],{"class":52},[39,3789,134],{"class":112},[39,3791,3255],{"class":52},[39,3793,3311],{"class":112},[39,3795,3269],{"class":52},[39,3797,134],{"class":112},[39,3799,3800],{"class":112}," 8",[39,3802,123],{"class":122},[39,3804,3805],{"class":112}," 24",[39,3807,123],{"class":122},[39,3809,3777],{"class":112},[39,3811,173],{"class":52},[39,3813,134],{"class":112},[39,3815,3255],{"class":52},[39,3817,134],{"class":112},[39,3819,3255],{"class":52},[39,3821,134],{"class":112},[39,3823,3255],{"class":52},[39,3825,3826],{"class":112},".14",[39,3828,3829],{"class":52},"); }  ",[39,3831,3832],{"class":45},"\u002F* 近处锐利 + 远处扩散 *\u002F\n",[15,3834,3835,3836,3839],{},"两层阴影是「像真的」的关键：只有一层大模糊的阴影看起来发灰，像蒙了雾。同理，暗色主题下阴影几乎看不见，应改用",[19,3837,3838],{},"更亮的边框","表达层次，而不是加深阴影。",[15,3841,3842,3843,3845,3846,3848],{},"性能：",[36,3844,3697],{}," 的动画代价高（要重绘），需要动效时改为「阴影写在伪元素上、动它的 ",[36,3847,1367],{},"」（第十八章）。",[24,3850,3852],{"id":3851},"焦点可见性不是装饰是合规","焦点可见性不是装饰，是合规",[29,3854,3856],{"className":375,"code":3855,"language":377,"meta":34,"style":34},":focus-visible { outline: 3px solid var(--c-primary); outline-offset: 2px; }\n",[36,3857,3858],{"__ignoreMap":34},[39,3859,3860,3862,3864,3866,3868,3870,3872,3874,3877,3879,3881,3883,3886,3888,3890,3892],{"class":41,"line":42},[39,3861,1098],{"class":60},[39,3863,109],{"class":52},[39,3865,3690],{"class":112},[39,3867,116],{"class":52},[39,3869,2743],{"class":112},[39,3871,123],{"class":122},[39,3873,2022],{"class":112},[39,3875,3876],{"class":112}," var",[39,3878,173],{"class":52},[39,3880,1885],{"class":1865},[39,3882,3041],{"class":52},[39,3884,3885],{"class":112},"outline-offset",[39,3887,116],{"class":52},[39,3889,2313],{"class":112},[39,3891,123],{"class":122},[39,3893,779],{"class":52},[15,3895,3896,3899,3900,1416,3902,3904],{},[36,3897,3898],{},"outline: none"," 单独出现就是可访问性缺陷；要么保留默认焦点环，要么换一条足够明显的替代样式。",[36,3901,1098],{},[36,3903,1095],{}," 的区别（只在键盘导航时显示焦点环）见第十五章。",[10,3906,3908,3909,3911,3912,3914],{"id":3907},"九display可见性与-float历史与今天的分工","九、",[36,3910,1350],{},"、可见性与 ",[36,3913,2332],{},"：历史与今天的分工",[304,3916],{"height":3917,"src":3918,"title":3919},720,"\u002Ftutorials\u002Fcss\u002Fdemos\u002F09-display.html","示例 09：块级行内、三种隐藏与 float 清除",[24,3921,3923,918,3926,918,3929],{"id":3922},"block-inline-inline-block",[36,3924,3925],{},"block",[36,3927,3928],{},"inline",[36,3930,3931],{},"inline-block",[15,3933,3934,3936,3937,3940],{},[36,3935,1350],{}," 决定元素参与",[19,3938,3939],{},"哪一种布局算法","，而不是「是否可见」。三种最基础的：",[219,3942,3943,3961],{},[222,3944,3945],{},[225,3946,3947,3949,3952,3955,3958],{},[228,3948],{},[228,3950,3951],{},"常见标签",[228,3953,3954],{},"宽高",[228,3956,3957],{},"垂直 margin",[228,3959,3960],{},"独占一行",[238,3962,3963,3989,4022],{},[225,3964,3965,3969,3980,3983,3986],{},[243,3966,3967],{},[36,3968,3925],{},[243,3970,3971,1223,3973,1223,3975,1223,3978],{},[36,3972,202],{},[36,3974,15],{},[36,3976,3977],{},"section",[36,3979,319],{},[243,3981,3982],{},"生效",[243,3984,3985],{},"生效（会塌陷）",[243,3987,3988],{},"是",[225,3990,3991,3995,4012,4015,4019],{},[243,3992,3993],{},[36,3994,3928],{},[243,3996,3997,1223,3999,1223,4001,1223,4004,1223,4006,1223,4009],{},[36,3998,2724],{},[36,4000,39],{},[36,4002,4003],{},"b",[36,4005,36],{},[36,4007,4008],{},"img",[36,4010,4011],{},"input",[243,4013,4014],{},"无效",[243,4016,4017],{},[19,4018,4014],{},[243,4020,4021],{},"否",[225,4023,4024,4028,4031,4033,4036],{},[243,4025,4026],{},[36,4027,3931],{},[243,4029,4030],{},"按钮、徽章、图标",[243,4032,3982],{},[243,4034,4035],{},"生效（不塌陷）",[243,4037,4021],{},[15,4039,4040,4041,4043,4044,4047],{},"行内元素「设了宽高没反应」是初学者最常见的困惑，正确答案通常是把它变成 ",[36,4042,3931],{},"，或者更好的是——给父级写 ",[36,4045,4046],{},"display: flex","（第十章），让子项自动获得块级尺寸能力。",[15,4049,4050,4052,4053,4056,4057,590],{},[36,4051,3931],{}," 之间那道缝来自 HTML 源码里的换行符被当作空白渲染。",[36,4054,4055],{},"font-size: 0","、写成一行、或者用 Flex 都能消掉，其中",[19,4058,4059],{},"用 Flex 是唯一没有副作用的",[24,4061,4063],{"id":4062},"三种看不见的代价完全不同","三种「看不见」的代价完全不同",[219,4065,4066,4084],{},[222,4067,4068],{},[225,4069,4070,4072,4075,4078,4081],{},[228,4071,602],{},[228,4073,4074],{},"是否占位",[228,4076,4077],{},"是否可交互",[228,4079,4080],{},"读屏能否念到",[228,4082,4083],{},"能否做过渡",[238,4085,4086,4103,4122],{},[225,4087,4088,4093,4096,4098,4101],{},[243,4089,4090],{},[36,4091,4092],{},"display: none",[243,4094,4095],{},"不占",[243,4097,4021],{},[243,4099,4100],{},"否（移出可访问性树）",[243,4102,4021],{},[225,4104,4105,4110,4115,4117,4119],{},[243,4106,4107],{},[36,4108,4109],{},"visibility: hidden",[243,4111,4112],{},[19,4113,4114],{},"占位",[243,4116,4021],{},[243,4118,4021],{},[243,4120,4121],{},"可（离散切换）",[225,4123,4124,4129,4131,4136,4140],{},[243,4125,4126],{},[36,4127,4128],{},"opacity: 0",[243,4130,4114],{},[243,4132,4133,4135],{},[19,4134,3988],{},"（仍可点，注意误触）",[243,4137,4138],{},[19,4139,3988],{},[243,4141,4142],{},"是（首选动画属性）",[15,4144,4145],{},"选择依据：",[434,4147,4148,4235,4241],{},[319,4149,4150,4151,4153,4154,4156,4157,4159,4160],{},"需要淡入淡出 → ",[36,4152,1367],{}," 配 ",[36,4155,1319],{},"，动画结束后再用 ",[36,4158,4109],{}," 彻底移出：",[29,4161,4163],{"className":375,"code":4162,"language":377,"meta":34,"style":34},".popover { opacity: 0; visibility: hidden; transition: opacity .18s ease, visibility .18s; }\n.popover.is-open { opacity: 1; visibility: visible; }\n",[36,4164,4165,4211],{"__ignoreMap":34},[39,4166,4167,4170,4172,4174,4176,4178,4180,4182,4184,4186,4188,4191,4194,4197,4199,4202,4205,4207,4209],{"class":41,"line":42},[39,4168,4169],{"class":60},".popover",[39,4171,109],{"class":52},[39,4173,1367],{"class":112},[39,4175,116],{"class":52},[39,4177,134],{"class":112},[39,4179,126],{"class":52},[39,4181,1319],{"class":112},[39,4183,116],{"class":52},[39,4185,2852],{"class":112},[39,4187,126],{"class":52},[39,4189,4190],{"class":112},"transition",[39,4192,4193],{"class":52},": opacity ",[39,4195,4196],{"class":112},".18",[39,4198,1681],{"class":122},[39,4200,4201],{"class":112}," ease",[39,4203,4204],{"class":52},", visibility ",[39,4206,4196],{"class":112},[39,4208,1681],{"class":122},[39,4210,779],{"class":52},[39,4212,4213,4216,4218,4220,4222,4224,4226,4228,4230,4233],{"class":41,"line":49},[39,4214,4215],{"class":60},".popover.is-open",[39,4217,109],{"class":52},[39,4219,1367],{"class":112},[39,4221,116],{"class":52},[39,4223,2017],{"class":112},[39,4225,126],{"class":52},[39,4227,1319],{"class":112},[39,4229,116],{"class":52},[39,4231,4232],{"class":112},"visible",[39,4234,779],{"class":52},[319,4236,4237,4238,4240],{},"只是不想出现在布局里 → ",[36,4239,4092],{},"，但它会打断过渡；",[319,4242,4243,4246,4247,4250,4251,4254,4255,4257,4258,4260],{},[19,4244,4245],{},"视觉隐藏但对读屏保留","（例如「已选中」状态、图例说明）用 ",[36,4248,4249],{},".sr-only"," 那套绝对定位 + ",[36,4252,4253],{},"clip-path"," 的写法，不要用 ",[36,4256,4128],{},"（会被读出但也可被点击）或 ",[36,4259,4092],{},"（读不到）。",[24,4262,4264,4266],{"id":4263},"float它唯一被设计出来的用途是文字环绕",[36,4265,2332],{},"：它唯一被设计出来的用途是文字环绕",[15,4268,4269,4271,4272,4275,4276,4278],{},[36,4270,2332],{}," 让元素脱离正常流并贴到一侧，后续",[19,4273,4274],{},"行内内容","绕着它排——这是报纸版面需求。今天仍然该用 ",[36,4277,2332],{}," 的只有一种场景：图文环绕（首图在段落左上，文字绕排）。Flex\u002FGrid 做不到绕排。",[15,4280,4281],{},"副作用则是所有人都熟悉的「父容器高度塌陷」：浮动元素不撑高父级，父级后面的内容会被压上来。四种清除方式：",[29,4283,4285],{"className":375,"code":4284,"language":377,"meta":34,"style":34},".clearfix::after { content: \"\"; display: block; clear: both; }  \u002F* 传统 *\u002F\n.parent { overflow: hidden; }    \u002F* 顺带创建 BFC，但会裁掉溢出内容 *\u002F\n.parent { display: flow-root; }  \u002F* 语义最准确、无副作用的现代写法 *\u002F\n",[36,4286,4287,4325,4343],{"__ignoreMap":34},[39,4288,4289,4292,4294,4297,4299,4302,4304,4306,4308,4310,4312,4315,4317,4320,4322],{"class":41,"line":42},[39,4290,4291],{"class":60},".clearfix::after",[39,4293,109],{"class":52},[39,4295,4296],{"class":112},"content",[39,4298,116],{"class":52},[39,4300,4301],{"class":67},"\"\"",[39,4303,126],{"class":52},[39,4305,1350],{"class":112},[39,4307,116],{"class":52},[39,4309,3925],{"class":112},[39,4311,126],{"class":52},[39,4313,4314],{"class":112},"clear",[39,4316,116],{"class":52},[39,4318,4319],{"class":112},"both",[39,4321,2028],{"class":52},[39,4323,4324],{"class":45},"\u002F* 传统 *\u002F\n",[39,4326,4327,4330,4332,4334,4336,4338,4340],{"class":41,"line":49},[39,4328,4329],{"class":60},".parent",[39,4331,109],{"class":52},[39,4333,1364],{"class":112},[39,4335,116],{"class":52},[39,4337,2852],{"class":112},[39,4339,2295],{"class":52},[39,4341,4342],{"class":45},"\u002F* 顺带创建 BFC，但会裁掉溢出内容 *\u002F\n",[39,4344,4345,4347,4349,4351,4353,4356,4358],{"class":41,"line":82},[39,4346,4329],{"class":60},[39,4348,109],{"class":52},[39,4350,1350],{"class":112},[39,4352,116],{"class":52},[39,4354,4355],{"class":112},"flow-root",[39,4357,2028],{"class":52},[39,4359,4360],{"class":45},"\u002F* 语义最准确、无副作用的现代写法 *\u002F\n",[15,4362,4363,4364,4366,4367,4369],{},"两列\u002F三列布局、等高卡片、导航条——这些历史上用 ",[36,4365,2332],{}," + 负 margin 完成的事情，现在都归 Flex 与 Grid。",[36,4368,2332],{}," 还剩一个合理去处是 HTML 邮件（客户端 CSS 支持极差）。",[24,4371,4373],{"id":4372},"bfc-顺手解决边距塌陷","BFC 顺手解决边距塌陷",[15,4375,4376,4377,4379,4380,1092,4382,1092,4385,1092,4388,4390,4391,1092,4393,590],{},"块级格式化上下文（BFC）是一个「内部布局与外界隔离」的盒子。它不影响外部 margin 塌陷，但父容器一旦成为 BFC，子的 ",[36,4378,2210],{}," 就不再穿透。触发条件（任一即可）：",[36,4381,2332],{},[36,4383,4384],{},"position: absolute\u002Ffixed",[36,4386,4387],{},"display: flow-root\u002Finline-block\u002Ftable-cell\u002Fflex\u002Fgrid",[36,4389,1364],{}," 非 ",[36,4392,4232],{},[36,4394,4395],{},"contain: paint",[15,4397,4398,4399,4402],{},"不用背——遇到「margin 莫名跑到父元素上」时，给父容器加 ",[36,4400,4401],{},"display: flow-root"," 即可。",[24,4404,4406,4407,4409],{"id":4405},"其余-display-值速查","其余 ",[36,4408,1350],{}," 值速查",[15,4411,4412,918,4414,4416,4417,1092,4420,4423,4424,918,4426,4429,4430,4433,4434,4437,4438,4440,4441,4444,4445,4448],{},[36,4413,1360],{},[36,4415,1357],{}," 是布局算法（第十、十一章）；",[36,4418,4419],{},"inline-flex",[36,4421,4422],{},"inline-grid"," 是它们的行内版本；",[36,4425,219],{},[36,4427,4428],{},"table-cell"," 仍是不定高内容垂直居中最省事的办法（虽然语义上应该用 Flex）；",[36,4431,4432],{},"contents"," 让盒子自身「消失」、子元素直接参与父级布局，方便但",[19,4435,4436],{},"会丢掉该元素自身的背景与边框，并曾引发展示与可访问性问题","，谨慎使用。列表 ",[36,4439,434],{}," 上写 ",[36,4442,4443],{},"list-style: none"," 会让 Safari\u002FVoiceOver 不再播报列表语义，需要用 ",[36,4446,4447],{},"role=\"list\""," 补回（这条属于 HTML 教程第十七章的可访问性清单）。",[10,4450,4452],{"id":4451},"十flexbox从主轴到实战","十、Flexbox：从主轴到实战",[15,4454,4455,4456,4459,4460,4463],{},"一维布局（一行或一列）交给 Flex。它的模型只有一个概念需要真正理解：",[19,4457,4458],{},"主轴与交叉轴","，而这两根轴会随 ",[36,4461,4462],{},"flex-direction"," 旋转——这也是 Flex 最大的困惑来源。",[304,4465],{"height":2979,"src":4466,"title":4467},"\u002Ftutorials\u002Fcss\u002Fdemos\u002F10a-flex-basics.html","示例 10a：flex-direction、justify\u002Falign 与 gap",[24,4469,4471],{"id":4470},"主轴与交叉轴属性名分两套","主轴与交叉轴：属性名分两套",[15,4473,4474,4477,4478,2612,4481,4477,4484,590,4487,4490,4491,4494],{},[36,4475,4476],{},"justify-*"," 永远管",[19,4479,4480],{},"主轴",[36,4482,4483],{},"align-*",[19,4485,4486],{},"交叉轴",[36,4488,4489],{},"direction: row"," 时 justify 是水平、align 是垂直；改成 ",[36,4492,4493],{},"column"," 后两者表现整体旋转 90°。判断方法只有一个：先确认主轴方向，再决定该写 justify 还是 align。",[15,4496,4497,4499,4500,4503,4504,1092,4507,1092,4509,590,4512,4515,4516,4519],{},[36,4498,4462],{}," 四个值：",[36,4501,4502],{},"row","（默认）、",[36,4505,4506],{},"row-reverse",[36,4508,4493],{},[36,4510,4511],{},"column-reverse",[36,4513,4514],{},"*-reverse"," 只反转",[19,4517,4518],{},"视觉","顺序，DOM 顺序、Tab 焦点顺序、读屏顺序都不变——这会造成「看到的顺序与听到的顺序不一致」，属于可访问性风险，能用 DOM 顺序解决就别反转。",[15,4521,4522,4525,4526,4529,4530,1092,4533,1092,4535,1092,4538,4541,4542,918,4545,4548],{},[36,4523,4524],{},"justify-content"," 的五个常用值只有在容器",[19,4527,4528],{},"有剩余空间","时才有区别：",[36,4531,4532],{},"flex-start",[36,4534,2684],{},[36,4536,4537],{},"flex-end",[36,4539,4540],{},"space-between","（两端贴边）、",[36,4543,4544],{},"space-around",[36,4546,4547],{},"space-evenly","（首尾也留空隙，后者所有空隙严格相等）。",[15,4550,4551,2169,4554,4557,4558,1092,4560,1092,4562,1092,4564,4567,4568,1674,4570,4572,4573,590],{},[36,4552,4553],{},"align-items",[36,4555,4556],{},"stretch","（默认，需子项不设高度）、",[36,4559,4532],{},[36,4561,2684],{},[36,4563,4537],{},[36,4565,4566],{},"baseline","。字号不同的两项并排时 ",[36,4569,4566],{},[36,4571,2684],{}," 更整齐。单个子项要叛逆时用 ",[36,4574,4575],{},"align-self",[24,4577,4579,4581],{"id":4578},"gap容器间距的正确写法",[36,4580,2224],{},"：容器间距的正确写法",[29,4583,4585],{"className":375,"code":4584,"language":377,"meta":34,"style":34},".list { display: flex; gap: 12px 20px; }   \u002F* 行间距 列间距 *\u002F\n",[36,4586,4587],{"__ignoreMap":34},[39,4588,4589,4592,4594,4596,4598,4600,4602,4604,4606,4608,4610,4612,4614,4616],{"class":41,"line":42},[39,4590,4591],{"class":60},".list",[39,4593,109],{"class":52},[39,4595,1350],{"class":112},[39,4597,116],{"class":52},[39,4599,1357],{"class":112},[39,4601,126],{"class":52},[39,4603,2224],{"class":112},[39,4605,116],{"class":52},[39,4607,3642],{"class":112},[39,4609,123],{"class":122},[39,4611,3235],{"class":112},[39,4613,123],{"class":122},[39,4615,3661],{"class":52},[39,4617,4618],{"class":45},"\u002F* 行间距 列间距 *\u002F\n",[15,4620,4621,4623,4624,4627,4628,4631,4632,4635,4636,4639,4640,590],{},[36,4622,2224],{}," 只加在相邻项",[19,4625,4626],{},"之间","，首尾不多出空白，因此从此不需要 ",[36,4629,4630],{},":last-child { margin-right: 0 }","。子项换行时（",[36,4633,4634],{},"flex-wrap","）行与行之间的间距同样由它管。Flex、Grid、多列 ",[36,4637,4638],{},"column-*"," 都支持 ",[36,4641,2224],{},[24,4643,4645,918,4647,918,4650],{"id":4644},"flex-grow-flex-shrink-flex-basis",[36,4646,1651],{},[36,4648,4649],{},"flex-shrink",[36,4651,4652],{},"flex-basis",[304,4654],{"height":4655,"src":4656,"title":4657},800,"\u002Ftutorials\u002Fcss\u002Fdemos\u002F10b-flex-patterns.html","示例 10b：flex 简写、wrap、order 与 min-width 溢出坑",[15,4659,4660],{},"三个属性分别管三件事：",[434,4662,4663,4675,4690],{},[319,4664,4665,4667,4668,4670,4671,4674],{},[36,4666,1651],{},"：容器",[19,4669,4528],{},"时按份数分给谁。分的是剩余空间，不是总宽度——所以两个 ",[36,4672,4673],{},"grow: 1"," 的项如果内容宽度不同，最终宽度也不相等。",[319,4676,4677,4667,4679,4682,4683,4686,4687,590],{},[36,4678,4649],{},[19,4680,4681],{},"不够宽","时谁让步（默认 1）。实际收缩量按 ",[36,4684,4685],{},"shrink × basis"," 加权，不是按数字直接分。不想被压的（图标、关闭按钮、固定侧栏）写 ",[36,4688,4689],{},"flex-shrink: 0",[319,4691,4692,4694,4695,4698,4699,4701],{},[36,4693,4652],{},"：伸缩的",[19,4696,4697],{},"起点尺寸","，优先级高于 ",[36,4700,1340],{},"（在主轴方向上）。",[15,4703,4704,4706],{},[36,4705,1357],{}," 简写有四个必须记住的展开：",[219,4708,4709,4721],{},[222,4710,4711],{},[225,4712,4713,4715,4718],{},[228,4714,602],{},[228,4716,4717],{},"展开",[228,4719,4720],{},"意图",[238,4722,4723,4738,4753,4768],{},[225,4724,4725,4730,4735],{},[243,4726,4727],{},[36,4728,4729],{},"flex: 1",[243,4731,4732],{},[36,4733,4734],{},"1 1 0%",[243,4736,4737],{},"严格等宽（basis 是 0，忽略内容宽度）",[225,4739,4740,4745,4750],{},[243,4741,4742],{},[36,4743,4744],{},"flex: auto",[243,4746,4747],{},[36,4748,4749],{},"1 1 auto",[243,4751,4752],{},"按内容比例分配剩余，能长能缩",[225,4754,4755,4760,4765],{},[243,4756,4757],{},[36,4758,4759],{},"flex: initial",[243,4761,4762],{},[36,4763,4764],{},"0 1 auto",[243,4766,4767],{},"默认值：不生长，但会被压缩",[225,4769,4770,4775,4780],{},[243,4771,4772],{},[36,4773,4774],{},"flex: none",[243,4776,4777],{},[36,4778,4779],{},"0 0 auto",[243,4781,4782],{},"完全固定",[15,4784,4785,4786,4788,4789,4792,4793,4796,4797,4800],{},"「等宽但内容长的那一项溢出」通常是误用了 ",[36,4787,4744],{},"；「固定 240px 侧栏」的正确写法是 ",[36,4790,4791],{},"flex: 0 0 240px","（或 ",[36,4794,4795],{},"flex-basis: 240px; flex-shrink: 0","），只写 ",[36,4798,4799],{},"width: 240px"," 会被压缩。",[24,4802,4804,1416,4806],{"id":4803},"flex-wrap-与-order",[36,4805,4634],{},[36,4807,4808],{},"order",[15,4810,4811,4814,4815,4817],{},[36,4812,4813],{},"flex-wrap: wrap"," 让子项放不下时换行，配合 ",[36,4816,4652],{}," 就是最省事的响应式标签云\u002F工具条：",[29,4819,4821],{"className":375,"code":4820,"language":377,"meta":34,"style":34},".tags { display: flex; flex-wrap: wrap; gap: 8px; }\n",[36,4822,4823],{"__ignoreMap":34},[39,4824,4825,4828,4830,4832,4834,4836,4838,4840,4842,4845,4847,4849,4851,4854,4856],{"class":41,"line":42},[39,4826,4827],{"class":60},".tags",[39,4829,109],{"class":52},[39,4831,1350],{"class":112},[39,4833,116],{"class":52},[39,4835,1357],{"class":112},[39,4837,126],{"class":52},[39,4839,4634],{"class":112},[39,4841,116],{"class":52},[39,4843,4844],{"class":112},"wrap",[39,4846,126],{"class":52},[39,4848,2224],{"class":112},[39,4850,116],{"class":52},[39,4852,4853],{"class":112},"8",[39,4855,123],{"class":122},[39,4857,779],{"class":52},[15,4859,4860,4862,4863,4865],{},[36,4861,4808],{}," 只改视觉顺序（默认 0，可负），典型用途是「DOM 按语义写、移动端把主内容提到前面」。风险与 ",[36,4864,4514],{}," 相同：Tab 顺序跟着 DOM 走，键盘用户会跳来跳去。",[24,4867,4869,4870,4872],{"id":4868},"最经典的坑min-width-不是-0","最经典的坑：",[36,4871,2101],{}," 不是 0",[15,4874,4875,4876,4879,4880,4883,4884,4887],{},"Flex 子项的自动最小尺寸是 ",[36,4877,4878],{},"min-content","，因此",[19,4881,4882],{},"子项无法被压缩到内容宽度以下","。这直接导致「",[36,4885,4886],{},"text-overflow: ellipsis"," 在 flex 子项里不生效」这个高频问题：",[29,4889,4891],{"className":375,"code":4890,"language":377,"meta":34,"style":34},".row { display: flex; }\n.row .side { flex-shrink: 0; }        \u002F* 图标\u002F按钮不让步 *\u002F\n.row .text { min-width: 0; }          \u002F* 关键：允许收缩到内容以下，省略号才生效 *\u002F\n.row .text span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n",[36,4892,4893,4908,4928,4949],{"__ignoreMap":34},[39,4894,4895,4898,4900,4902,4904,4906],{"class":41,"line":42},[39,4896,4897],{"class":60},".row",[39,4899,109],{"class":52},[39,4901,1350],{"class":112},[39,4903,116],{"class":52},[39,4905,1357],{"class":112},[39,4907,779],{"class":52},[39,4909,4910,4912,4915,4917,4919,4921,4923,4925],{"class":41,"line":49},[39,4911,4897],{"class":60},[39,4913,4914],{"class":60}," .side",[39,4916,109],{"class":52},[39,4918,4649],{"class":112},[39,4920,116],{"class":52},[39,4922,134],{"class":112},[39,4924,2323],{"class":52},[39,4926,4927],{"class":45},"\u002F* 图标\u002F按钮不让步 *\u002F\n",[39,4929,4930,4932,4935,4937,4939,4941,4943,4946],{"class":41,"line":82},[39,4931,4897],{"class":60},[39,4933,4934],{"class":60}," .text",[39,4936,109],{"class":52},[39,4938,2101],{"class":112},[39,4940,116],{"class":52},[39,4942,134],{"class":112},[39,4944,4945],{"class":52},"; }          ",[39,4947,4948],{"class":45},"\u002F* 关键：允许收缩到内容以下，省略号才生效 *\u002F\n",[39,4950,4951,4953,4955,4957,4959,4961,4963,4965,4967,4969,4971,4973,4975,4977,4979,4981],{"class":41,"line":89},[39,4952,4897],{"class":60},[39,4954,4934],{"class":60},[39,4956,846],{"class":56},[39,4958,109],{"class":52},[39,4960,2401],{"class":112},[39,4962,116],{"class":52},[39,4964,2843],{"class":112},[39,4966,126],{"class":52},[39,4968,1364],{"class":112},[39,4970,116],{"class":52},[39,4972,2852],{"class":112},[39,4974,126],{"class":52},[39,4976,2857],{"class":112},[39,4978,116],{"class":52},[39,4980,2862],{"class":112},[39,4982,779],{"class":52},[15,4984,4985,4986,4989,4990,4992,4993,1793,4996,4999,5000,5002,5003,5006],{},"同一类问题在嵌套 Flex、Grid 子项（",[36,4987,4988],{},"1fr"," 的下限是 ",[36,4991,2172],{},"）里都会出现，写 ",[36,4994,4995],{},"minmax(0, 1fr)",[36,4997,4998],{},"min-width: 0","。纵向（",[36,5001,4493],{},"）时对应的是 ",[36,5004,5005],{},"min-height: 0","，否则子项会撑破滚动容器。",[24,5008,5009],{"id":5009},"三个高频实战配方",[29,5011,5013],{"className":375,"code":5012,"language":377,"meta":34,"style":34},"\u002F* 居中：完全居中一行 *\u002F  .c { display: flex; align-items: center; justify-content: center; }\n\u002F* 工具条：左标题右操作 *\u002F .bar { display: flex; justify-content: space-between; align-items: center; gap: 12px; }\n\u002F* 吸底页脚 *\u002F            body { min-height: 100svh; display: flex; flex-direction: column; } main { flex: 1; }\n",[36,5014,5015,5049,5093],{"__ignoreMap":34},[39,5016,5017,5020,5023,5025,5027,5029,5031,5033,5035,5037,5039,5041,5043,5045,5047],{"class":41,"line":42},[39,5018,5019],{"class":45},"\u002F* 居中：完全居中一行 *\u002F",[39,5021,5022],{"class":60},"  .c",[39,5024,109],{"class":52},[39,5026,1350],{"class":112},[39,5028,116],{"class":52},[39,5030,1357],{"class":112},[39,5032,126],{"class":52},[39,5034,4553],{"class":112},[39,5036,116],{"class":52},[39,5038,2684],{"class":112},[39,5040,126],{"class":52},[39,5042,4524],{"class":112},[39,5044,116],{"class":52},[39,5046,2684],{"class":112},[39,5048,779],{"class":52},[39,5050,5051,5054,5057,5059,5061,5063,5065,5067,5069,5071,5073,5075,5077,5079,5081,5083,5085,5087,5089,5091],{"class":41,"line":49},[39,5052,5053],{"class":45},"\u002F* 工具条：左标题右操作 *\u002F",[39,5055,5056],{"class":60}," .bar",[39,5058,109],{"class":52},[39,5060,1350],{"class":112},[39,5062,116],{"class":52},[39,5064,1357],{"class":112},[39,5066,126],{"class":52},[39,5068,4524],{"class":112},[39,5070,116],{"class":52},[39,5072,4540],{"class":112},[39,5074,126],{"class":52},[39,5076,4553],{"class":112},[39,5078,116],{"class":52},[39,5080,2684],{"class":112},[39,5082,126],{"class":52},[39,5084,2224],{"class":112},[39,5086,116],{"class":52},[39,5088,3642],{"class":112},[39,5090,123],{"class":122},[39,5092,779],{"class":52},[39,5094,5095,5098,5101,5103,5105,5107,5109,5111,5113,5115,5117,5119,5121,5123,5125,5127,5130,5133,5135,5137,5139,5141],{"class":41,"line":82},[39,5096,5097],{"class":45},"\u002F* 吸底页脚 *\u002F",[39,5099,5100],{"class":56},"            body",[39,5102,109],{"class":52},[39,5104,2378],{"class":112},[39,5106,116],{"class":52},[39,5108,1995],{"class":112},[39,5110,1581],{"class":122},[39,5112,126],{"class":52},[39,5114,1350],{"class":112},[39,5116,116],{"class":52},[39,5118,1357],{"class":112},[39,5120,126],{"class":52},[39,5122,4462],{"class":112},[39,5124,116],{"class":52},[39,5126,4493],{"class":112},[39,5128,5129],{"class":52},"; } ",[39,5131,5132],{"class":56},"main",[39,5134,109],{"class":52},[39,5136,1357],{"class":112},[39,5138,116],{"class":52},[39,5140,2017],{"class":112},[39,5142,779],{"class":52},[15,5144,5145,5146,5149,5150,5153,5154,5156,5157,5159],{},"等高卡片靠 ",[36,5147,5148],{},"align-items: stretch","（Flex 的默认值）自动实现，卡片内部把页脚写成 ",[36,5151,5152],{},"margin-top: auto"," 或给它 ",[36,5155,4729],{}," 吃掉中间空白，就能「底部对齐」。这是 Flex 比 ",[36,5158,2332],{}," 简单得多的地方。",[10,5161,5163],{"id":5162},"十一grid从网格轨道到自适应布局","十一、Grid：从网格轨道到自适应布局",[15,5165,5166],{},"Flex 解决「一行里怎么排」，Grid 解决「整页分成几格」。Grid 是二维的：可以先声明列，再声明行，然后让子项落位。",[304,5168],{"height":5169,"src":5170,"title":5171},820,"\u002Ftutorials\u002Fcss\u002Fdemos\u002F11a-grid-basics.html","示例 11a：轨道、fr、命名区域与对齐",[24,5173,5175,1416,5178],{"id":5174},"grid-template-columns-与-fr",[36,5176,5177],{},"grid-template-columns",[36,5179,1619],{},[29,5181,5183],{"className":375,"code":5182,"language":377,"meta":34,"style":34},".g { display: grid; grid-template-columns: 200px 1fr 1fr; gap: 16px; }\n",[36,5184,5185],{"__ignoreMap":34},[39,5186,5187,5190,5192,5194,5196,5198,5200,5202,5204,5207,5209,5211,5213,5215,5217,5219,5221,5223,5225,5227],{"class":41,"line":42},[39,5188,5189],{"class":60},".g",[39,5191,109],{"class":52},[39,5193,1350],{"class":112},[39,5195,116],{"class":52},[39,5197,1360],{"class":112},[39,5199,126],{"class":52},[39,5201,5177],{"class":112},[39,5203,116],{"class":52},[39,5205,5206],{"class":112},"200",[39,5208,123],{"class":122},[39,5210,3741],{"class":112},[39,5212,1619],{"class":122},[39,5214,3741],{"class":112},[39,5216,1619],{"class":122},[39,5218,126],{"class":52},[39,5220,2224],{"class":112},[39,5222,116],{"class":52},[39,5224,2006],{"class":112},[39,5226,123],{"class":122},[39,5228,779],{"class":52},[15,5230,5231,2480,5233,5236,5237,5239,5240,5243,5244,5247,5248,5250,5251,5254],{},[36,5232,1619],{},[19,5234,5235],{},"剩余空间的等份","，只在 ",[36,5238,1628],{}," 里可用（写成 ",[36,5241,5242],{},"width: 1fr"," 无效）。",[36,5245,5246],{},"2fr 1fr"," 是二比一，但比例算的是扣掉固定轨道与 ",[36,5249,2224],{}," 之后的",[19,5252,5253],{},"剩余","空间，所以固定列宽变化时比例看起来会变，这是正常的。",[15,5256,5257,5260,5261,5264,5265,5268,5269,590],{},[36,5258,5259],{},"repeat(12, 1fr)"," 是简写；",[36,5262,5263],{},"repeat(3, minmax(0, 1fr))"," 是防御性写法（理由见上一章的 min-content 问题）；",[36,5266,5267],{},"grid-template-columns: [侧栏] 240px [主区] 1fr"," 给轨道命名，子项就能写 ",[36,5270,5271],{},"grid-column: 侧栏",[15,5273,5274,5275,5278,5279,5282,5283,5286,5287,5289,5290,2390,5293,918,5295,918,5297,5300],{},"行也一样：",[36,5276,5277],{},"grid-template-rows"," 描述你写明的轨道，超出的部分进入",[19,5280,5281],{},"隐式轨道","，尺寸由 ",[36,5284,5285],{},"grid-auto-rows"," 决定（默认 ",[36,5288,2172],{},"），排布方向由 ",[36,5291,5292],{},"grid-auto-flow",[36,5294,4502],{},[36,5296,4493],{},[36,5298,5299],{},"dense","）控制。",[24,5302,5304],{"id":5303},"命名区域把布局写成-ascii-图","命名区域：把布局写成 ASCII 图",[29,5306,5308],{"className":375,"code":5307,"language":377,"meta":34,"style":34},".page {\n  display: grid;\n  grid-template-columns: 216px minmax(0, 1fr) 232px;\n  grid-template-rows: 48px 1fr 40px;\n  grid-template-areas:\n    \"head head head\"\n    \"nav  main aside\"\n    \"foot foot foot\";\n}\nheader { grid-area: head; }\nmain   { grid-area: main; }\n",[36,5309,5310,5317,5328,5362,5384,5391,5396,5401,5408,5412,5425],{"__ignoreMap":34},[39,5311,5312,5315],{"class":41,"line":42},[39,5313,5314],{"class":60},".page",[39,5316,398],{"class":52},[39,5318,5319,5322,5324,5326],{"class":41,"line":49},[39,5320,5321],{"class":112},"  display",[39,5323,116],{"class":52},[39,5325,1360],{"class":112},[39,5327,427],{"class":52},[39,5329,5330,5333,5335,5338,5340,5343,5345,5347,5349,5351,5353,5355,5358,5360],{"class":41,"line":82},[39,5331,5332],{"class":112},"  grid-template-columns",[39,5334,116],{"class":52},[39,5336,5337],{"class":112},"216",[39,5339,123],{"class":122},[39,5341,5342],{"class":112}," minmax",[39,5344,173],{"class":52},[39,5346,134],{"class":112},[39,5348,392],{"class":52},[39,5350,2017],{"class":112},[39,5352,1619],{"class":122},[39,5354,1033],{"class":52},[39,5356,5357],{"class":112},"232",[39,5359,123],{"class":122},[39,5361,427],{"class":52},[39,5363,5364,5367,5369,5372,5374,5376,5378,5380,5382],{"class":41,"line":89},[39,5365,5366],{"class":112},"  grid-template-rows",[39,5368,116],{"class":52},[39,5370,5371],{"class":112},"48",[39,5373,123],{"class":122},[39,5375,3741],{"class":112},[39,5377,1619],{"class":122},[39,5379,3274],{"class":112},[39,5381,123],{"class":122},[39,5383,427],{"class":52},[39,5385,5386,5389],{"class":41,"line":95},[39,5387,5388],{"class":112},"  grid-template-areas",[39,5390,3219],{"class":52},[39,5392,5393],{"class":41,"line":147},[39,5394,5395],{"class":67},"    \"head head head\"\n",[39,5397,5398],{"class":41,"line":152},[39,5399,5400],{"class":67},"    \"nav  main aside\"\n",[39,5402,5403,5406],{"class":41,"line":158},[39,5404,5405],{"class":67},"    \"foot foot foot\"",[39,5407,427],{"class":52},[39,5409,5410],{"class":41,"line":186},[39,5411,432],{"class":52},[39,5413,5414,5417,5419,5422],{"class":41,"line":191},[39,5415,5416],{"class":56},"header",[39,5418,109],{"class":52},[39,5420,5421],{"class":112},"grid-area",[39,5423,5424],{"class":52},": head; }\n",[39,5426,5427,5429,5432,5434],{"class":41,"line":197},[39,5428,5132],{"class":56},[39,5430,5431],{"class":52},"   { ",[39,5433,5421],{"class":112},[39,5435,5436],{"class":52},": main; }\n",[15,5438,5439,5440,5443,5444,5447],{},"这是 Grid 比 Flex 更适合「整页骨架」的原因：响应式换布局只需重写 ",[36,5441,5442],{},"grid-template-areas"," 那几行，HTML 与子项选择器一行不动。约束是区域名组成的矩形必须完整（不能有 L 形空洞），否则整条声明静默失效；空格子用 ",[36,5445,5446],{},"."," 表示。",[15,5449,5450,5451,5453],{},"本站教程详情页的三栏（左目录 \u002F 正文 \u002F 右目录）就是这个思路——只是用 ",[36,5452,113],{}," 媒体查询把三栏收成单栏，并让左栏变成横向滚动的 chip 条。",[24,5455,5457],{"id":5456},"跨行跨列数的是线","跨行跨列：数的是「线」",[304,5459],{"height":5460,"src":5461,"title":5462},840,"\u002Ftutorials\u002Fcss\u002Fdemos\u002F11b-grid-advanced.html","示例 11b：span、minmax + auto-fit、subgrid 与 12 栏",[15,5464,5465,5466,590,5469,5472,5473,5476],{},"N 条线围成 N-1 个格子，所以「占第 2、3 列」写作 ",[36,5467,5468],{},"grid-column: 2 \u002F 4",[36,5470,5471],{},"-1"," 是最后一条线，",[36,5474,5475],{},"grid-column: 1 \u002F -1"," 就是横跨整行——写整行标题、整行页脚最常用。",[15,5478,5479,5481,5482,5485],{},[36,5480,5421],{}," 的四值顺序是 行开始 \u002F 列开始 \u002F 行结束 \u002F 列结束（与 margin 的顺时针一样）。",[36,5483,5484],{},"grid-column: span 3"," 让自动放置决定起点，比写死线号更适合响应式（断点变化时线号会全部错位）。",[24,5487,5489,5490,2357,5492,918,5495],{"id":5488},"一行代码的响应式minmax-auto-fit-auto-fill","一行代码的响应式：",[36,5491,2338],{},[36,5493,5494],{},"auto-fit",[36,5496,5497],{},"auto-fill",[29,5499,5501],{"className":375,"code":5500,"language":377,"meta":34,"style":34},".cards {\n  display: grid;\n  grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));\n  gap: 16px;\n}\n",[36,5502,5503,5510,5520,5564,5577],{"__ignoreMap":34},[39,5504,5505,5508],{"class":41,"line":42},[39,5506,5507],{"class":60},".cards",[39,5509,398],{"class":52},[39,5511,5512,5514,5516,5518],{"class":41,"line":49},[39,5513,5321],{"class":112},[39,5515,116],{"class":52},[39,5517,1360],{"class":112},[39,5519,427],{"class":52},[39,5521,5522,5524,5526,5528,5530,5532,5534,5537,5539,5542,5544,5547,5549,5551,5553,5555,5557,5559,5561],{"class":41,"line":82},[39,5523,5332],{"class":112},[39,5525,116],{"class":52},[39,5527,3004],{"class":112},[39,5529,173],{"class":52},[39,5531,5494],{"class":112},[39,5533,392],{"class":52},[39,5535,5536],{"class":112},"minmax",[39,5538,173],{"class":52},[39,5540,5541],{"class":112},"min",[39,5543,173],{"class":52},[39,5545,5546],{"class":112},"240",[39,5548,123],{"class":122},[39,5550,392],{"class":52},[39,5552,1995],{"class":112},[39,5554,1552],{"class":122},[39,5556,3269],{"class":52},[39,5558,2017],{"class":112},[39,5560,1619],{"class":122},[39,5562,5563],{"class":52},"));\n",[39,5565,5566,5569,5571,5573,5575],{"class":41,"line":89},[39,5567,5568],{"class":112},"  gap",[39,5570,116],{"class":52},[39,5572,2006],{"class":112},[39,5574,123],{"class":122},[39,5576,427],{"class":52},[39,5578,5579],{"class":41,"line":95},[39,5580,432],{"class":52},[15,5582,5583,1416,5585,5587,5588,676,5591,5593,5594,5596,5597,5599,5600,590],{},[36,5584,5494],{},[36,5586,5497],{}," 的差别只在",[19,5589,5590],{},"末尾有没有空轨道",[36,5592,5497],{}," 保留算出来但没内容的轨道（卡片会显得靠左一小堆），",[36,5595,5494],{}," 把空轨道压成 0，让现存卡片继续伸展铺满。内容少又要「铺满」用 ",[36,5598,5494],{},"；内容多、希望网格始终对齐用 ",[36,5601,5497],{},[15,5603,5604,5607,5608,5611,5612,5614],{},[36,5605,5606],{},"min(240px, 100%)"," 里那个 ",[36,5609,5610],{},"100%"," 是防窄屏横向滚动条的：容器比 240px 还窄时，",[36,5613,5536],{}," 的下限会强行撑破容器。",[15,5616,5617],{},"这套写法能替掉大量「卡片墙 \u002F 图库 \u002F 相关列表」的媒体查询——按内容自身宽度决定断点，比按设备宽度更稳。",[24,5619,5621,5624],{"id":5620},"subgrid让子卡片共享外层轨道",[36,5622,5623],{},"subgrid","：让子卡片共享外层轨道",[29,5626,5628],{"className":375,"code":5627,"language":377,"meta":34,"style":34},".panel { display: grid; grid-row: span 3; grid-template-rows: subgrid; }\n",[36,5629,5630],{"__ignoreMap":34},[39,5631,5632,5635,5637,5639,5641,5643,5645,5648,5651,5653,5655,5657,5659,5661],{"class":41,"line":42},[39,5633,5634],{"class":60},".panel",[39,5636,109],{"class":52},[39,5638,1350],{"class":112},[39,5640,116],{"class":52},[39,5642,1360],{"class":112},[39,5644,126],{"class":52},[39,5646,5647],{"class":112},"grid-row",[39,5649,5650],{"class":52},": span ",[39,5652,2743],{"class":112},[39,5654,126],{"class":52},[39,5656,5277],{"class":112},[39,5658,116],{"class":52},[39,5660,5623],{"class":112},[39,5662,779],{"class":52},[15,5664,5665,5666,5669],{},"跨的格子不再是「自己的轨道」而是复用父网格的，于是每张卡片的标题行、正文行、按钮行严格对齐——以前要每张卡硬写行高才能做到的事。浏览器基线：subgrid 需要较新的内核（Firefox 71 \u002F Chrome 117 \u002F Safari 16 一线），旧内核会退化成普通 Grid 而不破坏内容；上线前请以 caniuse 当前数据为准，并配 ",[36,5667,5668],{},"@supports (grid-template-rows: subgrid)"," 做渐进增强（第二十章）。",[24,5671,5673],{"id":5672},"grid-的三套对齐属性","Grid 的三套对齐属性",[434,5675,5676,5696,5704],{},[319,5677,5678,918,5681,5683,5684,5687,5688,5691,5692,5695],{},[36,5679,5680],{},"justify-items",[36,5682,4553],{},"：格子",[19,5685,5686],{},"内部","内容在水平\u002F垂直的位置；",[36,5689,5690],{},"place-items"," 是两者简写（",[36,5693,5694],{},"display: grid; place-items: center;"," 是最短的完全居中）；",[319,5697,5698,918,5700,5703],{},[36,5699,4524],{},[36,5701,5702],{},"align-content","：整个网格轨道在容器里的分布（有剩余空间才看得出）；",[319,5705,5706,918,5709,5711],{},[36,5707,5708],{},"justify-self",[36,5710,4575],{},"：单个子项叛逆。",[15,5713,5714,5715,1331,5717,5719,5720,5722,5723,5725],{},"Flex 只有 ",[36,5716,4553],{},[36,5718,4524],{}," 这一套；Grid 因为有两个明确的轴向，同名属性含义不同（Grid 的 ",[36,5721,4476],{}," 管水平、",[36,5724,4483],{}," 管垂直）。这正是「同一行 CSS 在两种布局下表现不同」的来源，别混着记。",[24,5727,5728],{"id":5728},"常见坑速查",[219,5730,5731,5741],{},[222,5732,5733],{},[225,5734,5735,5738],{},[228,5736,5737],{},"现象",[228,5739,5740],{},"原因与修法",[238,5742,5743,5761,5778,5791,5808],{},[225,5744,5745,5751],{},[243,5746,5747,5748,5750],{},"设了 ",[36,5749,4988],{}," 仍横向溢出",[243,5752,5753,5755,5756,5758,5759],{},[36,5754,4988],{}," 下限是 ",[36,5757,2172],{},"（= min-content）→ 写 ",[36,5760,4995],{},[225,5762,5763,5770],{},[243,5764,5765,5766,5769],{},"子项 ",[36,5767,5768],{},"height: 100%"," 不生效",[243,5771,1466,5772,5774,5775,5777],{},[36,5773,5277],{}," 或依赖默认的 ",[36,5776,5148],{},"，别猜父高",[225,5779,5780,5783],{},[243,5781,5782],{},"四周空白不对称",[243,5784,5785,5786,2612,5788,5790],{},"四周来自容器 ",[36,5787,1334],{},[36,5789,2224],{}," 只管轨道之间",[225,5792,5793,5798],{},[243,5794,5795,5797],{},[36,5796,5494],{}," 把卡片拉得很宽",[243,5799,5800,5801,5804,5805],{},"给上限：",[36,5802,5803],{},"minmax(240px, 320px)","，外层再 ",[36,5806,5807],{},"justify-content: center",[225,5809,5810,5813],{},[243,5811,5812],{},"子项叠在同一格",[243,5814,5815,5816,5818,5819,5821],{},"忘记 ",[36,5817,2224],{}," 或显式写了相同的 ",[36,5820,5421],{},"（Grid 允许重叠，做叠层时是特性）",[10,5823,5825],{"id":5824},"十二定位与层叠上下文","十二、定位与层叠上下文",[15,5827,5828,5830,5831,5834,5835,5837],{},[36,5829,1353],{}," 决定元素相对",[19,5832,5833],{},"谁","偏移；",[36,5836,1654],{}," 只在同一个层叠上下文内比大小。这两条理解到位，「弹层被挡住」「absolute 跑到左上角」之类的排错时间能砍掉一半。",[304,5839],{"height":5840,"src":5841,"title":5842},880,"\u002Ftutorials\u002Fcss\u002Fdemos\u002F12-position.html","示例 12：五种 position、inset、z-index 与 sticky",[24,5844,5846,5847,5849],{"id":5845},"五种-position-的差别在参考系","五种 ",[36,5848,1353],{}," 的差别在参考系",[219,5851,5852,5867],{},[222,5853,5854],{},[225,5855,5856,5859,5862,5865],{},[228,5857,5858],{},"值",[228,5860,5861],{},"参考系",[228,5863,5864],{},"是否脱离文档流",[228,5866,1514],{},[238,5868,5869,5890,5908,5927,5942],{},[225,5870,5871,5876,5885,5887],{},[243,5872,5873],{},[36,5874,5875],{},"static",[243,5877,5878,5879,1331,5882,5884],{},"—（",[36,5880,5881],{},"top",[36,5883,2678],{}," 完全无效）",[243,5886,4021],{},[243,5888,5889],{},"默认",[225,5891,5892,5897,5900,5905],{},[243,5893,5894],{},[36,5895,5896],{},"relative",[243,5898,5899],{},"自身正常位置",[243,5901,5902,5904],{},[19,5903,4021],{},"（原空间保留）",[243,5906,5907],{},"给子绝对定位当锚点、微调图标",[225,5909,5910,5915,5922,5924],{},[243,5911,5912],{},[36,5913,5914],{},"absolute",[243,5916,5917,5918,5921],{},"最近的",[19,5919,5920],{},"已定位","祖先",[243,5923,3988],{},[243,5925,5926],{},"徽标、下拉、遮罩",[225,5928,5929,5934,5937,5939],{},[243,5930,5931],{},[36,5932,5933],{},"fixed",[243,5935,5936],{},"视口（祖先有 transform 类属性时改变）",[243,5938,3988],{},[243,5940,5941],{},"吸底按钮、对话框",[225,5943,5944,5949,5952,5954],{},[243,5945,5946],{},[36,5947,5948],{},"sticky",[243,5950,5951],{},"滚动容器 + 自身所在区块范围",[243,5953,4021],{},[243,5955,5956],{},"表头、分区标题、吸附导航",[15,5958,5959,5961,5962,5964,5965,5967,5968,5970,5971,5974,5975,2357,5978,5980],{},[36,5960,5948],{}," 失效的三个常见原因：没写 ",[36,5963,5881],{}," 等偏移值、某个祖先设了 ",[36,5966,1364],{},"（改变了滚动容器）、父容器高度不足以容纳滑动范围（吸附不了几像素就跟着走了）。",[36,5969,5881],{}," 在有吸顶页头的站点里通常要写成 ",[36,5972,5973],{},"var(--header-h)","，否则会被盖住——本站左右目录栏正是用 ",[36,5976,5977],{},"position: sticky",[36,5979,5881],{}," 与页头高度联动。",[15,5982,5983,5984,5987,5988,5991],{},"表格 ",[36,5985,5986],{},"\u003Cthead>"," 也能 sticky，但需要 ",[36,5989,5990],{},"border-collapse: separate","（合并边框时边框不跟随）。",[24,5993,5995,5997],{"id":5994},"inset-简写与三种绝对居中",[36,5996,3713],{}," 简写与三种绝对居中",[15,5999,6000,6003,6004,6007,6008,6010],{},[36,6001,6002],{},"inset: 8px 12px auto auto"," 是 ",[36,6005,6006],{},"top right bottom left","，顺序与 ",[36,6009,129],{}," 一致。绝对居中三种写法：",[29,6012,6014],{"className":375,"code":6013,"language":377,"meta":34,"style":34},"\u002F* 一：Grid（推荐） *\u002F .wrap { display: grid; place-items: center; }\n\u002F* 二：transform（不要求父级尺寸） *\u002F .m { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }\n\u002F* 三：inset + auto margin（要求固定宽高） *\u002F .m { position: absolute; inset: 0; margin: auto; width: 120px; height: 40px; }\n",[36,6015,6016,6042,6103],{"__ignoreMap":34},[39,6017,6018,6021,6024,6026,6028,6030,6032,6034,6036,6038,6040],{"class":41,"line":42},[39,6019,6020],{"class":45},"\u002F* 一：Grid（推荐） *\u002F",[39,6022,6023],{"class":60}," .wrap",[39,6025,109],{"class":52},[39,6027,1350],{"class":112},[39,6029,116],{"class":52},[39,6031,1360],{"class":112},[39,6033,126],{"class":52},[39,6035,5690],{"class":112},[39,6037,116],{"class":52},[39,6039,2684],{"class":112},[39,6041,779],{"class":52},[39,6043,6044,6047,6050,6052,6054,6056,6058,6060,6062,6064,6067,6069,6071,6073,6075,6077,6079,6081,6083,6085,6088,6090,6093,6095,6097,6099,6101],{"class":41,"line":49},[39,6045,6046],{"class":45},"\u002F* 二：transform（不要求父级尺寸） *\u002F",[39,6048,6049],{"class":60}," .m",[39,6051,109],{"class":52},[39,6053,1353],{"class":112},[39,6055,116],{"class":52},[39,6057,5914],{"class":112},[39,6059,126],{"class":52},[39,6061,5881],{"class":112},[39,6063,116],{"class":52},[39,6065,6066],{"class":112},"50",[39,6068,1552],{"class":122},[39,6070,126],{"class":52},[39,6072,2678],{"class":112},[39,6074,116],{"class":52},[39,6076,6066],{"class":112},[39,6078,1552],{"class":122},[39,6080,126],{"class":52},[39,6082,1370],{"class":112},[39,6084,116],{"class":52},[39,6086,6087],{"class":112},"translate",[39,6089,173],{"class":52},[39,6091,6092],{"class":112},"-50",[39,6094,1552],{"class":122},[39,6096,392],{"class":52},[39,6098,6092],{"class":112},[39,6100,1552],{"class":122},[39,6102,3475],{"class":52},[39,6104,6105,6108,6110,6112,6114,6116,6118,6120,6122,6124,6126,6128,6130,6132,6134,6136,6138,6140,6143,6145,6147,6149,6151,6154,6156],{"class":41,"line":82},[39,6106,6107],{"class":45},"\u002F* 三：inset + auto margin（要求固定宽高） *\u002F",[39,6109,6049],{"class":60},[39,6111,109],{"class":52},[39,6113,1353],{"class":112},[39,6115,116],{"class":52},[39,6117,5914],{"class":112},[39,6119,126],{"class":52},[39,6121,3713],{"class":112},[39,6123,116],{"class":52},[39,6125,134],{"class":112},[39,6127,126],{"class":52},[39,6129,129],{"class":112},[39,6131,116],{"class":52},[39,6133,2172],{"class":112},[39,6135,126],{"class":52},[39,6137,1340],{"class":112},[39,6139,116],{"class":52},[39,6141,6142],{"class":112},"120",[39,6144,123],{"class":122},[39,6146,126],{"class":52},[39,6148,1343],{"class":112},[39,6150,116],{"class":52},[39,6152,6153],{"class":112},"40",[39,6155,123],{"class":122},[39,6157,779],{"class":52},[15,6159,6160,6163,6164,6167],{},[36,6161,6162],{},"translate(-50%, -50%)"," 的百分比相对",[19,6165,6166],{},"自身","尺寸，这是它能在不知宽高时居中的原因。",[24,6169,6171,6173],{"id":6170},"z-index只在自己的层叠上下文里比大小",[36,6172,1654],{},"：只在自己的层叠上下文里比大小",[15,6175,6176,6178,6179,6182,6183,6186,6187,6190],{},[36,6177,1654],{}," 只在",[19,6180,6181],{},"同一个层叠上下文","内有意义。父级一旦形成层叠上下文，子级写 ",[36,6184,6185],{},"z-index: 9999"," 也出不去——它只能在那个盒子内部称王，外面一个 ",[36,6188,6189],{},"z-index: 2"," 的兄弟就能盖住它。",[15,6192,6193],{},"创建层叠上下文的条件（任一成立）：",[434,6195,6196,6208,6213,6230,6236,6242,6247,6254],{},[319,6197,6198,4390,6200,6202,6203,4390,6205,6207],{},[36,6199,1353],{},[36,6201,5875],{}," 且 ",[36,6204,1654],{},[36,6206,2172],{},"（最常见的来源）；",[319,6209,6210,6212],{},[36,6211,1367],{}," 小于 1；",[319,6214,6215,918,6217,918,6220,918,6223,918,6226,6229],{},[36,6216,1370],{},[36,6218,6219],{},"filter",[36,6221,6222],{},"backdrop-filter",[36,6224,6225],{},"perspective",[36,6227,6228],{},"mask"," 相关属性；",[319,6231,6232,6235],{},[36,6233,6234],{},"will-change"," 里声明了上述任一属性；",[319,6237,6238,6241],{},[36,6239,6240],{},"isolation: isolate","（专门用来创建上下文的属性，语义最干净）；",[319,6243,6244,672],{},[36,6245,6246],{},"position: fixed",[319,6248,6249,6250,4390,6252,672],{},"Flex \u002F Grid 子项的 ",[36,6251,1654],{},[36,6253,2172],{},[319,6255,6256,918,6258,6261],{},[36,6257,4395],{},[36,6259,6260],{},"content-visibility"," 等生成独立绘制层的属性。",[15,6263,6264,6265,6267,6268,6270,6271,1331,6273,6275,6276,1092,6279,2405],{},"排错顺序固定：① 从目标元素往上找",[19,6266,5917],{},"层叠上下文祖先；② 只在这一层里比 ",[36,6269,1654],{},"；③ 需要「跳出去」时，要么去掉祖先的 ",[36,6272,1370],{},[36,6274,6219],{},"，要么把浮层挂到更外层的容器（或用原生 ",[36,6277,6278],{},"\u003Cpopover>",[36,6280,6246],{},[15,6282,6283,6284,6287,6288,6290,6291,6293,6294,6296],{},"数值请建自己的刻度而不是 9999：",[36,6285,6286],{},"10"," 下拉、",[36,6289,6066],{}," 遮罩、",[36,6292,1995],{}," 对话框、",[36,6295,5206],{}," toast。当所有人都写 9999 时，任何一层都赢不了。",[15,6298,6299,6300,6303,6304,2390,6307,6309],{},"顺带区分两件事：",[19,6301,6302],{},"层叠上下文","（本节的几何\u002F属性问题）与",[19,6305,6306],{},"层叠层级",[36,6308,339],{},"，第十六章的声明顺序问题）名字相近，机制完全无关。",[24,6311,6313,6315],{"id":6312},"fixed-会被祖先抢走",[36,6314,5933],{}," 会被祖先「抢走」",[15,6317,6318,6319,918,6321,918,6323,918,6325,918,6327,918,6329,2612,6331,6333,6334,6336],{},"祖先一旦有 ",[36,6320,1370],{},[36,6322,6219],{},[36,6324,6225],{},[36,6326,6222],{},[36,6328,6234],{},[36,6330,4395],{},[36,6332,5933],{}," 的参考系就从视口变成那个祖先，表现为「弹窗跟着页面乱跑」。动画里给祖先加 ",[36,6335,1370],{}," 时尤其容易碰上。",[24,6338,6339],{"id":6339},"实战配方",[29,6341,6343],{"className":375,"code":6342,"language":377,"meta":34,"style":34},"\u002F* 下拉菜单 *\u002F .dd { position: relative; } .dd-menu { position: absolute; top: calc(100% + 4px); left: 0; }\n\u002F* 徽标 *\u002F .badge-wrap { position: relative; } .badge { position: absolute; top: -6px; right: -6px; }\n\u002F* 遮罩 *\u002F .mask { position: fixed; inset: 0; background: rgb(0 0 0 \u002F .5); z-index: 50; }\n",[36,6344,6345,6405,6457],{"__ignoreMap":34},[39,6346,6347,6350,6353,6355,6357,6359,6361,6363,6366,6368,6370,6372,6374,6376,6378,6380,6383,6385,6387,6389,6391,6393,6395,6397,6399,6401,6403],{"class":41,"line":42},[39,6348,6349],{"class":45},"\u002F* 下拉菜单 *\u002F",[39,6351,6352],{"class":60}," .dd",[39,6354,109],{"class":52},[39,6356,1353],{"class":112},[39,6358,116],{"class":52},[39,6360,5896],{"class":112},[39,6362,5129],{"class":52},[39,6364,6365],{"class":60},".dd-menu",[39,6367,109],{"class":52},[39,6369,1353],{"class":112},[39,6371,116],{"class":52},[39,6373,5914],{"class":112},[39,6375,126],{"class":52},[39,6377,5881],{"class":112},[39,6379,116],{"class":52},[39,6381,6382],{"class":112},"calc",[39,6384,173],{"class":52},[39,6386,1995],{"class":112},[39,6388,1552],{"class":122},[39,6390,828],{"class":122},[39,6392,3647],{"class":112},[39,6394,123],{"class":122},[39,6396,3041],{"class":52},[39,6398,2678],{"class":112},[39,6400,116],{"class":52},[39,6402,134],{"class":112},[39,6404,779],{"class":52},[39,6406,6407,6410,6413,6415,6417,6419,6421,6423,6426,6428,6430,6432,6434,6436,6438,6440,6443,6445,6447,6449,6451,6453,6455],{"class":41,"line":49},[39,6408,6409],{"class":45},"\u002F* 徽标 *\u002F",[39,6411,6412],{"class":60}," .badge-wrap",[39,6414,109],{"class":52},[39,6416,1353],{"class":112},[39,6418,116],{"class":52},[39,6420,5896],{"class":112},[39,6422,5129],{"class":52},[39,6424,6425],{"class":60},".badge",[39,6427,109],{"class":52},[39,6429,1353],{"class":112},[39,6431,116],{"class":52},[39,6433,5914],{"class":112},[39,6435,126],{"class":52},[39,6437,5881],{"class":112},[39,6439,116],{"class":52},[39,6441,6442],{"class":112},"-6",[39,6444,123],{"class":122},[39,6446,126],{"class":52},[39,6448,2681],{"class":112},[39,6450,116],{"class":52},[39,6452,6442],{"class":112},[39,6454,123],{"class":122},[39,6456,779],{"class":52},[39,6458,6459,6462,6465,6467,6469,6471,6473,6475,6477,6479,6481,6483,6485,6487,6490,6492,6494,6496,6498,6500,6502,6504,6506,6508,6510],{"class":41,"line":82},[39,6460,6461],{"class":45},"\u002F* 遮罩 *\u002F",[39,6463,6464],{"class":60}," .mask",[39,6466,109],{"class":52},[39,6468,1353],{"class":112},[39,6470,116],{"class":52},[39,6472,5933],{"class":112},[39,6474,126],{"class":52},[39,6476,3713],{"class":112},[39,6478,116],{"class":52},[39,6480,134],{"class":112},[39,6482,126],{"class":52},[39,6484,1347],{"class":112},[39,6486,116],{"class":52},[39,6488,6489],{"class":112},"rgb",[39,6491,173],{"class":52},[39,6493,134],{"class":112},[39,6495,3509],{"class":112},[39,6497,3509],{"class":112},[39,6499,918],{"class":52},[39,6501,1733],{"class":112},[39,6503,3041],{"class":52},[39,6505,1654],{"class":112},[39,6507,116],{"class":52},[39,6509,6066],{"class":112},[39,6511,779],{"class":52},[15,6513,6514,6515,6517,6518,6521,6522,6524,6525,918,6527,6530],{},"下拉要同时写 ",[36,6516,1091],{}," 和 ",[36,6519,6520],{},":focus-within","，否则键盘用户打不开。弹出层靠近视口边缘被裁掉时，用 ",[36,6523,6246],{}," + 定位 API，或直接改用原生 ",[36,6526,6278],{},[36,6528,6529],{},"anchor()","（仍在演进，见 HTML 教程第十三章）。",[10,6532,6534],{"id":6533},"十三响应式与流式排版能连续变化的就别用断点","十三、响应式与流式排版：能连续变化的就别用断点",[15,6536,6537,6538,6541],{},"响应式的目标不是「适配三种手机」，而是",[19,6539,6540],{},"任何宽度都不破","。做法上分两层：能用连续函数解决的（字号、间距、卡片列数）用流式；真的需要结构切换时（三栏变一栏、导航变汉堡）才用媒体查询。",[304,6543],{"height":4655,"src":6544,"title":6545},"\u002Ftutorials\u002Fcss\u002Fdemos\u002F13a-media-queries.html","示例 13a：断点、移动优先与非尺寸类媒体查询",[24,6547,6549],{"id":6548},"断点跟着内容走不跟着机型走","断点跟着内容走，不跟着机型走",[15,6551,6552,6553,6556],{},"把浏览器从 320px 慢慢拉宽，",[19,6554,6555],{},"在哪里变丑就在哪里设断点","——通常 2 到 4 个就够。照抄某个框架的 576\u002F768\u002F992\u002F1200 能用，但那些数字与你的内容无关。",[15,6558,6559,6560,2390,6562,6565],{},"单位建议写 ",[36,6561,1523],{},[36,6563,6564],{},"min-width: 40rem","）而不是 px：用户放大根字号时媒体查询会提前触发，避免文字溢出。",[15,6567,6568],{},"新语法支持范围表达式，读起来更直观：",[29,6570,6572],{"className":375,"code":6571,"language":377,"meta":34,"style":34},"@media (40rem \u003C= width \u003C= 60rem) { … }   \u002F* 等价于 min-width 与 max-width 的 and 组合 *\u002F\n@media (min-width: 60rem), (orientation: landscape) { … }   \u002F* 逗号 = or *\u002F\n",[36,6573,6574,6605],{"__ignoreMap":34},[39,6575,6576,6579,6582,6584,6586,6589,6592,6594,6597,6599,6602],{"class":41,"line":42},[39,6577,6578],{"class":122},"@media",[39,6580,6581],{"class":52}," (",[39,6583,6153],{"class":112},[39,6585,1523],{"class":122},[39,6587,6588],{"class":122}," \u003C=",[39,6590,6591],{"class":112}," width",[39,6593,6588],{"class":122},[39,6595,6596],{"class":112}," 60",[39,6598,1523],{"class":122},[39,6600,6601],{"class":52},") { … }   ",[39,6603,6604],{"class":45},"\u002F* 等价于 min-width 与 max-width 的 and 组合 *\u002F\n",[39,6606,6607,6609,6611,6613,6615,6618,6620,6623,6626,6628,6631,6633],{"class":41,"line":49},[39,6608,6578],{"class":122},[39,6610,6581],{"class":52},[39,6612,2101],{"class":112},[39,6614,116],{"class":52},[39,6616,6617],{"class":112},"60",[39,6619,1523],{"class":122},[39,6621,6622],{"class":52},"), (",[39,6624,6625],{"class":112},"orientation",[39,6627,116],{"class":52},[39,6629,6630],{"class":112},"landscape",[39,6632,6601],{"class":52},[39,6634,6635],{"class":45},"\u002F* 逗号 = or *\u002F\n",[24,6637,6639,6640,6642],{"id":6638},"移动优先默认写窄屏逐级-min-width-增强","移动优先：默认写窄屏，逐级 ",[36,6641,2101],{}," 增强",[29,6644,6646],{"className":375,"code":6645,"language":377,"meta":34,"style":34},".layout { display: grid; gap: 12px; }                        \u002F* 默认：单列，不包在媒体查询里 *\u002F\n@media (min-width: 40rem) { .layout { grid-template-columns: 1fr 1fr; } }\n@media (min-width: 60rem) { .layout { grid-template-columns: 200px 1fr 200px; } }\n",[36,6647,6648,6677,6713],{"__ignoreMap":34},[39,6649,6650,6653,6655,6657,6659,6661,6663,6665,6667,6669,6671,6674],{"class":41,"line":42},[39,6651,6652],{"class":60},".layout",[39,6654,109],{"class":52},[39,6656,1350],{"class":112},[39,6658,116],{"class":52},[39,6660,1360],{"class":112},[39,6662,126],{"class":52},[39,6664,2224],{"class":112},[39,6666,116],{"class":52},[39,6668,3642],{"class":112},[39,6670,123],{"class":122},[39,6672,6673],{"class":52},"; }                        ",[39,6675,6676],{"class":45},"\u002F* 默认：单列，不包在媒体查询里 *\u002F\n",[39,6678,6679,6681,6683,6685,6687,6689,6691,6694,6696,6698,6700,6702,6704,6706,6708,6710],{"class":41,"line":49},[39,6680,6578],{"class":122},[39,6682,6581],{"class":52},[39,6684,2101],{"class":112},[39,6686,116],{"class":52},[39,6688,6153],{"class":112},[39,6690,1523],{"class":122},[39,6692,6693],{"class":52},") { ",[39,6695,6652],{"class":60},[39,6697,109],{"class":52},[39,6699,5177],{"class":112},[39,6701,116],{"class":52},[39,6703,2017],{"class":112},[39,6705,1619],{"class":122},[39,6707,3741],{"class":112},[39,6709,1619],{"class":122},[39,6711,6712],{"class":52},"; } }\n",[39,6714,6715,6717,6719,6721,6723,6725,6727,6729,6731,6733,6735,6737,6739,6741,6743,6745,6748,6750],{"class":41,"line":82},[39,6716,6578],{"class":122},[39,6718,6581],{"class":52},[39,6720,2101],{"class":112},[39,6722,116],{"class":52},[39,6724,6617],{"class":112},[39,6726,1523],{"class":122},[39,6728,6693],{"class":52},[39,6730,6652],{"class":60},[39,6732,109],{"class":52},[39,6734,5177],{"class":112},[39,6736,116],{"class":52},[39,6738,5206],{"class":112},[39,6740,123],{"class":122},[39,6742,3741],{"class":112},[39,6744,1619],{"class":122},[39,6746,6747],{"class":112}," 200",[39,6749,123],{"class":122},[39,6751,6712],{"class":52},[15,6753,6754,6755,6757],{},"好处是基础样式就是最小屏样式，逐级叠加；反过来的桌面优先（默认给桌面、逐级 ",[36,6756,113],{}," 降级）容易漏掉基础样式，也让覆盖关系变成「后写的规则更弱」，与维护成本相悖。",[24,6759,6761],{"id":6760},"不只是宽度这些也属于媒体查询","不只是宽度：这些也属于媒体查询",[219,6763,6764,6774],{},[222,6765,6766],{},[225,6767,6768,6771],{},[228,6769,6770],{},"特性查询",[228,6772,6773],{},"用途",[238,6775,6776,6790,6804,6818,6830,6840,6850],{},[225,6777,6778,6783],{},[243,6779,6780],{},[36,6781,6782],{},"prefers-color-scheme: dark",[243,6784,6785,6786,6789],{},"跟随系统深浅色（本站用 ",[36,6787,6788],{},"html[data-theme]"," 手动切换，见第十四章）",[225,6791,6792,6797],{},[243,6793,6794],{},[36,6795,6796],{},"prefers-reduced-motion: reduce",[243,6798,6799,6800,6803],{},"关闭\u002F收敛动效，",[19,6801,6802],{},"必须提供","（第十八章）",[225,6805,6806,6815],{},[243,6807,6808,6811,6812],{},[36,6809,6810],{},"hover: hover"," and ",[36,6813,6814],{},"pointer: fine",[243,6816,6817],{},"只给鼠标设备写 hover 效果，避免触屏「点一下卡在 hover 态」",[225,6819,6820,6827],{},[243,6821,6822,918,6824],{},[36,6823,6625],{},[36,6825,6826],{},"aspect-ratio",[243,6828,6829],{},"横竖屏、宽高比",[225,6831,6832,6837],{},[243,6833,6834],{},[36,6835,6836],{},"display-mode: standalone",[243,6838,6839],{},"PWA 已安装态",[225,6841,6842,6847],{},[243,6843,6844],{},[36,6845,6846],{},"forced-colors: active",[243,6848,6849],{},"Windows 高对比模式，需要专门准备描边",[225,6851,6852,6857],{},[243,6853,6854],{},[36,6855,6856],{},"print",[243,6858,6859,6860,6863],{},"打印：隐藏导航、展开折叠内容、",[36,6861,6862],{},"break-inside: avoid","、给外链补真实地址",[15,6865,6866],{},"全站级降级写法（可接受，但更好的做法是逐条设计静态替代方案）：",[29,6868,6870],{"className":375,"code":6869,"language":377,"meta":34,"style":34},"@media (prefers-reduced-motion: reduce) {\n  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }\n}\n",[36,6871,6872,6879,6937],{"__ignoreMap":34},[39,6873,6874,6876],{"class":41,"line":42},[39,6875,6578],{"class":122},[39,6877,6878],{"class":52}," (prefers-reduced-motion: reduce) {\n",[39,6880,6881,6884,6886,6888,6890,6892,6894,6896,6898,6901,6903,6906,6908,6911,6913,6916,6918,6920,6922,6924,6927,6929,6931,6933,6935],{"class":41,"line":49},[39,6882,6883],{"class":56},"  *",[39,6885,392],{"class":52},[39,6887,743],{"class":56},[39,6889,759],{"class":60},[39,6891,392],{"class":52},[39,6893,743],{"class":56},[39,6895,766],{"class":60},[39,6897,109],{"class":52},[39,6899,6900],{"class":112},"animation-duration",[39,6902,116],{"class":52},[39,6904,6905],{"class":112},".01",[39,6907,1684],{"class":122},[39,6909,6910],{"class":122}," !important",[39,6912,126],{"class":52},[39,6914,6915],{"class":112},"animation-iteration-count",[39,6917,116],{"class":52},[39,6919,2017],{"class":112},[39,6921,6910],{"class":122},[39,6923,126],{"class":52},[39,6925,6926],{"class":112},"transition-duration",[39,6928,116],{"class":52},[39,6930,6905],{"class":112},[39,6932,1684],{"class":122},[39,6934,6910],{"class":122},[39,6936,779],{"class":52},[39,6938,6939],{"class":41,"line":82},[39,6940,432],{"class":52},[24,6942,6944,6945,918,6948,918,6951],{"id":6943},"流式排版clamp-min-max","流式排版：",[36,6946,6947],{},"clamp()",[36,6949,6950],{},"min()",[36,6952,6953],{},"max()",[304,6955],{"height":2408,"src":6956,"title":6957},"\u002Ftutorials\u002Fcss\u002Fdemos\u002F13b-fluid-type.html","示例 13b：clamp 流式字号、aspect-ratio 与 object-fit",[15,6959,6960,6963],{},[36,6961,6962],{},"clamp(最小, 理想, 最大)"," 让数值随视口连续变化：",[29,6965,6967],{"className":375,"code":6966,"language":377,"meta":34,"style":34},"h1 { font-size: clamp(1.5rem, 1.06rem + 2.2vw, 3rem); }\nsection { padding-block: clamp(24px, 4vw, 64px); gap: clamp(8px, 1.5vw, 20px); }\n",[36,6968,6969,7011],{"__ignoreMap":34},[39,6970,6971,6973,6975,6977,6979,6982,6984,6987,6989,6991,6994,6996,6998,7001,7003,7005,7007,7009],{"class":41,"line":42},[39,6972,389],{"class":56},[39,6974,109],{"class":52},[39,6976,2536],{"class":112},[39,6978,116],{"class":52},[39,6980,6981],{"class":112},"clamp",[39,6983,173],{"class":52},[39,6985,6986],{"class":112},"1.5",[39,6988,1523],{"class":122},[39,6990,392],{"class":52},[39,6992,6993],{"class":112},"1.06",[39,6995,1523],{"class":122},[39,6997,828],{"class":122},[39,6999,7000],{"class":112}," 2.2",[39,7002,1569],{"class":122},[39,7004,392],{"class":52},[39,7006,2743],{"class":112},[39,7008,1523],{"class":122},[39,7010,3475],{"class":52},[39,7012,7013,7015,7017,7020,7022,7024,7026,7029,7031,7033,7035,7037,7039,7042,7044,7046,7048,7050,7052,7054,7056,7058,7060,7062,7064,7066,7069,7071],{"class":41,"line":49},[39,7014,3977],{"class":56},[39,7016,109],{"class":52},[39,7018,7019],{"class":112},"padding-block",[39,7021,116],{"class":52},[39,7023,6981],{"class":112},[39,7025,173],{"class":52},[39,7027,7028],{"class":112},"24",[39,7030,123],{"class":122},[39,7032,392],{"class":52},[39,7034,3593],{"class":112},[39,7036,1569],{"class":122},[39,7038,392],{"class":52},[39,7040,7041],{"class":112},"64",[39,7043,123],{"class":122},[39,7045,3041],{"class":52},[39,7047,2224],{"class":112},[39,7049,116],{"class":52},[39,7051,6981],{"class":112},[39,7053,173],{"class":52},[39,7055,4853],{"class":112},[39,7057,123],{"class":122},[39,7059,392],{"class":52},[39,7061,6986],{"class":112},[39,7063,1569],{"class":122},[39,7065,392],{"class":52},[39,7067,7068],{"class":112},"20",[39,7070,123],{"class":122},[39,7072,3475],{"class":52},[15,7074,7075,7076,7079,7080,7083],{},"理想值必须是",[19,7077,7078],{},"带视口单位的表达式","才会真的流动（只写单值就退化成 min\u002Fmax 选择）。斜率换算：",[36,7081,7082],{},"(最大px − 最小px) ÷ (最大视口px − 最小视口px) × 100","，基准 = 最小px − 斜率 × 最小视口px ÷ 100。",[15,7085,7086,918,7088,7090],{},[36,7087,6950],{},[36,7089,6953],{}," 常一行替掉一条媒体查询：",[29,7092,7094],{"className":375,"code":7093,"language":377,"meta":34,"style":34},".wrap { width: min(100% - 2rem, 68rem); margin-inline: auto; }   \u002F* 上限 68rem，窄屏自动留边距 *\u002F\n.gutter { padding-inline: max(1rem, env(safe-area-inset-left)); }  \u002F* 刘海屏安全区 *\u002F\n",[36,7095,7096,7144],{"__ignoreMap":34},[39,7097,7098,7101,7103,7105,7107,7109,7111,7113,7115,7118,7121,7123,7125,7128,7130,7132,7135,7137,7139,7141],{"class":41,"line":42},[39,7099,7100],{"class":60},".wrap",[39,7102,109],{"class":52},[39,7104,1340],{"class":112},[39,7106,116],{"class":52},[39,7108,5541],{"class":112},[39,7110,173],{"class":52},[39,7112,1995],{"class":112},[39,7114,1552],{"class":122},[39,7116,7117],{"class":122}," -",[39,7119,7120],{"class":112}," 2",[39,7122,1523],{"class":122},[39,7124,392],{"class":52},[39,7126,7127],{"class":112},"68",[39,7129,1523],{"class":122},[39,7131,3041],{"class":52},[39,7133,7134],{"class":112},"margin-inline",[39,7136,116],{"class":52},[39,7138,2172],{"class":112},[39,7140,3661],{"class":52},[39,7142,7143],{"class":45},"\u002F* 上限 68rem，窄屏自动留边距 *\u002F\n",[39,7145,7146,7149,7151,7154,7156,7159,7161,7163,7165,7167,7170,7173],{"class":41,"line":49},[39,7147,7148],{"class":60},".gutter",[39,7150,109],{"class":52},[39,7152,7153],{"class":112},"padding-inline",[39,7155,116],{"class":52},[39,7157,7158],{"class":112},"max",[39,7160,173],{"class":52},[39,7162,2017],{"class":112},[39,7164,1523],{"class":122},[39,7166,392],{"class":52},[39,7168,7169],{"class":1865},"env(safe-area-inset-left",[39,7171,7172],{"class":52},")); }  ",[39,7174,7175],{"class":45},"\u002F* 刘海屏安全区 *\u002F\n",[24,7177,7179,1416,7181,7183],{"id":7178},"aspect-ratio-与-object-fit图片适配的两个正交属性",[36,7180,6826],{},[36,7182,3073],{},"：图片适配的两个正交属性",[15,7185,7186,7189,7190,7193,7194,7196,7197,7200],{},[36,7187,7188],{},"aspect-ratio: 16 \u002F 9"," 让盒子保持比例（取代 ",[36,7191,7192],{},"padding-top: 56.25%"," 那套 hack）；",[36,7195,3073],{}," 让",[19,7198,7199],{},"替换元素的内容","在这个盒子里如何被裁：",[219,7202,7203,7214],{},[222,7204,7205],{},[225,7206,7207,7209,7212],{},[228,7208,5858],{},[228,7210,7211],{},"行为",[228,7213,6773],{},[238,7215,7216,7229,7241,7253,7266],{},[225,7217,7218,7223,7226],{},[243,7219,7220],{},[36,7221,7222],{},"fill",[243,7224,7225],{},"默认，拉伸变形",[243,7227,7228],{},"几乎不用",[225,7230,7231,7235,7238],{},[243,7232,7233],{},[36,7234,3066],{},[243,7236,7237],{},"完整显示，可能留白",[243,7239,7240],{},"logo、截图、图表",[225,7242,7243,7247,7250],{},[243,7244,7245],{},[36,7246,3048],{},[243,7248,7249],{},"铺满并裁切",[243,7251,7252],{},"等尺寸缩略图、卡片封面",[225,7254,7255,7260,7263],{},[243,7256,7257],{},[36,7258,7259],{},"none",[243,7261,7262],{},"原尺寸居中裁",[243,7264,7265],{},"图标",[225,7267,7268,7273,7280],{},[243,7269,7270],{},[36,7271,7272],{},"scale-down",[243,7274,7275,1416,7277,7279],{},[36,7276,7259],{},[36,7278,3066],{}," 中取较小的",[243,7281,7282],{},"大图不放大",[15,7284,7285,7286,7289,7290,7293,7294,7297,7298,2357,7300,7302],{},"配 ",[36,7287,7288],{},"object-position: right top"," 指定裁切时保留哪一侧（人像图常用 ",[36,7291,7292],{},"center 25%"," 保住脸）。",[19,7295,7296],{},"卡片封面的标准配方","就是两者相加：",[36,7299,7188],{},[36,7301,3683],{},"——本站教程入口卡片正是这个写法，所以三张 16:9 的封面 SVG 放进去不会被裁掉内容。",[15,7304,7305,7306,7308,7309,1331,7311,7313,7314,7317],{},"还有一条防布局抖动的规则（CLS）：",[36,7307,3076],{}," 必须写 ",[36,7310,1340],{},[36,7312,1343],{}," 属性，配合 ",[36,7315,7316],{},"img { max-width: 100%; height: auto; }","，比例由 HTML 属性提供、尺寸由 CSS 限制。",[10,7319,7321],{"id":7320},"十四自定义属性与主题化","十四、自定义属性与主题化",[15,7323,7324],{},"自定义属性（custom properties，俗称 CSS 变量）是这门课里回报率最高的一个特性：它同时解决「一处改全站」「组件可配置」「暗色主题」「JS 与 CSS 传值」四件事。",[304,7326],{"height":2979,"src":7327,"title":7328},"\u002Ftutorials\u002Fcss\u002Fdemos\u002F14-custom-props.html","示例 14：变量作用域、暗色主题与 JS 读写",[24,7330,7332],{"id":7331},"声明与读取两条语法","声明与读取：两条语法",[29,7334,7336],{"className":375,"code":7335,"language":377,"meta":34,"style":34},":root { --brand-500: #0969da; --radius-3: 10px; --space-3: 16px; }\n.btn { background: var(--brand-500); border-radius: var(--radius-3); padding: var(--space-3); }\n",[36,7337,7338,7375],{"__ignoreMap":34},[39,7339,7340,7342,7344,7347,7349,7351,7353,7356,7358,7360,7362,7364,7367,7369,7371,7373],{"class":41,"line":42},[39,7341,1860],{"class":60},[39,7343,109],{"class":52},[39,7345,7346],{"class":1865},"--brand-500",[39,7348,116],{"class":52},[39,7350,1698],{"class":112},[39,7352,126],{"class":52},[39,7354,7355],{"class":1865},"--radius-3",[39,7357,116],{"class":52},[39,7359,6286],{"class":112},[39,7361,123],{"class":122},[39,7363,126],{"class":52},[39,7365,7366],{"class":1865},"--space-3",[39,7368,116],{"class":52},[39,7370,2006],{"class":112},[39,7372,123],{"class":122},[39,7374,779],{"class":52},[39,7376,7377,7379,7381,7383,7385,7387,7389,7391,7393,7395,7397,7399,7401,7403,7405,7407,7409,7411,7413,7415],{"class":41,"line":49},[39,7378,1173],{"class":60},[39,7380,109],{"class":52},[39,7382,1347],{"class":112},[39,7384,116],{"class":52},[39,7386,3451],{"class":112},[39,7388,173],{"class":52},[39,7390,7346],{"class":1865},[39,7392,3041],{"class":52},[39,7394,3615],{"class":112},[39,7396,116],{"class":52},[39,7398,3451],{"class":112},[39,7400,173],{"class":52},[39,7402,7355],{"class":1865},[39,7404,3041],{"class":52},[39,7406,1334],{"class":112},[39,7408,116],{"class":52},[39,7410,3451],{"class":112},[39,7412,173],{"class":52},[39,7414,7366],{"class":1865},[39,7416,3475],{"class":52},[15,7418,7419,7420,7423],{},"它与预处理器变量的本质区别：",[19,7421,7422],{},"预处理器变量在编译期被替换成常量，自定义属性在渲染期按元素逐个求解","。所以它是活的——会继承、会被就近覆盖、能被 JS 在运行时改，也能被媒体查询改写。",[24,7425,7426],{"id":7426},"命名与作用域",[15,7428,7429,7430,1092,7433,1092,7436,1092,7438,1092,7440,7443,7444,6517,7447,7450],{},"命名建议「类别-语义-刻度」：",[36,7431,7432],{},"--text-1",[36,7434,7435],{},"--bg-2",[36,7437,7346],{},[36,7439,7366],{},[36,7441,7442],{},"--radius-2","。反面例子是 ",[36,7445,7446],{},"--blue",[36,7448,7449],{},"--big","：这类「描述外观」的名字在换主题时会立刻失效（暗色下那个蓝已经不是你写的蓝），而描述意图的名字只需要改取值。",[15,7452,7453],{},"作用域由声明它的那个选择器决定：",[434,7455,7456,7462,7465,7474],{},[319,7457,7458,7459,7461],{},"写在 ",[36,7460,1860],{}," → 全站可见；",[319,7463,7464],{},"写在组件类上 → 只有该子树可见；",[319,7466,7458,7467,7469,7470,7473],{},[36,7468,6578],{}," 里 → 响应式变量（本站的 ",[36,7471,7472],{},"--header-h"," 就随窄屏变化）；",[319,7475,7476,7477,7479],{},"写在元素的内联 ",[36,7478,100],{}," 上 → 只有这一个元素及其后代可见，也是「使用方定制组件」的入口。",[24,7481,7483,7486],{"id":7482},"var-的回退值与无效行为",[36,7484,7485],{},"var()"," 的回退值与「无效」行为",[29,7488,7490],{"className":375,"code":7489,"language":377,"meta":34,"style":34},".x { color: var(--maybe, blue); }          \u002F* 变量不存在时用回退值 *\u002F\n.y { padding: var(--a, var(--b, 8px)); }   \u002F* 回退可以嵌套 *\u002F\n.z { width: calc(var(--w, 100px) * 2); }   \u002F* 回退参与计算 *\u002F\n",[36,7491,7492,7521,7560],{"__ignoreMap":34},[39,7493,7494,7497,7499,7501,7503,7505,7507,7510,7512,7515,7518],{"class":41,"line":42},[39,7495,7496],{"class":60},".x",[39,7498,109],{"class":52},[39,7500,1304],{"class":112},[39,7502,116],{"class":52},[39,7504,3451],{"class":112},[39,7506,173],{"class":52},[39,7508,7509],{"class":1865},"--maybe",[39,7511,392],{"class":52},[39,7513,7514],{"class":112},"blue",[39,7516,7517],{"class":52},"); }          ",[39,7519,7520],{"class":45},"\u002F* 变量不存在时用回退值 *\u002F\n",[39,7522,7523,7526,7528,7530,7532,7534,7536,7539,7541,7543,7545,7548,7550,7552,7554,7557],{"class":41,"line":49},[39,7524,7525],{"class":60},".y",[39,7527,109],{"class":52},[39,7529,1334],{"class":112},[39,7531,116],{"class":52},[39,7533,3451],{"class":112},[39,7535,173],{"class":52},[39,7537,7538],{"class":1865},"--a",[39,7540,392],{"class":52},[39,7542,3451],{"class":112},[39,7544,173],{"class":52},[39,7546,7547],{"class":1865},"--b",[39,7549,392],{"class":52},[39,7551,4853],{"class":112},[39,7553,123],{"class":122},[39,7555,7556],{"class":52},")); }   ",[39,7558,7559],{"class":45},"\u002F* 回退可以嵌套 *\u002F\n",[39,7561,7562,7565,7567,7569,7571,7573,7575,7577,7579,7582,7584,7586,7588,7590,7592,7594,7597],{"class":41,"line":82},[39,7563,7564],{"class":60},".z",[39,7566,109],{"class":52},[39,7568,1340],{"class":112},[39,7570,116],{"class":52},[39,7572,6382],{"class":112},[39,7574,173],{"class":52},[39,7576,3451],{"class":112},[39,7578,173],{"class":52},[39,7580,7581],{"class":1865},"--w",[39,7583,392],{"class":52},[39,7585,1995],{"class":112},[39,7587,123],{"class":122},[39,7589,1033],{"class":52},[39,7591,743],{"class":122},[39,7593,7120],{"class":112},[39,7595,7596],{"class":52},"); }   ",[39,7598,7599],{"class":45},"\u002F* 回退参与计算 *\u002F\n",[15,7601,7602,7603,7605],{},"变量未定义且没给回退时，整条声明在该元素上被视为",[19,7604,4014],{},"（相当于回到继承值或初始值），不会报错、不会崩溃——所以「变量拼错」的表现是样式静默丢失，排查要看 Computed 面板。",[15,7607,7608,7609,7612],{},"一个必须知道的特例：用 ",[36,7610,7611],{},"@property"," 注册过的变量有「guaranteed-invalid」之外的初值语义，值为空时行为与未定义不同；未注册的变量请一律给回退值。",[24,7614,7616],{"id":7615},"主题化只改变量一条规则都不动","主题化：只改变量，一条规则都不动",[29,7618,7620],{"className":375,"code":7619,"language":377,"meta":34,"style":34},":root { --bg-1: #fff; --text-1: #24292f; --brand-500: #0969da; color-scheme: light; }\nhtml[data-theme='dark'] { --bg-1: #0d1117; --text-1: #e6edf3; --brand-500: #6aa8ff; color-scheme: dark; }\n",[36,7621,7622,7663],{"__ignoreMap":34},[39,7623,7624,7626,7628,7631,7633,7635,7637,7639,7641,7643,7645,7647,7649,7651,7653,7656,7658,7661],{"class":41,"line":42},[39,7625,1860],{"class":60},[39,7627,109],{"class":52},[39,7629,7630],{"class":1865},"--bg-1",[39,7632,116],{"class":52},[39,7634,1871],{"class":112},[39,7636,126],{"class":52},[39,7638,7432],{"class":1865},[39,7640,116],{"class":52},[39,7642,408],{"class":112},[39,7644,126],{"class":52},[39,7646,7346],{"class":1865},[39,7648,116],{"class":52},[39,7650,1698],{"class":112},[39,7652,126],{"class":52},[39,7654,7655],{"class":112},"color-scheme",[39,7657,116],{"class":52},[39,7659,7660],{"class":112},"light",[39,7662,779],{"class":52},[39,7664,7665,7667,7669,7671,7673,7675,7677,7679,7681,7683,7685,7687,7689,7691,7693,7695,7697,7699,7701,7703,7705,7708],{"class":41,"line":49},[39,7666,33],{"class":56},[39,7668,1898],{"class":52},[39,7670,1901],{"class":60},[39,7672,64],{"class":122},[39,7674,1906],{"class":67},[39,7676,1909],{"class":52},[39,7678,7630],{"class":1865},[39,7680,116],{"class":52},[39,7682,1916],{"class":112},[39,7684,126],{"class":52},[39,7686,7432],{"class":1865},[39,7688,116],{"class":52},[39,7690,1925],{"class":112},[39,7692,126],{"class":52},[39,7694,7346],{"class":1865},[39,7696,116],{"class":52},[39,7698,1934],{"class":112},[39,7700,126],{"class":52},[39,7702,7655],{"class":112},[39,7704,116],{"class":52},[39,7706,7707],{"class":112},"dark",[39,7709,779],{"class":52},[15,7711,7712],{},"三件配套事项：",[316,7714,7715,7723,7735],{},[319,7716,7717,7722],{},[19,7718,7719,7720],{},"写 ",[36,7721,7655],{},"：一行让浏览器的默认控件、滚动条、表单底色、高亮色一起切换，成本极低；",[319,7724,7725,7728,7729,7731,7732,7734],{},[19,7726,7727],{},"暗色下品牌色要重新调","：降饱和、提明度（",[36,7730,1698],{}," → ",[36,7733,1934],{},"）。深蓝底配高饱和原色会「发光」刺眼；简单取反（黑底白字）也不是好主题；",[319,7736,7737,7740,7741,7744,7745,7747,7748,7751],{},[19,7738,7739],{},"切换与持久化","：JS 改 ",[36,7742,7743],{},"\u003Chtml>"," 的 ",[36,7746,1901],{},"，把选择存进 ",[36,7749,7750],{},"localStorage","，并在首屏绘制前用一段内联脚本应用，否则会闪一下浅色（FOUC）。",[15,7753,7754,7755,7758,7759,7762],{},"本站就是这一套：",[36,7756,7757],{},"main.css"," 里 ",[36,7760,7761],{},"html[data-theme='dark']"," 覆盖同一批变量名，所有组件的规则完全不用改。",[15,7764,7765,7766,7769,7770,7772],{},"如果你更希望跟随系统而不是手动切换，把选择器换成 ",[36,7767,7768],{},"@media (prefers-color-scheme: dark)","（第十三章）；两者可以共存：先按系统给默认值，再用 ",[36,7771,1901],{}," 让用户覆盖。",[24,7774,7776],{"id":7775},"组件级变量把变量当公共-api","组件级变量：把变量当「公共 API」",[29,7778,7780],{"className":375,"code":7779,"language":377,"meta":34,"style":34},".badge { --badge-bg: #eaeef2; --badge-fg: #24292f; background: var(--badge-bg); color: var(--badge-fg); }\n",[36,7781,7782],{"__ignoreMap":34},[39,7783,7784,7786,7788,7791,7793,7795,7797,7800,7802,7804,7806,7808,7810,7812,7814,7816,7818,7820,7822,7824,7826,7828],{"class":41,"line":42},[39,7785,6425],{"class":60},[39,7787,109],{"class":52},[39,7789,7790],{"class":1865},"--badge-bg",[39,7792,116],{"class":52},[39,7794,3467],{"class":112},[39,7796,126],{"class":52},[39,7798,7799],{"class":1865},"--badge-fg",[39,7801,116],{"class":52},[39,7803,408],{"class":112},[39,7805,126],{"class":52},[39,7807,1347],{"class":112},[39,7809,116],{"class":52},[39,7811,3451],{"class":112},[39,7813,173],{"class":52},[39,7815,7790],{"class":1865},[39,7817,3041],{"class":52},[39,7819,1304],{"class":112},[39,7821,116],{"class":52},[39,7823,3451],{"class":112},[39,7825,173],{"class":52},[39,7827,7799],{"class":1865},[39,7829,3475],{"class":52},[15,7831,7832,7833,7835],{},"使用方不需要新增类名、不需要 ",[36,7834,327],{},"，只要给祖先或自身设变量就能定制：",[29,7837,7839],{"className":31,"code":7838,"language":33,"meta":34,"style":34},"\u003Cspan class=\"badge\" style=\"--badge-bg:#ddf4ff\">定制色\u003C\u002Fspan>\n\u003Cdiv class=\"zone\">\u003C!-- 这里的 badge 全部换色 -->\u003C\u002Fdiv>\n",[36,7840,7841,7869],{"__ignoreMap":34},[39,7842,7843,7845,7847,7850,7852,7855,7857,7859,7862,7865,7867],{"class":41,"line":42},[39,7844,53],{"class":52},[39,7846,39],{"class":56},[39,7848,7849],{"class":60}," class",[39,7851,64],{"class":52},[39,7853,7854],{"class":67},"\"badge\"",[39,7856,205],{"class":60},[39,7858,64],{"class":52},[39,7860,7861],{"class":67},"\"--badge-bg:#ddf4ff\"",[39,7863,7864],{"class":52},">定制色\u003C\u002F",[39,7866,39],{"class":56},[39,7868,79],{"class":52},[39,7870,7871,7873,7875,7877,7879,7882,7884,7887,7890,7892],{"class":41,"line":49},[39,7872,53],{"class":52},[39,7874,202],{"class":56},[39,7876,7849],{"class":60},[39,7878,64],{"class":52},[39,7880,7881],{"class":67},"\"zone\"",[39,7883,866],{"class":52},[39,7885,7886],{"class":45},"\u003C!-- 这里的 badge 全部换色 -->",[39,7888,7889],{"class":52},"\u003C\u002F",[39,7891,202],{"class":56},[39,7893,79],{"class":52},[15,7895,7896],{},"这比「写十个修饰类」更可组合，尤其适合图表、卡片、主题色块一类需要按数据着色的组件。",[24,7898,7899],{"id":7899},"用变量驱动计算与响应式",[29,7901,7903],{"className":375,"code":7902,"language":377,"meta":34,"style":34},".grid-auto { --cols: 3; grid-template-columns: repeat(var(--cols), 1fr); gap: var(--space-3); }\n.bar { --pct: 62%; } .bar > i { width: var(--pct); }\n@media (max-width: 40rem) { :root { --cols: 1; --space-3: 12px; --header-h: 96px; } }\n",[36,7904,7905,7955,7994],{"__ignoreMap":34},[39,7906,7907,7910,7912,7915,7917,7919,7921,7923,7925,7927,7929,7931,7933,7935,7937,7939,7941,7943,7945,7947,7949,7951,7953],{"class":41,"line":42},[39,7908,7909],{"class":60},".grid-auto",[39,7911,109],{"class":52},[39,7913,7914],{"class":1865},"--cols",[39,7916,116],{"class":52},[39,7918,2743],{"class":112},[39,7920,126],{"class":52},[39,7922,5177],{"class":112},[39,7924,116],{"class":52},[39,7926,3004],{"class":112},[39,7928,173],{"class":52},[39,7930,3451],{"class":112},[39,7932,173],{"class":52},[39,7934,7914],{"class":1865},[39,7936,3269],{"class":52},[39,7938,2017],{"class":112},[39,7940,1619],{"class":122},[39,7942,3041],{"class":52},[39,7944,2224],{"class":112},[39,7946,116],{"class":52},[39,7948,3451],{"class":112},[39,7950,173],{"class":52},[39,7952,7366],{"class":1865},[39,7954,3475],{"class":52},[39,7956,7957,7960,7962,7965,7967,7969,7971,7973,7975,7977,7980,7982,7984,7986,7988,7990,7992],{"class":41,"line":49},[39,7958,7959],{"class":60},".bar",[39,7961,109],{"class":52},[39,7963,7964],{"class":1865},"--pct",[39,7966,116],{"class":52},[39,7968,3460],{"class":112},[39,7970,1552],{"class":122},[39,7972,5129],{"class":52},[39,7974,7959],{"class":60},[39,7976,812],{"class":122},[39,7978,7979],{"class":56}," i",[39,7981,109],{"class":52},[39,7983,1340],{"class":112},[39,7985,116],{"class":52},[39,7987,3451],{"class":112},[39,7989,173],{"class":52},[39,7991,7964],{"class":1865},[39,7993,3475],{"class":52},[39,7995,7996,7998,8000,8002,8004,8006,8008,8010,8012,8014,8016,8018,8020,8022,8024,8026,8028,8030,8032,8034,8036,8039,8041],{"class":41,"line":82},[39,7997,6578],{"class":122},[39,7999,6581],{"class":52},[39,8001,113],{"class":112},[39,8003,116],{"class":52},[39,8005,6153],{"class":112},[39,8007,1523],{"class":122},[39,8009,6693],{"class":52},[39,8011,1860],{"class":60},[39,8013,109],{"class":52},[39,8015,7914],{"class":1865},[39,8017,116],{"class":52},[39,8019,2017],{"class":112},[39,8021,126],{"class":52},[39,8023,7366],{"class":1865},[39,8025,116],{"class":52},[39,8027,3642],{"class":112},[39,8029,123],{"class":122},[39,8031,126],{"class":52},[39,8033,7472],{"class":1865},[39,8035,116],{"class":52},[39,8037,8038],{"class":112},"96",[39,8040,123],{"class":122},[39,8042,6712],{"class":52},[15,8044,8045,8046,8048],{},"把「断点决定的一组尺寸」集中成变量，比在每个规则里重复写媒体查询干净得多——这也是本站把吸顶高度写成 ",[36,8047,7472],{}," 并在滚动判定里读取的原因。",[24,8050,8052],{"id":8051},"用-js-读写变量","用 JS 读写变量",[29,8054,8058],{"className":8055,"code":8056,"language":8057,"meta":34,"style":34},"language-js shiki shiki-themes github-dark","getComputedStyle(el).getPropertyValue('--brand-500').trim();   \u002F\u002F 读解析后的值\nel.style.setProperty('--pct', '80%');                          \u002F\u002F 写（只影响这棵子树）\nel.style.removeProperty('--pct');                              \u002F\u002F 删内联值，落回样式表\n","js",[36,8059,8060,8088,8112],{"__ignoreMap":34},[39,8061,8062,8065,8068,8071,8073,8076,8079,8082,8085],{"class":41,"line":42},[39,8063,8064],{"class":60},"getComputedStyle",[39,8066,8067],{"class":52},"(el).",[39,8069,8070],{"class":60},"getPropertyValue",[39,8072,173],{"class":52},[39,8074,8075],{"class":67},"'--brand-500'",[39,8077,8078],{"class":52},").",[39,8080,8081],{"class":60},"trim",[39,8083,8084],{"class":52},"();   ",[39,8086,8087],{"class":45},"\u002F\u002F 读解析后的值\n",[39,8089,8090,8093,8096,8098,8101,8103,8106,8109],{"class":41,"line":49},[39,8091,8092],{"class":52},"el.style.",[39,8094,8095],{"class":60},"setProperty",[39,8097,173],{"class":52},[39,8099,8100],{"class":67},"'--pct'",[39,8102,392],{"class":52},[39,8104,8105],{"class":67},"'80%'",[39,8107,8108],{"class":52},");                          ",[39,8110,8111],{"class":45},"\u002F\u002F 写（只影响这棵子树）\n",[39,8113,8114,8116,8119,8121,8123,8126],{"class":41,"line":82},[39,8115,8092],{"class":52},[39,8117,8118],{"class":60},"removeProperty",[39,8120,173],{"class":52},[39,8122,8100],{"class":67},[39,8124,8125],{"class":52},");                              ",[39,8127,8128],{"class":45},"\u002F\u002F 删内联值，落回样式表\n",[15,8130,8131],{},"反过来「JS 把状态传给 CSS」也用它，比切一堆类名更可组合：",[29,8133,8135],{"className":31,"code":8134,"language":33,"meta":34,"style":34},"\u003Cdiv style=\"--index: 3\">…\u003C\u002Fdiv>\n",[36,8136,8137],{"__ignoreMap":34},[39,8138,8139,8141,8143,8145,8147,8150,8152,8154],{"class":41,"line":42},[39,8140,53],{"class":52},[39,8142,202],{"class":56},[39,8144,205],{"class":60},[39,8146,64],{"class":52},[39,8148,8149],{"class":67},"\"--index: 3\"",[39,8151,213],{"class":52},[39,8153,202],{"class":56},[39,8155,79],{"class":52},[29,8157,8159],{"className":375,"code":8158,"language":377,"meta":34,"style":34},".item { transition-delay: calc(var(--index) * 60ms); }\n",[36,8160,8161],{"__ignoreMap":34},[39,8162,8163,8166,8168,8171,8173,8175,8177,8179,8181,8184,8186,8188,8190,8192],{"class":41,"line":42},[39,8164,8165],{"class":60},".item",[39,8167,109],{"class":52},[39,8169,8170],{"class":112},"transition-delay",[39,8172,116],{"class":52},[39,8174,6382],{"class":112},[39,8176,173],{"class":52},[39,8178,3451],{"class":112},[39,8180,173],{"class":52},[39,8182,8183],{"class":1865},"--index",[39,8185,1033],{"class":52},[39,8187,743],{"class":122},[39,8189,6596],{"class":112},[39,8191,1684],{"class":122},[39,8193,3475],{"class":52},[15,8195,8196,8197,8200,8201,8203],{},"一个限制：",[19,8198,8199],{},"变量本身不能被平滑过渡","（浏览器不知道该按什么规则插值）。要动画变量，先用 ",[36,8202,7611],{}," 注册语法类型：",[29,8205,8207],{"className":375,"code":8206,"language":377,"meta":34,"style":34},"@property --pct { syntax: \"\u003Cpercentage>\"; inherits: false; initial-value: 0%; }\n.bar > i { width: var(--pct); transition: --pct .6s ease; }   \u002F* 现在可动画了 *\u002F\n",[36,8208,8209,8243],{"__ignoreMap":34},[39,8210,8211,8213,8216,8219,8221,8224,8226,8229,8232,8235,8237,8239,8241],{"class":41,"line":42},[39,8212,7611],{"class":122},[39,8214,8215],{"class":52}," --pct { ",[39,8217,8218],{"class":112},"syntax",[39,8220,116],{"class":52},[39,8222,8223],{"class":67},"\"\u003Cpercentage>\"",[39,8225,126],{"class":52},[39,8227,8228],{"class":112},"inherits",[39,8230,8231],{"class":52},": false; ",[39,8233,8234],{"class":112},"initial-value",[39,8236,116],{"class":52},[39,8238,134],{"class":112},[39,8240,1552],{"class":122},[39,8242,779],{"class":52},[39,8244,8245,8247,8249,8251,8253,8255,8257,8259,8261,8263,8265,8267,8270,8273,8275,8277,8279],{"class":41,"line":49},[39,8246,7959],{"class":60},[39,8248,812],{"class":122},[39,8250,7979],{"class":56},[39,8252,109],{"class":52},[39,8254,1340],{"class":112},[39,8256,116],{"class":52},[39,8258,3451],{"class":112},[39,8260,173],{"class":52},[39,8262,7964],{"class":1865},[39,8264,3041],{"class":52},[39,8266,4190],{"class":112},[39,8268,8269],{"class":52},": --pct ",[39,8271,8272],{"class":112},".6",[39,8274,1681],{"class":122},[39,8276,4201],{"class":112},[39,8278,3661],{"class":52},[39,8280,8281],{"class":45},"\u002F* 现在可动画了 *\u002F\n",[15,8283,8284,8285,8287],{},"浏览器基线：",[36,8286,7611],{}," 在 Chrome 85 \u002F Safari 16.4 \u002F Firefox 128 一线支持，属渐进增强能力，不支持时过渡静默退化为跳变，布局不受影响；落笔前请以 caniuse 当前数据为准。",[24,8289,8290],{"id":8290},"常见误区速查",[219,8292,8293,8303],{},[222,8294,8295],{},[225,8296,8297,8300],{},[228,8298,8299],{},"误区",[228,8301,8302],{},"事实",[238,8304,8305,8313,8321,8335,8343],{},[225,8306,8307,8310],{},[243,8308,8309],{},"变量是常量",[243,8311,8312],{},"按元素逐个求解，会继承、会被就近覆盖",[225,8314,8315,8318],{},[243,8316,8317],{},"值只能是颜色或长度",[243,8319,8320],{},"可以是任意 token 序列，包括整串阴影值",[225,8322,8323,8329],{},[243,8324,8325,8328],{},[36,8326,8327],{},"calc()"," 里可以随便乘变量",[243,8330,8331,8332],{},"长度计算要求带单位，纯数字变量要写成 ",[36,8333,8334],{},"calc(var(--n) * 1px)",[225,8336,8337,8340],{},[243,8338,8339],{},"循环引用会崩",[243,8341,8342],{},"相关声明静默无效（不报错，但很难查）",[225,8344,8345,8348],{},[243,8346,8347],{},"变量性能差",[243,8349,8350],{},"解析成本可忽略，别为了「少几个变量」放弃主题化",[10,8352,8354],{"id":8353},"十五现代选择器与函数少写权重少写类名","十五、现代选择器与函数：少写权重、少写类名",[15,8356,8357],{},"这一章的选择器都不是「锦上添花」：它们各自替掉了一类以前必须靠 JS 或靠加权重才能完成的需求。",[304,8359],{"height":8360,"src":8361,"title":8362},900,"\u002Ftutorials\u002Fcss\u002Fdemos\u002F15-modern-selectors.html","示例 15：:is()\u002F:where()\u002F:has()、nth-child of S 与 calc() 混合单位",[24,8364,8366,1416,8368,8370],{"id":8365},"is-与-where把选择器体积收敛掉",[36,8367,1237],{},[36,8369,1233],{},"：把选择器体积收敛掉",[29,8372,8374],{"className":375,"code":8373,"language":377,"meta":34,"style":34},"\u002F* 展开写法：4 个前缀 × 3 个后缀 = 12 条 *\u002F\n.card .title, .card .meta, .panel .title, .panel .meta { … }\n\u002F* 收敛写法：一条 *\u002F\n:is(.card, .panel) :is(.title, .meta) { … }\n",[36,8375,8376,8381,8410,8415],{"__ignoreMap":34},[39,8377,8378],{"class":41,"line":42},[39,8379,8380],{"class":45},"\u002F* 展开写法：4 个前缀 × 3 个后缀 = 12 条 *\u002F\n",[39,8382,8383,8385,8388,8390,8392,8395,8397,8399,8401,8403,8405,8407],{"class":41,"line":49},[39,8384,721],{"class":60},[39,8386,8387],{"class":60}," .title",[39,8389,392],{"class":52},[39,8391,721],{"class":60},[39,8393,8394],{"class":60}," .meta",[39,8396,392],{"class":52},[39,8398,5634],{"class":60},[39,8400,8387],{"class":60},[39,8402,392],{"class":52},[39,8404,5634],{"class":60},[39,8406,8394],{"class":60},[39,8408,8409],{"class":52}," { … }\n",[39,8411,8412],{"class":41,"line":82},[39,8413,8414],{"class":45},"\u002F* 收敛写法：一条 *\u002F\n",[39,8416,8417,8420,8422,8424,8426,8428,8430,8432,8434,8436,8438,8441],{"class":41,"line":89},[39,8418,8419],{"class":60},":is",[39,8421,173],{"class":52},[39,8423,721],{"class":60},[39,8425,392],{"class":52},[39,8427,5634],{"class":60},[39,8429,1033],{"class":52},[39,8431,8419],{"class":60},[39,8433,173],{"class":52},[39,8435,395],{"class":60},[39,8437,392],{"class":52},[39,8439,8440],{"class":60},".meta",[39,8442,8443],{"class":52},") { … }\n",[15,8445,8446],{},"两者唯一的但关键的差别是权重：",[434,8448,8449,8459],{},[319,8450,8451,8454,8455,8458],{},[36,8452,8453],{},":is(A, B)"," 的权重 = 参数里",[19,8456,8457],{},"最高","的那个；",[319,8460,8461,8464,8465,590],{},[36,8462,8463],{},":where(A, B)"," 的权重 = ",[19,8466,134],{},[15,8468,8469,8470,8472,8473,8475,8476,590],{},"所以给组件写「默认样式」时用 ",[36,8471,1233],{},"（使用方随手就能覆盖，不需要 ",[36,8474,327],{},"），需要强调时用 ",[36,8477,1237],{},[15,8479,8480,676,8483,918,8485,8487,8488,8491,8492,8495],{},[19,8481,8482],{},"解析风险必须知道",[36,8484,1237],{},[36,8486,1233],{}," 参数里出现浏览器无法解析的选择器片段，会导致",[19,8489,8490],{},"整条规则被丢弃","。因此不要把「很新的选择器」塞进它们的参数里当降级方案——那种情况请用 ",[36,8493,8494],{},"@supports","（第二十章）或独立规则。",[24,8497,8499,8502],{"id":8498},"has真正的父向选择器",[36,8500,8501],{},":has()","：真正的父向选择器",[29,8504,8506],{"className":375,"code":8505,"language":377,"meta":34,"style":34},".item:has(input:checked) { border-color: #0969da; }   \u002F* 状态上移到容器 *\u002F\n.card:has(img) { padding-top: 0; }                    \u002F* 有封面图的卡片去掉顶部留白 *\u002F\nli:has(> ul) { font-weight: 700; }                    \u002F* 「有子列表」的项加粗 *\u002F\nbody:has(#search:focus) .hero { opacity: .35; }       \u002F* 页面级联动，谨慎使用 *\u002F\n",[36,8507,8508,8533,8556,8583],{"__ignoreMap":34},[39,8509,8510,8513,8515,8517,8520,8522,8524,8526,8528,8530],{"class":41,"line":42},[39,8511,8512],{"class":60},".item:has",[39,8514,173],{"class":52},[39,8516,4011],{"class":56},[39,8518,8519],{"class":60},":checked",[39,8521,6693],{"class":52},[39,8523,3555],{"class":112},[39,8525,116],{"class":52},[39,8527,1698],{"class":112},[39,8529,3661],{"class":52},[39,8531,8532],{"class":45},"\u002F* 状态上移到容器 *\u002F\n",[39,8534,8535,8538,8540,8542,8544,8546,8548,8550,8553],{"class":41,"line":49},[39,8536,8537],{"class":60},".card:has",[39,8539,173],{"class":52},[39,8541,4008],{"class":56},[39,8543,6693],{"class":52},[39,8545,2202],{"class":112},[39,8547,116],{"class":52},[39,8549,134],{"class":112},[39,8551,8552],{"class":52},"; }                    ",[39,8554,8555],{"class":45},"\u002F* 有封面图的卡片去掉顶部留白 *\u002F\n",[39,8557,8558,8560,8563,8565,8567,8570,8572,8574,8576,8578,8580],{"class":41,"line":82},[39,8559,319],{"class":56},[39,8561,8562],{"class":60},":has",[39,8564,173],{"class":52},[39,8566,866],{"class":122},[39,8568,8569],{"class":56}," ul",[39,8571,6693],{"class":52},[39,8573,1659],{"class":112},[39,8575,116],{"class":52},[39,8577,119],{"class":112},[39,8579,8552],{"class":52},[39,8581,8582],{"class":45},"\u002F* 「有子列表」的项加粗 *\u002F\n",[39,8584,8585,8587,8589,8591,8594,8596,8598,8600,8602,8604,8606,8609],{"class":41,"line":89},[39,8586,106],{"class":56},[39,8588,8562],{"class":60},[39,8590,173],{"class":52},[39,8592,8593],{"class":60},"#search:focus",[39,8595,1033],{"class":52},[39,8597,3024],{"class":60},[39,8599,109],{"class":52},[39,8601,1367],{"class":112},[39,8603,116],{"class":52},[39,8605,3266],{"class":112},[39,8607,8608],{"class":52},"; }       ",[39,8610,8611],{"class":45},"\u002F* 页面级联动，谨慎使用 *\u002F\n",[15,8613,8614,8615,8618,8619,8622,8623,8626],{},"参数里还能写相对关系：",[36,8616,8617],{},":has(+ .next)","（紧跟其后的兄弟存在）、",[36,8620,8621],{},":has(~ .x)","（之后同级存在）、",[36,8624,8625],{},":has(> .x)","（直接子元素）。它替掉了「用 JS 监听后给父加类」这一大类代码。",[15,8628,8284,8629,8631,8632,8635],{},[36,8630,8501],{}," 已在 Chrome \u002F Edge \u002F Safari \u002F Firefox 全量支持（Firefox 121 起），属 Baseline 可用。代价是浏览器要在结构变化时重算，避免在超大列表上写高成本的选择器链（例如 ",[36,8633,8634],{},"body:has(...)"," 这种全局查询）。",[24,8637,8639,8641],{"id":8638},"not-的多参数与结构伪类",[36,8640,1181],{}," 的多参数与结构伪类",[29,8643,8645],{"className":375,"code":8644,"language":377,"meta":34,"style":34},".btn:not(.primary, [disabled]) { … }    \u002F* 逗号 = and，等价于串联两个 :not() *\u002F\nli:nth-child(2 of .tag) { … }           \u002F* 「.tag 里的第 2 个」 *\u002F\ntr:nth-child(odd of :is(.tag, .note)) { … }\nli:nth-last-child(-n+2) { … }           \u002F* 倒数两项 *\u002F\n",[36,8646,8647,8669,8685,8705],{"__ignoreMap":34},[39,8648,8649,8652,8654,8657,8660,8663,8666],{"class":41,"line":42},[39,8650,8651],{"class":60},".btn:not",[39,8653,173],{"class":52},[39,8655,8656],{"class":60},".primary",[39,8658,8659],{"class":52},", [",[39,8661,8662],{"class":60},"disabled",[39,8664,8665],{"class":52},"]) { … }    ",[39,8667,8668],{"class":45},"\u002F* 逗号 = and，等价于串联两个 :not() *\u002F\n",[39,8670,8671,8673,8675,8677,8679,8682],{"class":41,"line":49},[39,8672,319],{"class":56},[39,8674,1015],{"class":60},[39,8676,173],{"class":52},[39,8678,2313],{"class":112},[39,8680,8681],{"class":52}," of .tag) { … }           ",[39,8683,8684],{"class":45},"\u002F* 「.tag 里的第 2 个」 *\u002F\n",[39,8686,8687,8689,8691,8693,8696,8699,8702],{"class":41,"line":82},[39,8688,225],{"class":56},[39,8690,1015],{"class":60},[39,8692,173],{"class":52},[39,8694,8695],{"class":112},"odd",[39,8697,8698],{"class":52}," of :is(.tag, .",[39,8700,8701],{"class":112},"n",[39,8703,8704],{"class":52},"ote)) { … }\n",[39,8706,8707,8709,8712,8714,8717,8720],{"class":41,"line":89},[39,8708,319],{"class":56},[39,8710,8711],{"class":60},":nth-last-child",[39,8713,173],{"class":52},[39,8715,8716],{"class":112},"-n+2",[39,8718,8719],{"class":52},") { … }           ",[39,8721,8722],{"class":45},"\u002F* 倒数两项 *\u002F\n",[15,8724,8725,8728],{},[36,8726,8727],{},":nth-child(An+B of S)"," 解决了「跳过表头后再数奇偶」「只在某类元素里数第 N 个」这两个长期只能靠 JS 的需求。浏览器基线：这一形态同样已是主流内核全量支持（Firefox 113 \u002F Chrome 111 一线起）。",[24,8730,8732],{"id":8731},"状态伪类表单与交互的真相来源","状态伪类：表单与交互的真相来源",[219,8734,8735,8746],{},[222,8736,8737],{},[225,8738,8739,8741,8743],{},[228,8740,875],{},[228,8742,898],{},[228,8744,8745],{},"注意",[238,8747,8748,8763,8775,8795,8811,8827,8847,8863,8876],{},[225,8749,8750,8754,8757],{},[243,8751,8752],{},[36,8753,1098],{},[243,8755,8756],{},"只在「该显示焦点环」时命中（键盘导航）",[243,8758,8759,8760,8762],{},"替代 ",[36,8761,3898],{}," 的正确写法，可访问性硬要求",[225,8764,8765,8769,8772],{},[243,8766,8767],{},[36,8768,6520],{},[243,8770,8771],{},"后代任一元素获得焦点时命中容器",[243,8773,8774],{},"搜索框整块高亮的最省方案",[225,8776,8777,8785,8788],{},[243,8778,8779,918,8782],{},[36,8780,8781],{},":valid",[36,8783,8784],{},":invalid",[243,8786,8787],{},"校验状态",[243,8789,8790,8791,8794],{},"未交互的空必填项也算 ",[36,8792,8793],{},"invalid","，直接上红框会吓人",[225,8796,8797,8802,8805],{},[243,8798,8799],{},[36,8800,8801],{},":user-invalid",[243,8803,8804],{},"用户改过之后才判无效",[243,8806,8807,8808,8810],{},"做红框提示比 ",[36,8809,8784],{}," 合适（较新内核）",[225,8812,8813,8818,8821],{},[243,8814,8815],{},[36,8816,8817],{},":placeholder-shown",[243,8819,8820],{},"占位符仍显示",[243,8822,8823,8824,8826],{},"浮动 label 老配方，现在可用 ",[36,8825,8501],{}," 更直观",[225,8828,8829,8839,8842],{},[243,8830,8831,918,8833,918,8836],{},[36,8832,8519],{},[36,8834,8835],{},":default",[36,8837,8838],{},":indeterminate",[243,8840,8841],{},"选中 \u002F 默认选中 \u002F 半选",[243,8843,8844,8846],{},[36,8845,8838],{}," 只能由 JS 设置",[225,8848,8849,8854,8860],{},[243,8850,8851],{},[36,8852,8853],{},":open",[243,8855,8856,8859],{},[36,8857,8858],{},"\u003Cdetails>"," 展开",[243,8861,8862],{},"纯 CSS 折叠面板的状态源（第十七章配合伪元素）",[225,8864,8865,8870,8873],{},[243,8866,8867],{},[36,8868,8869],{},":target",[243,8871,8872],{},"URL 的 hash 指向它",[243,8874,8875],{},"「定位高亮」零成本",[225,8877,8878,8883,8889],{},[243,8879,8880],{},[36,8881,8882],{},":lang(zh)",[243,8884,8885,8886,8888],{},"按 ",[36,8887,2697],{}," 匹配",[243,8890,8891],{},"中英文的标点、字距、字体差异靠它",[24,8893,8895,8897],{"id":8894},"calc-与混合单位",[36,8896,8327],{}," 与混合单位",[29,8899,8901],{"className":375,"code":8900,"language":377,"meta":34,"style":34},".el { width: calc(100% - 2 * 16px); }               \u002F* %、px 必须在 calc 里才能相减 *\u002F\n.el { font-size: calc(1rem + 0.5vw); }\n.el { padding: max(12px, calc((100% - 640px) \u002F 2)); }\n.el { margin-top: calc(var(--n) * 6px); }\n",[36,8902,8903,8940,8967,9012],{"__ignoreMap":34},[39,8904,8905,8908,8910,8912,8914,8916,8918,8920,8922,8924,8926,8929,8932,8934,8937],{"class":41,"line":42},[39,8906,8907],{"class":60},".el",[39,8909,109],{"class":52},[39,8911,1340],{"class":112},[39,8913,116],{"class":52},[39,8915,6382],{"class":112},[39,8917,173],{"class":52},[39,8919,1995],{"class":112},[39,8921,1552],{"class":122},[39,8923,7117],{"class":122},[39,8925,7120],{"class":112},[39,8927,8928],{"class":122}," *",[39,8930,8931],{"class":112}," 16",[39,8933,123],{"class":122},[39,8935,8936],{"class":52},"); }               ",[39,8938,8939],{"class":45},"\u002F* %、px 必须在 calc 里才能相减 *\u002F\n",[39,8941,8942,8944,8946,8948,8950,8952,8954,8956,8958,8960,8963,8965],{"class":41,"line":49},[39,8943,8907],{"class":60},[39,8945,109],{"class":52},[39,8947,2536],{"class":112},[39,8949,116],{"class":52},[39,8951,6382],{"class":112},[39,8953,173],{"class":52},[39,8955,2017],{"class":112},[39,8957,1523],{"class":122},[39,8959,828],{"class":122},[39,8961,8962],{"class":112}," 0.5",[39,8964,1569],{"class":122},[39,8966,3475],{"class":52},[39,8968,8969,8971,8973,8975,8977,8979,8981,8983,8985,8987,8989,8992,8994,8996,8998,9001,9003,9005,9007,9009],{"class":41,"line":82},[39,8970,8907],{"class":60},[39,8972,109],{"class":52},[39,8974,1334],{"class":112},[39,8976,116],{"class":52},[39,8978,7158],{"class":112},[39,8980,173],{"class":52},[39,8982,3642],{"class":112},[39,8984,123],{"class":122},[39,8986,392],{"class":52},[39,8988,6382],{"class":112},[39,8990,8991],{"class":52},"((",[39,8993,1995],{"class":112},[39,8995,1552],{"class":122},[39,8997,7117],{"class":122},[39,8999,9000],{"class":112}," 640",[39,9002,123],{"class":122},[39,9004,1033],{"class":52},[39,9006,1331],{"class":122},[39,9008,7120],{"class":112},[39,9010,9011],{"class":52},")); }\n",[39,9013,9014,9016,9018,9020,9022,9024,9026,9028,9030,9033,9035,9037,9039,9041],{"class":41,"line":89},[39,9015,8907],{"class":60},[39,9017,109],{"class":52},[39,9019,2210],{"class":112},[39,9021,116],{"class":52},[39,9023,6382],{"class":112},[39,9025,173],{"class":52},[39,9027,3451],{"class":112},[39,9029,173],{"class":52},[39,9031,9032],{"class":1865},"--n",[39,9034,1033],{"class":52},[39,9036,743],{"class":122},[39,9038,3318],{"class":112},[39,9040,123],{"class":122},[39,9042,3475],{"class":52},[15,9044,9045,9046,1223,9048,9051,9052,1223,9054,9056,9057,1331,9059,1331,9061,1416,9063,9065],{},"三条规则：",[36,9047,1226],{},[36,9049,9050],{},"-"," 两侧要有空格；",[36,9053,743],{},[36,9055,1331],{}," 的乘除数必须是纯数字（带单位非法）；参与长度计算的变量必须自带单位。",[36,9058,6947],{},[36,9060,6950],{},[36,9062,6953],{},[36,9064,8327],{}," 可以互相嵌套（第十三章的流式排版正是这个组合）。",[15,9067,9068,9069,1092,9072,1092,9075,1092,9078,1092,9081,9084,9085,9087],{},"更新的数学函数（",[36,9070,9071],{},"round()",[36,9073,9074],{},"mod()",[36,9076,9077],{},"sign()",[36,9079,9080],{},"hypot()",[36,9082,9083],{},"tan()"," 等）已进入主流内核，用于生产前请用 ",[36,9086,8494],{}," 检查（第二十章）。",[24,9089,9090],{"id":9090},"什么时候不该用现代选择器",[316,9092,9093,9098,9104,9107],{},[319,9094,1466,9095,9097],{},[36,9096,8501],{}," 表达「需要 JS 才能算出的业务状态」——状态该由 JS 写类，选择器只负责样式；",[319,9099,9100,9101,9103],{},"在 ",[36,9102,1237],{}," 里混入不支持的选择器，整条规则被丢弃；",[319,9105,9106],{},"用超长选择器链去「抢权重」——权重问题回第四章，靠更合理的类名结构解决；",[319,9108,9109,9110,918,9113,9116],{},"依赖 ",[36,9111,9112],{},"@scope",[36,9114,9115],{},":scope"," 做常规样式：仍在演进，生产项目请谨慎。",[10,9118,9120,9121],{"id":9119},"十六原生嵌套与-layer","十六、原生嵌套与 ",[36,9122,339],{},[15,9124,9125,9126,9129,9130,9133],{},"CSS 规范补上了两件 Sass 早就有的能力：",[19,9127,9128],{},"原生嵌套","（少写重复上下文）与",[19,9131,9132],{},"层叠层","（把「谁优先」变成显式声明）。",[304,9135],{"height":5840,"src":9136,"title":9137},"\u002Ftutorials\u002Fcss\u002Fdemos\u002F16-nesting-layers.html","示例 16：& 嵌套、条件规则内嵌、@layer 顺序表",[24,9139,9141,9142,9145],{"id":9140},"原生嵌套-是外层选择器原文","原生嵌套：",[36,9143,9144],{},"&"," 是「外层选择器原文」",[29,9147,9149],{"className":375,"code":9148,"language":377,"meta":34,"style":34},".card {\n  border: 1px solid #d0d7de;\n  &:hover { border-color: #0969da; }        \u002F* → .card:hover *\u002F\n  & .meta { color: #57606a; }               \u002F* → .card .meta *\u002F\n  & + .card { margin-top: 10px; }           \u002F* → .card + .card *\u002F\n  &.is-active { border-width: 2px; }        \u002F* → .card.is-active —— 注意 & 与修饰符之间没有空格 *\u002F\n  &:has(img) { padding-top: 0; }\n  &::after { content: \"\"; }\n}\n.btn { &--primary { … } }                    \u002F* → .btn--primary，BEM 修饰符最短写法 *\u002F\n",[36,9150,9151,9157,9174,9194,9214,9239,9262,9282,9298,9302],{"__ignoreMap":34},[39,9152,9153,9155],{"class":41,"line":42},[39,9154,721],{"class":60},[39,9156,398],{"class":52},[39,9158,9159,9162,9164,9166,9168,9170,9172],{"class":41,"line":49},[39,9160,9161],{"class":112},"  border",[39,9163,116],{"class":52},[39,9165,2017],{"class":112},[39,9167,123],{"class":122},[39,9169,2022],{"class":112},[39,9171,3583],{"class":112},[39,9173,427],{"class":52},[39,9175,9176,9179,9181,9183,9185,9187,9189,9191],{"class":41,"line":82},[39,9177,9178],{"class":56},"  &",[39,9180,1091],{"class":60},[39,9182,109],{"class":52},[39,9184,3555],{"class":112},[39,9186,116],{"class":52},[39,9188,1698],{"class":112},[39,9190,2323],{"class":52},[39,9192,9193],{"class":45},"\u002F* → .card:hover *\u002F\n",[39,9195,9196,9198,9200,9202,9204,9206,9209,9211],{"class":41,"line":89},[39,9197,9178],{"class":56},[39,9199,8394],{"class":60},[39,9201,109],{"class":52},[39,9203,1304],{"class":112},[39,9205,116],{"class":52},[39,9207,9208],{"class":112},"#57606a",[39,9210,3625],{"class":52},[39,9212,9213],{"class":45},"\u002F* → .card .meta *\u002F\n",[39,9215,9216,9218,9220,9223,9225,9227,9229,9231,9233,9236],{"class":41,"line":95},[39,9217,9178],{"class":56},[39,9219,828],{"class":122},[39,9221,9222],{"class":60}," .card",[39,9224,109],{"class":52},[39,9226,2210],{"class":112},[39,9228,116],{"class":52},[39,9230,6286],{"class":112},[39,9232,123],{"class":122},[39,9234,9235],{"class":52},"; }           ",[39,9237,9238],{"class":45},"\u002F* → .card + .card *\u002F\n",[39,9240,9241,9243,9246,9248,9251,9253,9255,9257,9259],{"class":41,"line":147},[39,9242,9178],{"class":56},[39,9244,9245],{"class":60},".is-active",[39,9247,109],{"class":52},[39,9249,9250],{"class":112},"border-width",[39,9252,116],{"class":52},[39,9254,2313],{"class":112},[39,9256,123],{"class":122},[39,9258,2323],{"class":52},[39,9260,9261],{"class":45},"\u002F* → .card.is-active —— 注意 & 与修饰符之间没有空格 *\u002F\n",[39,9263,9264,9266,9268,9270,9272,9274,9276,9278,9280],{"class":41,"line":152},[39,9265,9178],{"class":56},[39,9267,8562],{"class":60},[39,9269,173],{"class":52},[39,9271,4008],{"class":56},[39,9273,6693],{"class":52},[39,9275,2202],{"class":112},[39,9277,116],{"class":52},[39,9279,134],{"class":112},[39,9281,779],{"class":52},[39,9283,9284,9286,9288,9290,9292,9294,9296],{"class":41,"line":158},[39,9285,9178],{"class":56},[39,9287,766],{"class":60},[39,9289,109],{"class":52},[39,9291,4296],{"class":112},[39,9293,116],{"class":52},[39,9295,4301],{"class":67},[39,9297,779],{"class":52},[39,9299,9300],{"class":41,"line":186},[39,9301,432],{"class":52},[39,9303,9304,9306,9308,9310,9313],{"class":41,"line":191},[39,9305,1173],{"class":60},[39,9307,109],{"class":52},[39,9309,9144],{"class":56},[39,9311,9312],{"class":52},"--primary { … } }                    ",[39,9314,9315],{"class":45},"\u002F* → .btn--primary，BEM 修饰符最短写法 *\u002F\n",[15,9317,9318,9319,6003,9322,2612,9325,9328],{},"空格是有语义的：",[36,9320,9321],{},"&--hot",[36,9323,9324],{},".card--hot",[36,9326,9327],{},"& --hot"," 是后代选择器。这是嵌套最常见的笔误。",[15,9330,9331,9333,9334,9337,9338,9341],{},[36,9332,9144],{}," 出现在最前面时可以省略（",[36,9335,9336],{}," .card { h3 { … } }","），但",[19,9339,9340],{},"不建议","——省略后隐含的是后代关系，权重和匹配范围都变了，可读性也下降。",[15,9343,9344,9345,1092,9347,676],{},"条件规则可以写在规则内部，包括媒体查询、",[36,9346,8494],{},[36,9348,9349],{},"@container",[29,9351,9353],{"className":375,"code":9352,"language":377,"meta":34,"style":34},".menu { @media (max-width: 24rem) { & { font-size: 13px; } } }\n",[36,9354,9355],{"__ignoreMap":34},[39,9356,9357,9360,9362,9364,9366,9368,9370,9372,9374,9376,9378,9380,9382,9384,9387,9389],{"class":41,"line":42},[39,9358,9359],{"class":60},".menu",[39,9361,109],{"class":52},[39,9363,6578],{"class":122},[39,9365,6581],{"class":52},[39,9367,113],{"class":112},[39,9369,116],{"class":52},[39,9371,7028],{"class":112},[39,9373,1523],{"class":122},[39,9375,6693],{"class":52},[39,9377,9144],{"class":56},[39,9379,109],{"class":52},[39,9381,2536],{"class":112},[39,9383,116],{"class":52},[39,9385,9386],{"class":112},"13",[39,9388,123],{"class":122},[39,9390,9391],{"class":52},"; } } }\n",[15,9393,9394,9395,9397],{},"浏览器基线：原生嵌套（含 ",[36,9396,9144],{},"、条件规则内嵌）在 Safari 16.5 \u002F Chrome 112 \u002F Firefox 117 一线已全量支持，属 Baseline 可用。需要兼容更旧内核时，让构建工具（Sass、PostCSS、Lightning CSS）降级展开，不要在生产里裸写。",[24,9399,9401],{"id":9400},"嵌套的代价选择器膨胀","嵌套的代价：选择器膨胀",[29,9403,9405],{"className":375,"code":9404,"language":377,"meta":34,"style":34},"\u002F* 四层嵌套写起来爽，展开后是这种怪物： *\u002F\n.page .section .list .item:hover .title span { … }   \u002F* 权重 (0,4,3)，几乎无法覆盖 *\u002F\n",[36,9406,9407,9412],{"__ignoreMap":34},[39,9408,9409],{"class":41,"line":42},[39,9410,9411],{"class":45},"\u002F* 四层嵌套写起来爽，展开后是这种怪物： *\u002F\n",[39,9413,9414,9416,9419,9422,9425,9427,9429,9432],{"class":41,"line":49},[39,9415,5314],{"class":60},[39,9417,9418],{"class":60}," .section",[39,9420,9421],{"class":60}," .list",[39,9423,9424],{"class":60}," .item:hover",[39,9426,8387],{"class":60},[39,9428,846],{"class":56},[39,9430,9431],{"class":52}," { … }   ",[39,9433,9434],{"class":45},"\u002F* 权重 (0,4,3)，几乎无法覆盖 *\u002F\n",[15,9436,9437,9438,9440],{},"症状：想改一个标题颜色只能加 ",[36,9439,327],{},"；改一处 DOM 结构样式全断。四条经验值：",[316,9442,9443,9446,9453,9456],{},[319,9444,9445],{},"嵌套深度 ≤ 2 层（组件本体 + 一个子元素或状态）；",[319,9447,9448,9449,9452],{},"不要把布局上下文写进组件——组件不该知道自己被放在哪个 ",[36,9450,9451],{},".page .section"," 里；",[319,9454,9455],{},"需要跨层级联动时用「变量或状态类」而不是选择器链（第十四章的组件变量）；",[319,9457,9458],{},"权重问题回第四章解决，靠类名结构而不是嵌套堆叠。",[24,9460,9462,9464],{"id":9461},"layer把优先级写成一句声明",[36,9463,339],{},"：把优先级写成一句声明",[29,9466,9468],{"className":375,"code":9467,"language":377,"meta":34,"style":34},"@layer reset, base, vendors, components, utilities, overrides;   \u002F* 越靠后越优先 *\u002F\n\n@layer base     { .panel { border-color: #bf8700; } }\n@layer vendors  { .panel { border-color: #cf222e; } }   \u002F* 后声明的层赢，与书写顺序无关 *\u002F\n",[36,9469,9470,9508,9512,9535],{"__ignoreMap":34},[39,9471,9472,9474,9477,9479,9482,9484,9487,9489,9492,9494,9497,9499,9502,9505],{"class":41,"line":42},[39,9473,339],{"class":122},[39,9475,9476],{"class":1865}," reset",[39,9478,392],{"class":52},[39,9480,9481],{"class":1865},"base",[39,9483,392],{"class":52},[39,9485,9486],{"class":1865},"vendors",[39,9488,392],{"class":52},[39,9490,9491],{"class":1865},"components",[39,9493,392],{"class":52},[39,9495,9496],{"class":1865},"utilities",[39,9498,392],{"class":52},[39,9500,9501],{"class":1865},"overrides",[39,9503,9504],{"class":52},";   ",[39,9506,9507],{"class":45},"\u002F* 越靠后越优先 *\u002F\n",[39,9509,9510],{"class":41,"line":49},[39,9511,86],{"emptyLinePlaceholder":85},[39,9513,9514,9516,9519,9522,9524,9526,9528,9530,9533],{"class":41,"line":82},[39,9515,339],{"class":122},[39,9517,9518],{"class":1865}," base",[39,9520,9521],{"class":52},"     { ",[39,9523,5634],{"class":60},[39,9525,109],{"class":52},[39,9527,3555],{"class":112},[39,9529,116],{"class":52},[39,9531,9532],{"class":112},"#bf8700",[39,9534,6712],{"class":52},[39,9536,9537,9539,9542,9544,9546,9548,9550,9552,9555,9558],{"class":41,"line":89},[39,9538,339],{"class":122},[39,9540,9541],{"class":1865}," vendors",[39,9543,3759],{"class":52},[39,9545,5634],{"class":60},[39,9547,109],{"class":52},[39,9549,3555],{"class":112},[39,9551,116],{"class":52},[39,9553,9554],{"class":112},"#cf222e",[39,9556,9557],{"class":52},"; } }   ",[39,9559,9560],{"class":45},"\u002F* 后声明的层赢，与书写顺序无关 *\u002F\n",[15,9562,9563,9564,9566],{},"它解决的是老问题：第三方库和工具类的样式总在悄悄抢权重。有了层，你不再靠「写得靠后」或「加 ",[36,9565,327],{},"」取胜，而是靠声明层顺序。",[15,9568,9569,9570,9573,9574,9577],{},"同名层会合并；",[36,9571,9572],{},"@layer components { @layer button { … } }"," 形成 ",[36,9575,9576],{},"components.button"," 子层；还可以让第三方 CSS 进层而不改它源码：",[29,9579,9581],{"className":375,"code":9580,"language":377,"meta":34,"style":34},"@layer vendors { @import \"reset.css\"; }\n",[36,9582,9583],{"__ignoreMap":34},[39,9584,9585,9587,9589,9591,9593,9596],{"class":41,"line":42},[39,9586,339],{"class":122},[39,9588,9541],{"class":1865},[39,9590,109],{"class":52},[39,9592,167],{"class":122},[39,9594,9595],{"class":67}," \"reset.css\"",[39,9597,779],{"class":52},[24,9599,9601],{"id":9600},"完整的层叠顺序必须记住的一张表","完整的层叠顺序（必须记住的一张表）",[15,9603,9604],{},"从高到低：",[316,9606,9607,9613,9619,9632,9638,9645,9648],{},[319,9608,9609,9612],{},[19,9610,9611],{},"进行中的过渡\u002F动画声明","（第十八章）；",[319,9614,9615,9616,9618],{},"用户 ",[36,9617,327],{},"（扩展、用户样式表）；",[319,9620,9621,9622,676,9624,9627,9628,9631],{},"作者 ",[36,9623,327],{},[19,9625,9626],{},"未分层最高","，各层之间则",[19,9629,9630],{},"反向","（越早声明的层越优先）——这条最反直觉；",[319,9633,9634,9637],{},[19,9635,9636],{},"未分层（unlayered）作者样式","：比所有已声明的层都高；",[319,9639,9640,9641,9644],{},"分层作者样式：按 ",[36,9642,9643],{},"@layer a, b, c;"," 顺序，c > b > a，同层内回到第四章的权重规则；",[319,9646,9647],{},"用户样式表；",[319,9649,9650],{},"浏览器默认。",[15,9652,9653],{},"第 4 条是实践中最容易踩的：「随手加的一行补丁」默认就是最强，会压住你所有分层规则。想让补丁被层管理，就把它放进最末的层。",[15,9655,9656,9657,9659,9660,9662],{},"另外区分两个名字相近、机制无关的概念：",[19,9658,6302],{},"（第十二章的几何问题）与",[19,9661,6306],{},"（本节的声明顺序问题）。",[15,9664,8284,9665,1416,9667,9670,9671,9674],{},[36,9666,339],{},[36,9668,9669],{},"layer()"," 函数在 Chrome 99 \u002F Safari 15.4 \u002F Firefox 103 一线已全量支持。用法建议：",[19,9672,9673],{},"项目从零开始才引入分层","；给已有大项目补层容易和未分层样式打架。",[24,9676,9677],{"id":9677},"自查",[316,9679,9680,9691,9697,9703],{},[319,9681,9682,9683,9685,9686,9688,9689,2814],{},"「嵌套写了没生效」→ 检查 ",[36,9684,9144],{}," 与空格（",[36,9687,9321],{}," vs ",[36,9690,9327],{},[319,9692,9693,9694,9696],{},"「层里的样式被随手一行盖掉」→ 那是未分层默认最高，符合规范，把补丁挪进 ",[36,9695,9501],{}," 层；",[319,9698,9699,9700,9702],{},"「加了 ",[36,9701,327],{}," 反而输给早层」→ 正确行为；",[319,9704,9705],{},"「DevTools 里看不懂谁赢」→ Styles 面板会显示层名与权重，逐条取消勾选验证（第二十章）。",[10,9707,9709],{"id":9708},"十七伪元素与生成内容","十七、伪元素与生成内容",[15,9711,9712,918,9714,9716],{},[36,9713,759],{},[36,9715,766],{}," 是「不写进 HTML 的装饰盒子」。它的价值在于让表现性内容与文档结构分离——代价是这份内容对搜索、复制、辅助技术都不可靠。",[304,9718],{"height":5169,"src":9719,"title":9720},"\u002Ftutorials\u002Fcss\u002Fdemos\u002F17-pseudo-elements.html","示例 17：content 取值、counter 自动编号、::selection 与纯 CSS 装饰",[24,9722,9724,9725],{"id":9723},"只有一个前提必须有-content","只有一个前提：必须有 ",[36,9726,4296],{},[29,9728,9730],{"className":375,"code":9729,"language":377,"meta":34,"style":34},".x::before { content: \"\"; }      \u002F* 生成一个空盒子 —— 装饰全靠它 *\u002F\n.x::before { content: none; }    \u002F* 完全不生成，伪元素不存在 *\u002F\n",[36,9731,9732,9751],{"__ignoreMap":34},[39,9733,9734,9737,9739,9741,9743,9745,9748],{"class":41,"line":42},[39,9735,9736],{"class":60},".x::before",[39,9738,109],{"class":52},[39,9740,4296],{"class":112},[39,9742,116],{"class":52},[39,9744,4301],{"class":67},[39,9746,9747],{"class":52},"; }      ",[39,9749,9750],{"class":45},"\u002F* 生成一个空盒子 —— 装饰全靠它 *\u002F\n",[39,9752,9753,9755,9757,9759,9761,9763,9765],{"class":41,"line":49},[39,9754,9736],{"class":60},[39,9756,109],{"class":52},[39,9758,4296],{"class":112},[39,9760,116],{"class":52},[39,9762,7259],{"class":112},[39,9764,2295],{"class":52},[39,9766,9767],{"class":45},"\u002F* 完全不生成，伪元素不存在 *\u002F\n",[15,9769,9770,9771,9773,9774,9776],{},"不写 ",[36,9772,4296],{}," 时伪元素不会渲染。单冒号 ",[36,9775,1124],{}," 也能工作，但规范用双冒号区分伪元素与伪类（单冒号）。",[24,9778,9780,9782],{"id":9779},"content-的取值形态",[36,9781,4296],{}," 的取值形态",[29,9784,9786],{"className":375,"code":9785,"language":377,"meta":34,"style":34},".x::before { content: \"文字\"; }\n.x::before { content: attr(data-icon) \" \"; }                    \u002F* 属性值，可拼接 *\u002F\n.x::after  { content: \"（来源：\" attr(data-src, \"未标注\") \"）\"; }  \u002F* attr() 第二参数是回退值 *\u002F\n.x::after  { content: url(arrow.svg); }                          \u002F* 图片 *\u002F\n.x::before { content: counter(n) \".\" counter(m); }               \u002F* 计数器 *\u002F\n.x::before { content: open-quote; }                              \u002F* 引号，跟随 lang 与 quotes *\u002F\n.x::before { content: \"\\201C 转义字符\"; }                        \u002F* Unicode 转义后要有空格 *\u002F\n",[36,9787,9788,9803,9831,9868,9891,9926,9945],{"__ignoreMap":34},[39,9789,9790,9792,9794,9796,9798,9801],{"class":41,"line":42},[39,9791,9736],{"class":60},[39,9793,109],{"class":52},[39,9795,4296],{"class":112},[39,9797,116],{"class":52},[39,9799,9800],{"class":67},"\"文字\"",[39,9802,779],{"class":52},[39,9804,9805,9807,9809,9811,9813,9816,9818,9821,9823,9826,9828],{"class":41,"line":49},[39,9806,9736],{"class":60},[39,9808,109],{"class":52},[39,9810,4296],{"class":112},[39,9812,116],{"class":52},[39,9814,9815],{"class":112},"attr",[39,9817,173],{"class":52},[39,9819,9820],{"class":1865},"data-icon",[39,9822,1033],{"class":52},[39,9824,9825],{"class":67},"\" \"",[39,9827,8552],{"class":52},[39,9829,9830],{"class":45},"\u002F* 属性值，可拼接 *\u002F\n",[39,9832,9833,9836,9838,9840,9842,9845,9848,9850,9853,9855,9858,9860,9863,9865],{"class":41,"line":82},[39,9834,9835],{"class":60},".x::after",[39,9837,3759],{"class":52},[39,9839,4296],{"class":112},[39,9841,116],{"class":52},[39,9843,9844],{"class":67},"\"（来源：\"",[39,9846,9847],{"class":112}," attr",[39,9849,173],{"class":52},[39,9851,9852],{"class":1865},"data-src",[39,9854,392],{"class":52},[39,9856,9857],{"class":67},"\"未标注\"",[39,9859,1033],{"class":52},[39,9861,9862],{"class":67},"\"）\"",[39,9864,2028],{"class":52},[39,9866,9867],{"class":45},"\u002F* attr() 第二参数是回退值 *\u002F\n",[39,9869,9870,9872,9874,9876,9878,9880,9882,9885,9888],{"class":41,"line":89},[39,9871,9835],{"class":60},[39,9873,3759],{"class":52},[39,9875,4296],{"class":112},[39,9877,116],{"class":52},[39,9879,3033],{"class":112},[39,9881,173],{"class":52},[39,9883,9884],{"class":1865},"arrow.svg",[39,9886,9887],{"class":52},"); }                          ",[39,9889,9890],{"class":45},"\u002F* 图片 *\u002F\n",[39,9892,9893,9895,9897,9899,9901,9904,9906,9908,9910,9913,9916,9918,9921,9923],{"class":41,"line":95},[39,9894,9736],{"class":60},[39,9896,109],{"class":52},[39,9898,4296],{"class":112},[39,9900,116],{"class":52},[39,9902,9903],{"class":112},"counter",[39,9905,173],{"class":52},[39,9907,8701],{"class":1865},[39,9909,1033],{"class":52},[39,9911,9912],{"class":67},"\".\"",[39,9914,9915],{"class":112}," counter",[39,9917,173],{"class":52},[39,9919,9920],{"class":1865},"m",[39,9922,8936],{"class":52},[39,9924,9925],{"class":45},"\u002F* 计数器 *\u002F\n",[39,9927,9928,9930,9932,9934,9936,9939,9942],{"class":41,"line":147},[39,9929,9736],{"class":60},[39,9931,109],{"class":52},[39,9933,4296],{"class":112},[39,9935,116],{"class":52},[39,9937,9938],{"class":112},"open-quote",[39,9940,9941],{"class":52},"; }                              ",[39,9943,9944],{"class":45},"\u002F* 引号，跟随 lang 与 quotes *\u002F\n",[39,9946,9947,9949,9951,9953,9955,9958,9961,9964,9966],{"class":41,"line":152},[39,9948,9736],{"class":60},[39,9950,109],{"class":52},[39,9952,4296],{"class":112},[39,9954,116],{"class":52},[39,9956,9957],{"class":67},"\"",[39,9959,9960],{"class":112},"\\201C",[39,9962,9963],{"class":67}," 转义字符\"",[39,9965,6673],{"class":52},[39,9967,9968],{"class":45},"\u002F* Unicode 转义后要有空格 *\u002F\n",[24,9970,9972,9975],{"id":9971},"counter章节自动编号",[36,9973,9974],{},"counter()","：章节自动编号",[29,9977,9979],{"className":375,"code":9978,"language":377,"meta":34,"style":34},"body { counter-reset: sect sub; }              \u002F* 声明计数器（初值 0） *\u002F\n.sect { counter-increment: sect; }\n.sect::before { content: \"第 \" counter(sect) \" 节：\"; }\n.sub { counter-increment: sub; }\n.sub::before { content: counter(sect) \".\" counter(sub); }        \u002F* 两级编号 *\u002F\n",[36,9980,9981,10001,10014,10042,10057],{"__ignoreMap":34},[39,9982,9983,9985,9987,9990,9993,9996,9998],{"class":41,"line":42},[39,9984,106],{"class":56},[39,9986,109],{"class":52},[39,9988,9989],{"class":112},"counter-reset",[39,9991,9992],{"class":52},": sect ",[39,9994,9995],{"class":112},"sub",[39,9997,3748],{"class":52},[39,9999,10000],{"class":45},"\u002F* 声明计数器（初值 0） *\u002F\n",[39,10002,10003,10006,10008,10011],{"class":41,"line":49},[39,10004,10005],{"class":60},".sect",[39,10007,109],{"class":52},[39,10009,10010],{"class":112},"counter-increment",[39,10012,10013],{"class":52},": sect; }\n",[39,10015,10016,10019,10021,10023,10025,10028,10030,10032,10035,10037,10040],{"class":41,"line":82},[39,10017,10018],{"class":60},".sect::before",[39,10020,109],{"class":52},[39,10022,4296],{"class":112},[39,10024,116],{"class":52},[39,10026,10027],{"class":67},"\"第 \"",[39,10029,9915],{"class":112},[39,10031,173],{"class":52},[39,10033,10034],{"class":1865},"sect",[39,10036,1033],{"class":52},[39,10038,10039],{"class":67},"\" 节：\"",[39,10041,779],{"class":52},[39,10043,10044,10047,10049,10051,10053,10055],{"class":41,"line":89},[39,10045,10046],{"class":60},".sub",[39,10048,109],{"class":52},[39,10050,10010],{"class":112},[39,10052,116],{"class":52},[39,10054,9995],{"class":112},[39,10056,779],{"class":52},[39,10058,10059,10062,10064,10066,10068,10070,10072,10074,10076,10078,10080,10082,10084,10087],{"class":41,"line":95},[39,10060,10061],{"class":60},".sub::before",[39,10063,109],{"class":52},[39,10065,4296],{"class":112},[39,10067,116],{"class":52},[39,10069,9903],{"class":112},[39,10071,173],{"class":52},[39,10073,10034],{"class":1865},[39,10075,1033],{"class":52},[39,10077,9912],{"class":67},[39,10079,9915],{"class":112},[39,10081,173],{"class":52},[39,10083,9995],{"class":112},[39,10085,10086],{"class":52},"); }        ",[39,10088,10089],{"class":45},"\u002F* 两级编号 *\u002F\n",[15,10091,10092,10094,10095,1092,10098,1092,10101,1092,10104,10107,10108,10111],{},[36,10093,9974],{}," 的第二个参数可以指定样式：",[36,10096,10097],{},"upper-roman",[36,10099,10100],{},"lower-alpha",[36,10102,10103],{},"cjk-decimal",[36,10105,10106],{},"decimal-leading-zero","。它的价值不在替代 ",[36,10109,10110],{},"\u003Col>","，而在「多级编号 + 非列表元素 + 跨元素拼字符串」这类真实需求（论文式标题、题号、章节引用）。",[15,10113,10114],{},"本站教程正文刻意不用自动编号：标题文字本身就是内容，编号写进正文而不是靠 CSS 生成，这样搜索结果、复制、读屏拿到的都是完整标题。",[24,10116,10118],{"id":10117},"其它伪元素一个比一个更只能装饰","其它伪元素：一个比一个更「只能装饰」",[219,10120,10121,10134],{},[222,10122,10123],{},[225,10124,10125,10128,10131],{},[228,10126,10127],{},"伪元素",[228,10129,10130],{},"能做什么",[228,10132,10133],{},"限制",[238,10135,10136,10150,10169,10185,10200,10212],{},[225,10137,10138,10144,10147],{},[243,10139,10140,918,10142],{},[36,10141,759],{},[36,10143,766],{},[243,10145,10146],{},"任意装饰盒子",[243,10148,10149],{},"每个元素只有两个",[225,10151,10152,10160,10163],{},[243,10153,10154,918,10157],{},[36,10155,10156],{},"::first-line",[36,10158,10159],{},"::first-letter",[243,10161,10162],{},"首行\u002F首字样式（杂志风）",[243,10164,10165,10166,10168],{},"只接受少量属性；",[36,10167,10159],{}," 不能作用于行内非替换元素",[225,10170,10171,10176,10182],{},[243,10172,10173],{},[36,10174,10175],{},"::marker",[243,10177,10178,10179,10181],{},"列表记号的颜色、字重，甚至用 ",[36,10180,4296],{}," 换成箭头",[243,10183,10184],{},"只开放 content\u002Fcolor\u002Ffont-* 等少数属性",[225,10186,10187,10191,10194],{},[243,10188,10189],{},[36,10190,1116],{},[243,10192,10193],{},"选中高亮配色",[243,10195,10196,10197],{},"只允许 color\u002Fbackground\u002Ftext-shadow 等；",[19,10198,10199],{},"对比度必须够",[225,10201,10202,10206,10209],{},[243,10203,10204],{},[36,10205,1113],{},[243,10207,10208],{},"占位符样式",[243,10210,10211],{},"默认带透明度，需要显式覆盖",[225,10213,10214,10219,10225],{},[243,10215,10216],{},[36,10217,10218],{},"::backdrop",[243,10220,10221,10224],{},[36,10222,10223],{},"\u003Cdialog>","\u002F全屏时遮罩层样式",[243,10226,10227,10228,10231],{},"配合 ",[36,10229,10230],{},"color-mix()"," 做半透明遮罩很合适",[24,10233,10235],{"id":10234},"五个纯-css-装饰配方","五个纯 CSS 装饰配方",[29,10237,10239],{"className":375,"code":10238,"language":377,"meta":34,"style":34},"\u002F* 圆形序号徽标：counter + inline-grid 居中 *\u002F\n.steps { counter-reset: step; list-style: none; }\n.steps li { counter-increment: step; }\n.steps li::before { content: counter(step); display: inline-grid; place-items: center;\n                    width: 20px; height: 20px; border-radius: 50%; background: #0969da; color: #fff; }\n\u002F* 尖角 tooltip：零尺寸盒子 + 四条透明 border，只给一侧上色 *\u002F\n.tip::after { content: \"\"; position: absolute; top: 100%; border: 6px solid transparent; border-top-color: #24292f; }\n\u002F* hover 下划线：动 ::after 的 scaleX —— text-decoration 不能平滑过渡 *\u002F\n.ul-anim::after { content: \"\"; position: absolute; left: 0; right: 0; bottom: -2px; height: 2px;\n                  background: #0969da; transform: scaleX(0); transform-origin: left; transition: transform .22s; }\n.ul-anim:hover::after { transform: scaleX(1); }\n\u002F* 骨架屏：background-position 动画，不需要图片 *\u002F\n.skeleton { background: linear-gradient(90deg, #eaeef2 0 25%, #f6f8fa 37%, #eaeef2 63%) 0 0\u002F400% 100%;\n            animation: shimmer 1.4s ease infinite; }\n",[36,10240,10241,10246,10267,10281,10320,10369,10374,10432,10437,10498,10543,10562,10568,10636],{"__ignoreMap":34},[39,10242,10243],{"class":41,"line":42},[39,10244,10245],{"class":45},"\u002F* 圆形序号徽标：counter + inline-grid 居中 *\u002F\n",[39,10247,10248,10251,10253,10255,10258,10261,10263,10265],{"class":41,"line":49},[39,10249,10250],{"class":60},".steps",[39,10252,109],{"class":52},[39,10254,9989],{"class":112},[39,10256,10257],{"class":52},": step; ",[39,10259,10260],{"class":112},"list-style",[39,10262,116],{"class":52},[39,10264,7259],{"class":112},[39,10266,779],{"class":52},[39,10268,10269,10271,10274,10276,10278],{"class":41,"line":82},[39,10270,10250],{"class":60},[39,10272,10273],{"class":56}," li",[39,10275,109],{"class":52},[39,10277,10010],{"class":112},[39,10279,10280],{"class":52},": step; }\n",[39,10282,10283,10285,10287,10289,10291,10293,10295,10297,10299,10302,10304,10306,10308,10310,10312,10314,10316,10318],{"class":41,"line":89},[39,10284,10250],{"class":60},[39,10286,10273],{"class":56},[39,10288,759],{"class":60},[39,10290,109],{"class":52},[39,10292,4296],{"class":112},[39,10294,116],{"class":52},[39,10296,9903],{"class":112},[39,10298,173],{"class":52},[39,10300,10301],{"class":1865},"step",[39,10303,3041],{"class":52},[39,10305,1350],{"class":112},[39,10307,116],{"class":52},[39,10309,4422],{"class":112},[39,10311,126],{"class":52},[39,10313,5690],{"class":112},[39,10315,116],{"class":52},[39,10317,2684],{"class":112},[39,10319,427],{"class":52},[39,10321,10322,10325,10327,10329,10331,10333,10335,10337,10339,10341,10343,10345,10347,10349,10351,10353,10355,10357,10359,10361,10363,10365,10367],{"class":41,"line":95},[39,10323,10324],{"class":112},"                    width",[39,10326,116],{"class":52},[39,10328,7068],{"class":112},[39,10330,123],{"class":122},[39,10332,126],{"class":52},[39,10334,1343],{"class":112},[39,10336,116],{"class":52},[39,10338,7068],{"class":112},[39,10340,123],{"class":122},[39,10342,126],{"class":52},[39,10344,3615],{"class":112},[39,10346,116],{"class":52},[39,10348,6066],{"class":112},[39,10350,1552],{"class":122},[39,10352,126],{"class":52},[39,10354,1347],{"class":112},[39,10356,116],{"class":52},[39,10358,1698],{"class":112},[39,10360,126],{"class":52},[39,10362,1304],{"class":112},[39,10364,116],{"class":52},[39,10366,1871],{"class":112},[39,10368,779],{"class":52},[39,10370,10371],{"class":41,"line":147},[39,10372,10373],{"class":45},"\u002F* 尖角 tooltip：零尺寸盒子 + 四条透明 border，只给一侧上色 *\u002F\n",[39,10375,10376,10379,10381,10383,10385,10387,10389,10391,10393,10395,10397,10399,10401,10403,10405,10407,10409,10411,10414,10416,10418,10421,10423,10426,10428,10430],{"class":41,"line":152},[39,10377,10378],{"class":60},".tip::after",[39,10380,109],{"class":52},[39,10382,4296],{"class":112},[39,10384,116],{"class":52},[39,10386,4301],{"class":67},[39,10388,126],{"class":52},[39,10390,1353],{"class":112},[39,10392,116],{"class":52},[39,10394,5914],{"class":112},[39,10396,126],{"class":52},[39,10398,5881],{"class":112},[39,10400,116],{"class":52},[39,10402,1995],{"class":112},[39,10404,1552],{"class":122},[39,10406,126],{"class":52},[39,10408,1337],{"class":112},[39,10410,116],{"class":52},[39,10412,10413],{"class":112},"6",[39,10415,123],{"class":122},[39,10417,2022],{"class":112},[39,10419,10420],{"class":112}," transparent",[39,10422,126],{"class":52},[39,10424,10425],{"class":112},"border-top-color",[39,10427,116],{"class":52},[39,10429,408],{"class":112},[39,10431,779],{"class":52},[39,10433,10434],{"class":41,"line":158},[39,10435,10436],{"class":45},"\u002F* hover 下划线：动 ::after 的 scaleX —— text-decoration 不能平滑过渡 *\u002F\n",[39,10438,10439,10442,10444,10446,10448,10450,10452,10454,10456,10458,10460,10462,10464,10466,10468,10470,10472,10474,10476,10479,10481,10484,10486,10488,10490,10492,10494,10496],{"class":41,"line":186},[39,10440,10441],{"class":60},".ul-anim::after",[39,10443,109],{"class":52},[39,10445,4296],{"class":112},[39,10447,116],{"class":52},[39,10449,4301],{"class":67},[39,10451,126],{"class":52},[39,10453,1353],{"class":112},[39,10455,116],{"class":52},[39,10457,5914],{"class":112},[39,10459,126],{"class":52},[39,10461,2678],{"class":112},[39,10463,116],{"class":52},[39,10465,134],{"class":112},[39,10467,126],{"class":52},[39,10469,2681],{"class":112},[39,10471,116],{"class":52},[39,10473,134],{"class":112},[39,10475,126],{"class":52},[39,10477,10478],{"class":112},"bottom",[39,10480,116],{"class":52},[39,10482,10483],{"class":112},"-2",[39,10485,123],{"class":122},[39,10487,126],{"class":52},[39,10489,1343],{"class":112},[39,10491,116],{"class":52},[39,10493,2313],{"class":112},[39,10495,123],{"class":122},[39,10497,427],{"class":52},[39,10499,10500,10503,10505,10507,10509,10511,10513,10516,10518,10520,10522,10525,10527,10529,10531,10533,10536,10539,10541],{"class":41,"line":191},[39,10501,10502],{"class":112},"                  background",[39,10504,116],{"class":52},[39,10506,1698],{"class":112},[39,10508,126],{"class":52},[39,10510,1370],{"class":112},[39,10512,116],{"class":52},[39,10514,10515],{"class":112},"scaleX",[39,10517,173],{"class":52},[39,10519,134],{"class":112},[39,10521,3041],{"class":52},[39,10523,10524],{"class":112},"transform-origin",[39,10526,116],{"class":52},[39,10528,2678],{"class":112},[39,10530,126],{"class":52},[39,10532,4190],{"class":112},[39,10534,10535],{"class":52},": transform ",[39,10537,10538],{"class":112},".22",[39,10540,1681],{"class":122},[39,10542,779],{"class":52},[39,10544,10545,10548,10550,10552,10554,10556,10558,10560],{"class":41,"line":197},[39,10546,10547],{"class":60},".ul-anim:hover::after",[39,10549,109],{"class":52},[39,10551,1370],{"class":112},[39,10553,116],{"class":52},[39,10555,10515],{"class":112},[39,10557,173],{"class":52},[39,10559,2017],{"class":112},[39,10561,3475],{"class":52},[39,10563,10565],{"class":41,"line":10564},12,[39,10566,10567],{"class":45},"\u002F* 骨架屏：background-position 动画，不需要图片 *\u002F\n",[39,10569,10571,10574,10576,10578,10580,10582,10584,10586,10588,10590,10592,10594,10597,10599,10601,10604,10607,10609,10611,10613,10616,10618,10620,10622,10624,10626,10628,10630,10632,10634],{"class":41,"line":10570},13,[39,10572,10573],{"class":60},".skeleton",[39,10575,109],{"class":52},[39,10577,1347],{"class":112},[39,10579,116],{"class":52},[39,10581,3125],{"class":112},[39,10583,173],{"class":52},[39,10585,3130],{"class":112},[39,10587,1663],{"class":122},[39,10589,392],{"class":52},[39,10591,3467],{"class":112},[39,10593,3509],{"class":112},[39,10595,10596],{"class":112}," 25",[39,10598,1552],{"class":122},[39,10600,392],{"class":52},[39,10602,10603],{"class":112},"#f6f8fa",[39,10605,10606],{"class":112}," 37",[39,10608,1552],{"class":122},[39,10610,392],{"class":52},[39,10612,3467],{"class":112},[39,10614,10615],{"class":112}," 63",[39,10617,1552],{"class":122},[39,10619,1033],{"class":52},[39,10621,134],{"class":112},[39,10623,3509],{"class":112},[39,10625,1331],{"class":52},[39,10627,2558],{"class":112},[39,10629,1552],{"class":122},[39,10631,3379],{"class":112},[39,10633,1552],{"class":122},[39,10635,427],{"class":52},[39,10637,10639,10642,10645,10648,10650,10652,10655],{"class":41,"line":10638},14,[39,10640,10641],{"class":112},"            animation",[39,10643,10644],{"class":52},": shimmer ",[39,10646,10647],{"class":112},"1.4",[39,10649,1681],{"class":122},[39,10651,4201],{"class":112},[39,10653,10654],{"class":112}," infinite",[39,10656,779],{"class":52},[15,10658,10659,10660,10662],{},"（伪元素与过渡\u002F动画的组合见第十八章；",[36,10661,4296],{}," 参与媒体查询做不同装饰也完全合法，见第十三章。）",[24,10664,10665],{"id":10665},"三个必须知道的限制",[316,10667,10668,10680,10686],{},[319,10669,10670,676,10673,10675,10676,10679],{},[19,10671,10672],{},"不能嵌 HTML",[36,10674,4296],{}," 里写 ",[36,10677,10678],{},"\u003Cb>"," 只会显示字面量。需要结构就写进 DOM。",[319,10681,10682,10685],{},[19,10683,10684],{},"不可选中、不可搜索、复制会丢失","：所以「必需信息」不要只存在于伪元素里（价格、状态文字、必填星号的说明）。读屏支持参差不齐，把它当纯装饰最安全。",[319,10687,10688,10690,10691,10693,10694,10696,10697,10700,10701,10703,10704,10706],{},[19,10689,10149],{},"：需要三层装饰时——给父用 ",[36,10692,759],{},"、子元素用 ",[36,10695,766],{},"，或者改用真实 ",[36,10698,10699],{},"\u003Cspan>","、多重 ",[36,10702,3697],{},"、多层 ",[36,10705,1347],{},"（第八章）。",[15,10708,10709,10710,10718],{},"一条判断标准：",[19,10711,10712,10713,10715,10716,340],{},"图片的说明文字属于 HTML（",[36,10714,3084],{},"），装饰符号属于 CSS（",[36,10717,4296],{},"。前者是内容，后者是表现。",[10,10720,10722],{"id":10721},"十八过渡变形与动画","十八、过渡、变形与动画",[15,10724,10725,10726,10729,10730,590],{},"动效的目标是「解释变化」，不是「装饰页面」。技术上只需要区分两件事：过渡负责",[19,10727,10728],{},"两个状态之间","，动画负责",[19,10731,10732],{},"多帧序列",[304,10734],{"height":5460,"src":10735,"title":10736},"\u002Ftutorials\u002Fcss\u002Fdemos\u002F18a-transition.html","示例 18a：transition 四要素、缓动曲线、transform 2D\u002F3D 与性能友好属性",[24,10738,10740,10742],{"id":10739},"transition-的四要素",[36,10741,4190],{}," 的四要素",[29,10744,10746],{"className":375,"code":10745,"language":377,"meta":34,"style":34},".btn { transition: background-color 200ms ease-out 0s, border-color 200ms ease-in 50ms; }\n",[36,10747,10748],{"__ignoreMap":34},[39,10749,10750,10752,10754,10756,10759,10761,10763,10766,10768,10770,10773,10775,10777,10780,10783,10785],{"class":41,"line":42},[39,10751,1173],{"class":60},[39,10753,109],{"class":52},[39,10755,4190],{"class":112},[39,10757,10758],{"class":52},": background-color ",[39,10760,5206],{"class":112},[39,10762,1684],{"class":122},[39,10764,10765],{"class":112}," ease-out",[39,10767,3509],{"class":112},[39,10769,1681],{"class":122},[39,10771,10772],{"class":52},", border-color ",[39,10774,5206],{"class":112},[39,10776,1684],{"class":122},[39,10778,10779],{"class":112}," ease-in",[39,10781,10782],{"class":112}," 50",[39,10784,1684],{"class":122},[39,10786,779],{"class":52},[15,10788,10789,10790,10793,10794,10797],{},"顺序是 ",[19,10791,10792],{},"属性 \u002F 时长 \u002F 缓动 \u002F 延迟","；两个时间同时出现时",[19,10795,10796],{},"第一个是时长、第二个是延迟","，写反含义就变。",[15,10799,10800,10801,10803,10804,10806,10807,10810],{},"最常见的笔误是把 ",[36,10802,4190],{}," 只写在 ",[36,10805,1091],{}," 里——那样只有悬停时有过渡，移开时瞬间跳回。正确做法是写在",[19,10808,10809],{},"基础状态","上：",[29,10812,10814],{"className":375,"code":10813,"language":377,"meta":34,"style":34},".a { transition: all .3s; }        \u002F* ✓ *\u002F\n.a:hover { transform: translateY(-2px); }\n",[36,10815,10816,10840],{"__ignoreMap":34},[39,10817,10818,10821,10823,10825,10827,10830,10833,10835,10837],{"class":41,"line":42},[39,10819,10820],{"class":60},".a",[39,10822,109],{"class":52},[39,10824,4190],{"class":112},[39,10826,116],{"class":52},[39,10828,10829],{"class":112},"all",[39,10831,10832],{"class":112}," .3",[39,10834,1681],{"class":122},[39,10836,2323],{"class":52},[39,10838,10839],{"class":45},"\u002F* ✓ *\u002F\n",[39,10841,10842,10845,10847,10849,10851,10854,10856,10858,10860],{"class":41,"line":49},[39,10843,10844],{"class":60},".a:hover",[39,10846,109],{"class":52},[39,10848,1370],{"class":112},[39,10850,116],{"class":52},[39,10852,10853],{"class":112},"translateY",[39,10855,173],{"class":52},[39,10857,10483],{"class":112},[39,10859,123],{"class":122},[39,10861,3475],{"class":52},[15,10863,9770,10864,10867,10868,10870],{},[36,10865,10866],{},"transition-property"," 时默认是 ",[36,10869,10829],{},"，会带来意外的连锁动画（连布局属性都在补帧），建议显式列出要过渡的属性。",[24,10872,10873],{"id":10873},"缓动决定手感",[434,10875,10876,10883,10889,10895,10902,10908],{},[319,10877,10878,10879,10882],{},"进入用 ",[36,10880,10881],{},"ease-out","（快起手、慢落位）；",[319,10884,10885,10886,672],{},"离开用 ",[36,10887,10888],{},"ease-in",[319,10890,10891,10892,672],{},"来回运动用 ",[36,10893,10894],{},"ease-in-out",[319,10896,10897,10898,10901],{},"需要「有重量」的弹跳用 ",[36,10899,10900],{},"cubic-bezier(.34, 1.56, .64, 1)","（控制点 y 超出 1 会过冲回弹）；",[319,10903,10904,10905,672],{},"精灵图\u002F打字机用 ",[36,10906,10907],{},"steps(6, end)",[319,10909,10910,10911,10914],{},"新写法 ",[36,10912,10913],{},"linear(0, .6 20%, 1 40%, .8 55%, 1)"," 直接按关键帧描述曲线，回弹不必再手算贝塞尔控制点。",[15,10916,10917,10918,10921,10922,10925],{},"一个常被忽略的细节：",[36,10919,10920],{},"animation-timing-function"," 作用于",[19,10923,10924],{},"每两个关键帧之间","（不是整段动画），也可以写在关键帧内部逐段指定。",[24,10927,10929,10931],{"id":10928},"transform2d3d-与支点",[36,10930,1370],{},"：2D、3D 与支点",[29,10933,10935],{"className":375,"code":10934,"language":377,"meta":34,"style":34},".x:hover { transform: translate(6px, -4px) rotate(-6deg) scale(1.1); }\n.wrap { perspective: 500px; }                 \u002F* 给 3D 一个观察距离 *\u002F\n.card:hover { transform: rotateY(180deg); }\n.origin { transform-origin: top left; }       \u002F* 旋转\u002F缩放的支点 *\u002F\n",[36,10936,10937,10986,11007,11029],{"__ignoreMap":34},[39,10938,10939,10942,10944,10946,10948,10950,10952,10954,10956,10958,10961,10963,10965,10968,10970,10972,10974,10976,10979,10981,10984],{"class":41,"line":42},[39,10940,10941],{"class":60},".x:hover",[39,10943,109],{"class":52},[39,10945,1370],{"class":112},[39,10947,116],{"class":52},[39,10949,6087],{"class":112},[39,10951,173],{"class":52},[39,10953,10413],{"class":112},[39,10955,123],{"class":122},[39,10957,392],{"class":52},[39,10959,10960],{"class":112},"-4",[39,10962,123],{"class":122},[39,10964,1033],{"class":52},[39,10966,10967],{"class":112},"rotate",[39,10969,173],{"class":52},[39,10971,6442],{"class":112},[39,10973,1663],{"class":122},[39,10975,1033],{"class":52},[39,10977,10978],{"class":112},"scale",[39,10980,173],{"class":52},[39,10982,10983],{"class":112},"1.1",[39,10985,3475],{"class":52},[39,10987,10988,10990,10992,10994,10996,10999,11001,11004],{"class":41,"line":49},[39,10989,7100],{"class":60},[39,10991,109],{"class":52},[39,10993,6225],{"class":112},[39,10995,116],{"class":52},[39,10997,10998],{"class":112},"500",[39,11000,123],{"class":122},[39,11002,11003],{"class":52},"; }                 ",[39,11005,11006],{"class":45},"\u002F* 给 3D 一个观察距离 *\u002F\n",[39,11008,11009,11011,11013,11015,11017,11020,11022,11025,11027],{"class":41,"line":82},[39,11010,3550],{"class":60},[39,11012,109],{"class":52},[39,11014,1370],{"class":112},[39,11016,116],{"class":52},[39,11018,11019],{"class":112},"rotateY",[39,11021,173],{"class":52},[39,11023,11024],{"class":112},"180",[39,11026,1663],{"class":122},[39,11028,3475],{"class":52},[39,11030,11031,11034,11036,11038,11040,11042,11045,11047],{"class":41,"line":89},[39,11032,11033],{"class":60},".origin",[39,11035,109],{"class":52},[39,11037,10524],{"class":112},[39,11039,116],{"class":52},[39,11041,5881],{"class":112},[39,11043,11044],{"class":112}," left",[39,11046,8608],{"class":52},[39,11048,11049],{"class":45},"\u002F* 旋转\u002F缩放的支点 *\u002F\n",[15,11051,11052],{},"三条要点：",[316,11054,11055,11069,11076],{},[319,11056,11057,676,11060,11062,11063,11065,11066,11068],{},[19,11058,11059],{},"顺序有意义",[36,11061,1370],{}," 是矩阵相乘，先 ",[36,11064,6087],{}," 再 ",[36,11067,10967],{}," 与反过来结果不同；",[319,11070,11071,6163,11073,11075],{},[36,11072,6087],{},[19,11074,6166],{},"尺寸——这是「未知宽高也能居中」的依据（第十二章）；",[319,11077,11078,11080],{},[36,11079,10978],{}," 不改变布局占位，只是绘制时被放大，相邻元素不会让位（可能重叠）。",[15,11082,11083,11084,11087,11088,590],{},"翻牌卡片：两面绝对定位叠在一起 + ",[36,11085,11086],{},"backface-visibility: hidden","；立方体一类立体组合需要父级 ",[36,11089,11090],{},"transform-style: preserve-3d",[24,11092,11094,11095,1416,11097],{"id":11093},"只动-transform-与-opacity","只动 ",[36,11096,1370],{},[36,11098,1367],{},[219,11100,11101,11110],{},[222,11102,11103],{},[225,11104,11105,11108],{},[228,11106,11107],{},"属性",[228,11109,236],{},[238,11111,11112,11126,11136,11150],{},[225,11113,11114,11120],{},[243,11115,11116,1092,11118],{},[36,11117,1370],{},[36,11119,1367],{},[243,11121,11122,11123],{},"只需合成，不触发布局与重排 → ",[19,11124,11125],{},"动画首选",[225,11127,11128,11133],{},[243,11129,11130],{},[36,11131,11132],{},"width\u002Fheight\u002Ftop\u002Fleft\u002Fmargin\u002Fpadding",[243,11134,11135],{},"触发布局（layout），多元素同时动会掉帧",[225,11137,11138,11147],{},[243,11139,11140,1092,11142,1092,11144],{},[36,11141,3697],{},[36,11143,3615],{},[36,11145,11146],{},"background-color",[243,11148,11149],{},"触发重绘（paint），大面积时明显",[225,11151,11152,11158],{},[243,11153,1466,11154,11157],{},[36,11155,11156],{},"left\u002Ftop"," 做位移",[243,11159,11160,11161,11164],{},"改用 ",[36,11162,11163],{},"transform: translate()","，视觉一致、成本低得多",[15,11166,11167,11168,11170,11171,676],{},"想给阴影加过渡时不要直接动 ",[36,11169,3697],{},"（中间帧发灰且要重绘整块模糊），把阴影画在伪元素上、动它的 ",[36,11172,1367],{},[29,11174,11176],{"className":375,"code":11175,"language":377,"meta":34,"style":34},".lift::after { content: \"\"; position: absolute; inset: 0; border-radius: inherit; z-index: -1;\n               box-shadow: 0 8px 22px rgba(0,0,0,.22); opacity: 0; transition: opacity .22s; }\n.lift:hover::after { opacity: 1; }\n",[36,11177,11178,11226,11282],{"__ignoreMap":34},[39,11179,11180,11183,11185,11187,11189,11191,11193,11195,11197,11199,11201,11203,11205,11207,11209,11211,11213,11216,11218,11220,11222,11224],{"class":41,"line":42},[39,11181,11182],{"class":60},".lift::after",[39,11184,109],{"class":52},[39,11186,4296],{"class":112},[39,11188,116],{"class":52},[39,11190,4301],{"class":67},[39,11192,126],{"class":52},[39,11194,1353],{"class":112},[39,11196,116],{"class":52},[39,11198,5914],{"class":112},[39,11200,126],{"class":52},[39,11202,3713],{"class":112},[39,11204,116],{"class":52},[39,11206,134],{"class":112},[39,11208,126],{"class":52},[39,11210,3615],{"class":112},[39,11212,116],{"class":52},[39,11214,11215],{"class":112},"inherit",[39,11217,126],{"class":52},[39,11219,1654],{"class":112},[39,11221,116],{"class":52},[39,11223,5471],{"class":112},[39,11225,427],{"class":52},[39,11227,11228,11231,11233,11235,11237,11239,11242,11244,11246,11248,11250,11252,11254,11256,11258,11260,11262,11264,11266,11268,11270,11272,11274,11276,11278,11280],{"class":41,"line":49},[39,11229,11230],{"class":112},"               box-shadow",[39,11232,116],{"class":52},[39,11234,134],{"class":112},[39,11236,3800],{"class":112},[39,11238,123],{"class":122},[39,11240,11241],{"class":112}," 22",[39,11243,123],{"class":122},[39,11245,3777],{"class":112},[39,11247,173],{"class":52},[39,11249,134],{"class":112},[39,11251,3255],{"class":52},[39,11253,134],{"class":112},[39,11255,3255],{"class":52},[39,11257,134],{"class":112},[39,11259,3255],{"class":52},[39,11261,10538],{"class":112},[39,11263,3041],{"class":52},[39,11265,1367],{"class":112},[39,11267,116],{"class":52},[39,11269,134],{"class":112},[39,11271,126],{"class":52},[39,11273,4190],{"class":112},[39,11275,4193],{"class":52},[39,11277,10538],{"class":112},[39,11279,1681],{"class":122},[39,11281,779],{"class":52},[39,11283,11284,11287,11289,11291,11293,11295],{"class":41,"line":82},[39,11285,11286],{"class":60},".lift:hover::after",[39,11288,109],{"class":52},[39,11290,1367],{"class":112},[39,11292,116],{"class":52},[39,11294,2017],{"class":112},[39,11296,779],{"class":52},[304,11298],{"height":5840,"src":11299,"title":11300},"\u002Ftutorials\u002Fcss\u002Fdemos\u002F18b-keyframes.html","示例 18b：@keyframes、animation 属性族、stagger 与滚动驱动动画",[24,11302,11304,1416,11307,11310],{"id":11303},"keyframes-与-animation-属性族",[36,11305,11306],{},"@keyframes",[36,11308,11309],{},"animation"," 属性族",[29,11312,11314],{"className":375,"code":11313,"language":377,"meta":34,"style":34},"@keyframes rise { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }\n.item { animation: rise .5s ease-out both; animation-delay: calc(var(--i, 0) * 80ms); }\n",[36,11315,11316,11374],{"__ignoreMap":34},[39,11317,11318,11320,11323,11325,11328,11330,11332,11334,11336,11338,11340,11342,11344,11346,11348,11350,11353,11356,11358,11360,11362,11364,11366,11368,11370,11372],{"class":41,"line":42},[39,11319,11306],{"class":122},[39,11321,11322],{"class":1865}," rise",[39,11324,109],{"class":52},[39,11326,11327],{"class":60},"from",[39,11329,109],{"class":52},[39,11331,1367],{"class":112},[39,11333,116],{"class":52},[39,11335,134],{"class":112},[39,11337,126],{"class":52},[39,11339,1370],{"class":112},[39,11341,116],{"class":52},[39,11343,10853],{"class":112},[39,11345,173],{"class":52},[39,11347,3642],{"class":112},[39,11349,123],{"class":122},[39,11351,11352],{"class":52},"); } ",[39,11354,11355],{"class":60},"to",[39,11357,109],{"class":52},[39,11359,1367],{"class":112},[39,11361,116],{"class":52},[39,11363,2017],{"class":112},[39,11365,126],{"class":52},[39,11367,1370],{"class":112},[39,11369,116],{"class":52},[39,11371,7259],{"class":112},[39,11373,6712],{"class":52},[39,11375,11376,11378,11380,11382,11385,11387,11389,11391,11394,11396,11399,11401,11403,11405,11407,11409,11412,11414,11416,11418,11420,11423,11425],{"class":41,"line":49},[39,11377,8165],{"class":60},[39,11379,109],{"class":52},[39,11381,11309],{"class":112},[39,11383,11384],{"class":52},": rise ",[39,11386,1733],{"class":112},[39,11388,1681],{"class":122},[39,11390,10765],{"class":112},[39,11392,11393],{"class":112}," both",[39,11395,126],{"class":52},[39,11397,11398],{"class":112},"animation-delay",[39,11400,116],{"class":52},[39,11402,6382],{"class":112},[39,11404,173],{"class":52},[39,11406,3451],{"class":112},[39,11408,173],{"class":52},[39,11410,11411],{"class":1865},"--i",[39,11413,392],{"class":52},[39,11415,134],{"class":112},[39,11417,1033],{"class":52},[39,11419,743],{"class":122},[39,11421,11422],{"class":112}," 80",[39,11424,1684],{"class":122},[39,11426,3475],{"class":52},[15,11428,11429],{},"九个 longhand 里必须真正理解的三个：",[434,11431,11432,11451,11460],{},[319,11433,11434,676,11437,11440,11441,7196,11444,11447,11448,11450],{},[36,11435,11436],{},"animation-fill-mode",[36,11438,11439],{},"forwards"," 结束后停在最后一帧，",[36,11442,11443],{},"backwards",[19,11445,11446],{},"延迟期间","就显示第一帧，进入动画通常写 ",[36,11449,4319],{},"（否则元素会先闪一下原位再飞入）；",[319,11452,11453,11455,11456,11459],{},[36,11454,11398],{}," 可以为",[19,11457,11458],{},"负值","：表示从动画中段开始播，做错峰循环很方便；",[319,11461,11462,11464],{},[36,11463,6915],{}," 可以是小数：播到该比例停止。",[15,11466,11467,11468,11471],{},"多动画并列用逗号（",[36,11469,11470],{},"animation: fade-in .6s both, nudge 1.4s infinite alternate;","），第一个名字对应第一个时长。",[15,11473,11474,11475,11480],{},"进行中的动画声明",[19,11476,11477,11478],{},"优先级高于普通声明和 ",[36,11479,327],{},"（第十六章的层叠表第 1 位）。所以「动画一跑 hover 就没反应」是规范行为，要先结束动画。",[24,11482,11484],{"id":11483},"重放暂停与错峰","重放、暂停与错峰",[29,11486,11488],{"className":375,"code":11487,"language":377,"meta":34,"style":34},"\u002F* 暂停：CSS 就能控制，不需要 JS 计时 *\u002F\n.paused .box { animation-play-state: paused; }\n\u002F* 重新触发同名动画：必须先移除、强制回流、再加回（JS 里的一行技巧） *\u002F\nel.classList.remove('run'); void el.offsetWidth; el.classList.add('run');\n\u002F* 错峰：把延迟交给变量，避免给每项写一条规则 *\u002F\n.item { animation-delay: calc(var(--i) * 80ms); }   \u002F* \u003Cli style=\"--i:2\"> *\u002F\n",[36,11489,11490,11495,11515,11520,11525,11530],{"__ignoreMap":34},[39,11491,11492],{"class":41,"line":42},[39,11493,11494],{"class":45},"\u002F* 暂停：CSS 就能控制，不需要 JS 计时 *\u002F\n",[39,11496,11497,11500,11503,11505,11508,11510,11513],{"class":41,"line":49},[39,11498,11499],{"class":60},".paused",[39,11501,11502],{"class":60}," .box",[39,11504,109],{"class":52},[39,11506,11507],{"class":112},"animation-play-state",[39,11509,116],{"class":52},[39,11511,11512],{"class":112},"paused",[39,11514,779],{"class":52},[39,11516,11517],{"class":41,"line":82},[39,11518,11519],{"class":45},"\u002F* 重新触发同名动画：必须先移除、强制回流、再加回（JS 里的一行技巧） *\u002F\n",[39,11521,11522],{"class":41,"line":89},[39,11523,11524],{"class":52},"el.classList.remove('run'); void el.offsetWidth; el.classList.add('run');\n",[39,11526,11527],{"class":41,"line":95},[39,11528,11529],{"class":45},"\u002F* 错峰：把延迟交给变量，避免给每项写一条规则 *\u002F\n",[39,11531,11532,11534,11536,11538,11540,11542,11544,11546,11548,11550,11552,11554,11556,11558,11560],{"class":41,"line":147},[39,11533,8165],{"class":60},[39,11535,109],{"class":52},[39,11537,11398],{"class":112},[39,11539,116],{"class":52},[39,11541,6382],{"class":112},[39,11543,173],{"class":52},[39,11545,3451],{"class":112},[39,11547,173],{"class":52},[39,11549,11411],{"class":1865},[39,11551,1033],{"class":52},[39,11553,743],{"class":122},[39,11555,11422],{"class":112},[39,11557,1684],{"class":122},[39,11559,7596],{"class":52},[39,11561,11562],{"class":45},"\u002F* \u003Cli style=\"--i:2\"> *\u002F\n",[24,11564,11566,11568],{"id":11565},"will-change先测量再加",[36,11567,6234],{},"：先测量再加",[29,11570,11572],{"className":375,"code":11571,"language":377,"meta":34,"style":34},".box { will-change: transform; }   \u002F* 提前把元素提升为合成层，避免动画开始时建层卡顿 *\u002F\n",[36,11573,11574],{"__ignoreMap":34},[39,11575,11576,11579,11581,11583,11586],{"class":41,"line":42},[39,11577,11578],{"class":60},".box",[39,11580,109],{"class":52},[39,11582,6234],{"class":112},[39,11584,11585],{"class":52},": transform; }   ",[39,11587,11588],{"class":45},"\u002F* 提前把元素提升为合成层，避免动画开始时建层卡顿 *\u002F\n",[15,11590,11591,11592,1331,11594,11596],{},"三条纪律：只给「马上要动」的元素加（每个合成层都吃显存，几十层就负收益）；动画结束后移除；现代内核已经会对 ",[36,11593,1370],{},[36,11595,1367],{}," 动画自动分层，实测收益常为零——先用 DevTools 的 Rendering（Paint flashing）与 Layers 面板确认再决定。",[15,11598,11599,11600,11602,11603,11605,11606,11609,11610,11612],{},"副作用要记住：",[36,11601,6234],{}," 会创建",[19,11604,6302],{},"与",[19,11607,11608],{},"包含块","，可能改变 ",[36,11611,5933],{}," 的参考系（第十二章）。",[24,11614,11616],{"id":11615},"滚动驱动动画新增能力","滚动驱动动画（新增能力）",[29,11618,11620],{"className":375,"code":11619,"language":377,"meta":34,"style":34},".bar { animation: grow linear both; animation-timeline: scroll(self); }\n\u002F* 也可以用命名滚动轴或元素可见度：animation-timeline: view(block 20% 60%) *\u002F\n",[36,11621,11622,11651],{"__ignoreMap":34},[39,11623,11624,11626,11628,11630,11633,11636,11638,11640,11643,11645,11648],{"class":41,"line":42},[39,11625,7959],{"class":60},[39,11627,109],{"class":52},[39,11629,11309],{"class":112},[39,11631,11632],{"class":52},": grow ",[39,11634,11635],{"class":112},"linear",[39,11637,11393],{"class":112},[39,11639,126],{"class":52},[39,11641,11642],{"class":112},"animation-timeline",[39,11644,116],{"class":52},[39,11646,11647],{"class":112},"scroll",[39,11649,11650],{"class":52},"(self); }\n",[39,11652,11653],{"class":41,"line":49},[39,11654,11655],{"class":45},"\u002F* 也可以用命名滚动轴或元素可见度：animation-timeline: view(block 20% 60%) *\u002F\n",[15,11657,11658,11659,11662],{},"浏览器基线：滚动驱动动画目前在 Chromium 系（Chrome\u002FEdge 115+）可用，Safari\u002FFirefox 仍在演进，属渐进增强——",[19,11660,11661],{},"必须保证「动画不跑时视图也成立」","（例如进度条不跑时停在 0，而不是盖住内容）。落笔与上线前请以 caniuse 当前数据为准。",[24,11664,11665],{"id":11665},"动效的三条纪律",[316,11667,11668,11674,11683],{},[319,11669,11670,11673],{},[19,11671,11672],{},"只用于解释变化","（位置、状态、加载进度），装饰性动效一律从简；时长 150–300ms 足够，超过 500ms 就会被感知为「慢」。",[319,11675,11676,676,11679,11682],{},[19,11677,11678],{},"必须提供降级",[36,11680,11681],{},"@media (prefers-reduced-motion: reduce)"," 下关闭无限循环、把位移换成淡入（第十三章的全站写法）。",[319,11684,11685,11688],{},[19,11686,11687],{},"不要同时动很多个大面积元素","：性能与注意力都是有限资源。",[10,11690,11692],{"id":11691},"十九视觉进阶渐变滤镜遮罩与混合","十九、视觉进阶：渐变、滤镜、遮罩与混合",[15,11694,11695,11696,11699,11700,11702],{},"这一章的工具全部服务于同一句话：",[19,11697,11698],{},"让「不需要作为内容存在」的视觉，不用图片也能做出来","。反过来也是判断标准——如果一块视觉承载了信息（截图、图表、产品图），它就该是 ",[36,11701,3076],{}," 而不是 CSS。",[304,11704],{"height":8360,"src":11705,"title":11706},"\u002Ftutorials\u002Fcss\u002Fdemos\u002F19-visual-fx.html","示例 19：conic\u002Fradial 渐变、filter\u002Fbackdrop-filter、mask 与 clip-path、blend",[24,11708,11710],{"id":11709},"渐变从线性到锥形","渐变：从线性到锥形",[15,11712,11713],{},"四种函数构成全部渐变能力：",[29,11715,11717],{"className":375,"code":11716,"language":377,"meta":34,"style":34},"linear-gradient(135deg, #0969da, #8250df)                      \u002F* 角度或关键词 *\u002F\nradial-gradient(circle at 30% 30%, #fff 0 8%, #0969da 30%)     \u002F* 形状 + 圆心 + 色标区间 *\u002F\nconic-gradient(from 45deg at 50% 50%, red, gold, green, red)   \u002F* 绕一圈，色相环\u002F饼图 *\u002F\nrepeating-linear-gradient(...) \u002F repeating-conic-gradient(...) \u002F* 重复，条纹\u002F放射纹 *\u002F\n",[36,11718,11719,11735,11758,11766],{"__ignoreMap":34},[39,11720,11721,11724,11726,11728,11730,11732],{"class":41,"line":42},[39,11722,11723],{"class":52},"linear-gradient(135deg, ",[39,11725,1698],{"class":1697},[39,11727,392],{"class":52},[39,11729,3141],{"class":1697},[39,11731,1080],{"class":52},[39,11733,11734],{"class":45},"\u002F* 角度或关键词 *\u002F\n",[39,11736,11737,11740,11742,11745,11747,11750,11752,11755],{"class":41,"line":49},[39,11738,11739],{"class":52},"radial-gradient(",[39,11741,3229],{"class":56},[39,11743,11744],{"class":52}," at 30% 30%, ",[39,11746,1871],{"class":60},[39,11748,11749],{"class":52}," 0 8%, ",[39,11751,1698],{"class":1697},[39,11753,11754],{"class":52}," 30%)     ",[39,11756,11757],{"class":45},"\u002F* 形状 + 圆心 + 色标区间 *\u002F\n",[39,11759,11760,11763],{"class":41,"line":82},[39,11761,11762],{"class":52},"conic-gradient(from 45deg at 50% 50%, red, gold, green, red)   ",[39,11764,11765],{"class":45},"\u002F* 绕一圈，色相环\u002F饼图 *\u002F\n",[39,11767,11768,11771],{"class":41,"line":89},[39,11769,11770],{"class":52},"repeating-linear-gradient(...) \u002F repeating-conic-gradient(...) ",[39,11772,11773],{"class":45},"\u002F* 重复，条纹\u002F放射纹 *\u002F\n",[15,11775,11776],{},"两个立刻能用的配方：",[29,11778,11780],{"className":375,"code":11779,"language":377,"meta":34,"style":34},"\u002F* 硬切色带：同一位置写两次色标 → 进度条、双色块 *\u002F\n.progress { background: linear-gradient(90deg, var(--brand-500) 62%, var(--bg-3) 62%); }\n\n\u002F* 环形进度：conic 上色 + mask 挖中心，纯 CSS 无 SVG *\u002F\n.ring { aspect-ratio: 1; border-radius: 50%;\n        background: conic-gradient(var(--brand-500) 0 var(--pct), var(--bg-3) var(--pct) 100%);\n        mask: radial-gradient(circle, transparent 0 55%, #000 56%); }\n",[36,11781,11782,11787,11836,11840,11845,11870,11922],{"__ignoreMap":34},[39,11783,11784],{"class":41,"line":42},[39,11785,11786],{"class":45},"\u002F* 硬切色带：同一位置写两次色标 → 进度条、双色块 *\u002F\n",[39,11788,11789,11791,11793,11795,11797,11799,11801,11803,11805,11807,11809,11811,11813,11815,11817,11819,11821,11823,11825,11828,11830,11832,11834],{"class":41,"line":49},[39,11790,3432],{"class":60},[39,11792,109],{"class":52},[39,11794,1347],{"class":112},[39,11796,116],{"class":52},[39,11798,3125],{"class":112},[39,11800,173],{"class":52},[39,11802,3130],{"class":112},[39,11804,1663],{"class":122},[39,11806,392],{"class":52},[39,11808,3451],{"class":112},[39,11810,173],{"class":52},[39,11812,7346],{"class":1865},[39,11814,1033],{"class":52},[39,11816,3460],{"class":112},[39,11818,1552],{"class":122},[39,11820,392],{"class":52},[39,11822,3451],{"class":112},[39,11824,173],{"class":52},[39,11826,11827],{"class":1865},"--bg-3",[39,11829,1033],{"class":52},[39,11831,3460],{"class":112},[39,11833,1552],{"class":122},[39,11835,3475],{"class":52},[39,11837,11838],{"class":41,"line":82},[39,11839,86],{"emptyLinePlaceholder":85},[39,11841,11842],{"class":41,"line":89},[39,11843,11844],{"class":45},"\u002F* 环形进度：conic 上色 + mask 挖中心，纯 CSS 无 SVG *\u002F\n",[39,11846,11847,11850,11852,11854,11856,11858,11860,11862,11864,11866,11868],{"class":41,"line":95},[39,11848,11849],{"class":60},".ring",[39,11851,109],{"class":52},[39,11853,6826],{"class":112},[39,11855,116],{"class":52},[39,11857,2017],{"class":112},[39,11859,126],{"class":52},[39,11861,3615],{"class":112},[39,11863,116],{"class":52},[39,11865,6066],{"class":112},[39,11867,1552],{"class":122},[39,11869,427],{"class":52},[39,11871,11872,11875,11877,11880,11882,11884,11886,11888,11890,11892,11894,11896,11898,11900,11902,11904,11906,11908,11910,11912,11914,11916,11918,11920],{"class":41,"line":147},[39,11873,11874],{"class":112},"        background",[39,11876,116],{"class":52},[39,11878,11879],{"class":112},"conic-gradient",[39,11881,173],{"class":52},[39,11883,3451],{"class":112},[39,11885,173],{"class":52},[39,11887,7346],{"class":1865},[39,11889,1033],{"class":52},[39,11891,134],{"class":112},[39,11893,3876],{"class":112},[39,11895,173],{"class":52},[39,11897,7964],{"class":1865},[39,11899,3269],{"class":52},[39,11901,3451],{"class":112},[39,11903,173],{"class":52},[39,11905,11827],{"class":1865},[39,11907,1033],{"class":52},[39,11909,3451],{"class":112},[39,11911,173],{"class":52},[39,11913,7964],{"class":1865},[39,11915,1033],{"class":52},[39,11917,1995],{"class":112},[39,11919,1552],{"class":122},[39,11921,3144],{"class":52},[39,11923,11924,11927,11929,11932,11934,11936,11938,11940,11942,11945,11947,11949,11952,11955,11957],{"class":41,"line":152},[39,11925,11926],{"class":112},"        mask",[39,11928,116],{"class":52},[39,11930,11931],{"class":112},"radial-gradient",[39,11933,173],{"class":52},[39,11935,3229],{"class":112},[39,11937,392],{"class":52},[39,11939,3176],{"class":112},[39,11941,3509],{"class":112},[39,11943,11944],{"class":112}," 55",[39,11946,1552],{"class":122},[39,11948,392],{"class":52},[39,11950,11951],{"class":112},"#000",[39,11953,11954],{"class":112}," 56",[39,11956,1552],{"class":122},[39,11958,3475],{"class":52},[15,11960,11961,11962,11964],{},"多层渐变叠加是「有质感的封面」的标准做法：一层径向高光 + 一层细密纹理 + 一层底色渐变，配合 ",[36,11963,3396],{}," 决定层间混合方式（本章示例最后那个 hero 就是三层）。",[24,11966,11968,11970],{"id":11967},"filter改自己的绘制结果",[36,11969,6219],{},"：改自己的绘制结果",[29,11972,11974],{"className":375,"code":11973,"language":377,"meta":34,"style":34},"filter: grayscale(1) saturate(1.6) blur(2px) drop-shadow(3px 4px 0 rgba(9,105,218,.5));\n",[36,11975,11976],{"__ignoreMap":34},[39,11977,11978],{"class":41,"line":42},[39,11979,11973],{"class":52},[434,11981,11982,12015,12026],{},[319,11983,11984,11985,1223,11988,1223,11991,1223,11994,1223,11997,1223,12000,1223,12003,1223,12006,1223,12009,1223,12012,672],{},"可用函数：",[36,11986,11987],{},"blur()",[36,11989,11990],{},"brightness()",[36,11992,11993],{},"contrast()",[36,11995,11996],{},"grayscale()",[36,11998,11999],{},"hue-rotate()",[36,12001,12002],{},"invert()",[36,12004,12005],{},"opacity()",[36,12007,12008],{},"saturate()",[36,12010,12011],{},"sepia()",[36,12013,12014],{},"drop-shadow()",[319,12016,12017,1416,12019,12021,12022,12025],{},[36,12018,12014],{},[36,12020,3697],{}," 的区别：前者贴着",[19,12023,12024],{},"透明轮廓","画，适合异形\u002F带透明通道的图片，后者只按矩形盒子；",[319,12027,12028,12029,12031,12032,12034,12035,12037],{},"三个副作用：创建",[19,12030,6302],{},"（第十二章）、改变 ",[36,12033,5933],{}," 的参考系、动画 ",[36,12036,6219],{}," 成本高（模糊半径变化要重绘）。",[15,12039,12040,12041,12044,12045,12047],{},"实用配方：禁用态 ",[36,12042,12043],{},"grayscale(1) + opacity(.6)","；hover 轻微提饱和比加遮罩更省；缩略图统一色调用 ",[36,12046,6219],{}," 而不是重新处理图片。",[24,12049,12051,12053],{"id":12050},"backdrop-filter毛玻璃",[36,12052,6222],{},"：毛玻璃",[29,12055,12057],{"className":375,"code":12056,"language":377,"meta":34,"style":34},".glass { background: rgba(255,255,255,.18);\n         backdrop-filter: blur(6px) saturate(1.4);\n         -webkit-backdrop-filter: blur(6px) saturate(1.4);\n         border: 1px solid rgba(255,255,255,.35); }\n",[36,12058,12059,12090,12117,12142],{"__ignoreMap":34},[39,12060,12061,12064,12066,12068,12070,12072,12074,12076,12078,12080,12082,12084,12086,12088],{"class":41,"line":42},[39,12062,12063],{"class":60},".glass",[39,12065,109],{"class":52},[39,12067,1347],{"class":112},[39,12069,116],{"class":52},[39,12071,3247],{"class":112},[39,12073,173],{"class":52},[39,12075,3252],{"class":112},[39,12077,3255],{"class":52},[39,12079,3252],{"class":112},[39,12081,3255],{"class":52},[39,12083,3252],{"class":112},[39,12085,3255],{"class":52},[39,12087,4196],{"class":112},[39,12089,3144],{"class":52},[39,12091,12092,12095,12097,12100,12102,12104,12106,12108,12111,12113,12115],{"class":41,"line":49},[39,12093,12094],{"class":112},"         backdrop-filter",[39,12096,116],{"class":52},[39,12098,12099],{"class":112},"blur",[39,12101,173],{"class":52},[39,12103,10413],{"class":112},[39,12105,123],{"class":122},[39,12107,1033],{"class":52},[39,12109,12110],{"class":112},"saturate",[39,12112,173],{"class":52},[39,12114,10647],{"class":112},[39,12116,3144],{"class":52},[39,12118,12119,12122,12124,12126,12128,12130,12132,12134,12136,12138,12140],{"class":41,"line":82},[39,12120,12121],{"class":112},"         -webkit-backdrop-filter",[39,12123,116],{"class":52},[39,12125,12099],{"class":112},[39,12127,173],{"class":52},[39,12129,10413],{"class":112},[39,12131,123],{"class":122},[39,12133,1033],{"class":52},[39,12135,12110],{"class":112},[39,12137,173],{"class":52},[39,12139,10647],{"class":112},[39,12141,3144],{"class":52},[39,12143,12144,12147,12149,12151,12153,12155,12157,12159,12161,12163,12165,12167,12169,12171,12173],{"class":41,"line":89},[39,12145,12146],{"class":112},"         border",[39,12148,116],{"class":52},[39,12150,2017],{"class":112},[39,12152,123],{"class":122},[39,12154,2022],{"class":112},[39,12156,3777],{"class":112},[39,12158,173],{"class":52},[39,12160,3252],{"class":112},[39,12162,3255],{"class":52},[39,12164,3252],{"class":112},[39,12166,3255],{"class":52},[39,12168,3252],{"class":112},[39,12170,3255],{"class":52},[39,12172,3266],{"class":112},[39,12174,3475],{"class":52},[15,12176,12177,12178,12181,12182,12184],{},"三条注意：需要 Safari 前缀；",[19,12179,12180],{},"背后必须有内容","才看得出效果（纯色底上等于白做）；大面积高斯模糊在低端设备上很贵，别给整页背景加。那条半透明 ",[36,12183,1337],{}," 是让玻璃「看得见边界」的关键，缺了它面板会糊成一片。",[24,12186,12188,1416,12190,12192],{"id":12187},"mask-与-clip-path软边界与硬边界",[36,12189,6228],{},[36,12191,4253],{},"：软边界与硬边界",[219,12194,12195,12209],{},[222,12196,12197],{},[225,12198,12199,12201,12205],{},[228,12200],{},[228,12202,12203],{},[36,12204,6228],{},[228,12206,12207],{},[36,12208,4253],{},[238,12210,12211,12222,12252],{},[225,12212,12213,12216,12219],{},[243,12214,12215],{},"表达",[243,12217,12218],{},"Alpha\u002F亮度决定「哪里可见」，可以有渐变过渡",[243,12220,12221],{},"几何裁剪，只有硬边界",[225,12223,12224,12226,12235],{},[243,12225,895],{},[243,12227,12228,12229,12231,12232,340],{},"与 ",[36,12230,1347],{}," 几乎一致（",[36,12233,12234],{},"mask-image\u002Fsize\u002Fposition\u002Frepeat",[243,12236,12237,1223,12240,1223,12243,1223,12246,1223,12249],{},[36,12238,12239],{},"inset()",[36,12241,12242],{},"circle()",[36,12244,12245],{},"ellipse()",[36,12247,12248],{},"polygon()",[36,12250,12251],{},"path()",[225,12253,12254,12256,12259],{},[243,12255,1514],{},[243,12257,12258],{},"图片右缘渐隐、用 SVG 当图标形状（颜色交给 CSS）",[243,12260,12261],{},"切角卡片、星形、hover 时从方到圆的形变",[29,12263,12265],{"className":375,"code":12264,"language":377,"meta":34,"style":34},".fade-out { mask: linear-gradient(90deg, #000 40%, transparent); }        \u002F* 列表末尾渐隐 *\u002F\n.icon { mask: url(star.svg) center\u002Fcontain no-repeat; background: currentColor; }  \u002F* 随文字色变化的图标 *\u002F\n.card { clip-path: polygon(0 0, 100% 0, 100% 70%, 70% 100%, 0 100%); }\n",[36,12266,12267,12303,12345],{"__ignoreMap":34},[39,12268,12269,12272,12274,12276,12278,12280,12282,12284,12286,12288,12290,12292,12294,12296,12298,12300],{"class":41,"line":42},[39,12270,12271],{"class":60},".fade-out",[39,12273,109],{"class":52},[39,12275,6228],{"class":112},[39,12277,116],{"class":52},[39,12279,3125],{"class":112},[39,12281,173],{"class":52},[39,12283,3130],{"class":112},[39,12285,1663],{"class":122},[39,12287,392],{"class":52},[39,12289,11951],{"class":112},[39,12291,3274],{"class":112},[39,12293,1552],{"class":122},[39,12295,392],{"class":52},[39,12297,3176],{"class":112},[39,12299,10086],{"class":52},[39,12301,12302],{"class":45},"\u002F* 列表末尾渐隐 *\u002F\n",[39,12304,12305,12308,12310,12312,12314,12316,12318,12321,12323,12325,12327,12329,12332,12334,12336,12338,12340,12342],{"class":41,"line":49},[39,12306,12307],{"class":60},".icon",[39,12309,109],{"class":52},[39,12311,6228],{"class":112},[39,12313,116],{"class":52},[39,12315,3033],{"class":112},[39,12317,173],{"class":52},[39,12319,12320],{"class":1865},"star.svg",[39,12322,1033],{"class":52},[39,12324,2684],{"class":112},[39,12326,1331],{"class":52},[39,12328,3066],{"class":112},[39,12330,12331],{"class":112}," no-repeat",[39,12333,126],{"class":52},[39,12335,1347],{"class":112},[39,12337,116],{"class":52},[39,12339,1836],{"class":112},[39,12341,2028],{"class":52},[39,12343,12344],{"class":45},"\u002F* 随文字色变化的图标 *\u002F\n",[39,12346,12347,12349,12351,12353,12355,12358,12360,12362,12364,12366,12368,12370,12372,12374,12376,12378,12381,12383,12385,12388,12390,12392,12394,12396,12398,12400,12402],{"class":41,"line":82},[39,12348,721],{"class":60},[39,12350,109],{"class":52},[39,12352,4253],{"class":112},[39,12354,116],{"class":52},[39,12356,12357],{"class":112},"polygon",[39,12359,173],{"class":52},[39,12361,134],{"class":112},[39,12363,3509],{"class":112},[39,12365,392],{"class":52},[39,12367,1995],{"class":112},[39,12369,1552],{"class":122},[39,12371,3509],{"class":112},[39,12373,392],{"class":52},[39,12375,1995],{"class":112},[39,12377,1552],{"class":122},[39,12379,12380],{"class":112}," 70",[39,12382,1552],{"class":122},[39,12384,392],{"class":52},[39,12386,12387],{"class":112},"70",[39,12389,1552],{"class":122},[39,12391,3379],{"class":112},[39,12393,1552],{"class":122},[39,12395,392],{"class":52},[39,12397,134],{"class":112},[39,12399,3379],{"class":112},[39,12401,1552],{"class":122},[39,12403,3475],{"class":52},[15,12405,12406,12407,12410,12411,12413],{},"两者都会创建层叠上下文，也都会",[19,12408,12409],{},"裁掉溢出内容与阴影","（第十二章的包含块规则同样适用）。",[36,12412,4253],{}," 在两个形状函数相同、点数一致时可以平滑过渡——这是形变动效的做法；无障碍角度注意：被裁掉的文字仍会被读屏念到，视觉信息丢失要自己兜住。",[24,12415,12417,1416,12420],{"id":12416},"mix-blend-mode-与-background-blend-mode",[36,12418,12419],{},"mix-blend-mode",[36,12421,3396],{},[29,12423,12425],{"className":375,"code":12424,"language":377,"meta":34,"style":34},".overlay { mix-blend-mode: multiply; }        \u002F* 与背后元素混合 *\u002F\n.bg { background-blend-mode: multiply; }      \u002F* 自己的多层背景之间混合 *\u002F\n",[36,12426,12427,12446],{"__ignoreMap":34},[39,12428,12429,12432,12434,12436,12438,12441,12443],{"class":41,"line":42},[39,12430,12431],{"class":60},".overlay",[39,12433,109],{"class":52},[39,12435,12419],{"class":112},[39,12437,116],{"class":52},[39,12439,12440],{"class":112},"multiply",[39,12442,2323],{"class":52},[39,12444,12445],{"class":45},"\u002F* 与背后元素混合 *\u002F\n",[39,12447,12448,12451,12453,12455,12457,12459,12461],{"class":41,"line":49},[39,12449,12450],{"class":60},".bg",[39,12452,109],{"class":52},[39,12454,3396],{"class":112},[39,12456,116],{"class":52},[39,12458,12440],{"class":112},[39,12460,9747],{"class":52},[39,12462,12463],{"class":45},"\u002F* 自己的多层背景之间混合 *\u002F\n",[15,12465,12466,12467,12469,12470,12473,12474,918,12477,12480,12481,918,12484,12487,12488,918,12491,12494],{},"常用值：",[36,12468,12440],{},"（变暗，适合阴影\u002F水印）、",[36,12471,12472],{},"screen","（变亮，适合光效）、",[36,12475,12476],{},"overlay",[36,12478,12479],{},"soft-light","（保对比的叠加）、",[36,12482,12483],{},"difference",[36,12485,12486],{},"exclusion","（反色文字）、",[36,12489,12490],{},"hue",[36,12492,12493],{},"luminosity","（给图片换色相）。",[15,12496,12497,12498,12503],{},"关键的一条：",[19,12499,12500,12501],{},"给混合区域加 ",[36,12502,6240],{},"，否则它会跟整个祖先背景混合，页面别处会出现莫名其妙的颜色变化（同时你也顺手创建了层叠上下文，见第十二章）。",[24,12505,12506],{"id":12506},"什么时候不要用这些",[316,12508,12509,12520,12528],{},[319,12510,12511,12512,2357,12514,12517,12518,2814],{},"首屏大图：仍然应该 ",[36,12513,3076],{},[36,12515,12516],{},"srcset","（能缓存、能裁切、能懒加载、有 ",[36,12519,3084],{},[319,12521,12522,12523,1416,12525,12527],{},"需要印刷\u002F导出 PDF 的视觉：",[36,12524,6219],{},[36,12526,6228],{}," 在打印管线里表现不一致；",[319,12529,12530,12531,1331,12533,12535],{},"大面积持续动画的 ",[36,12532,6219],{},[36,12534,6222],{},"：低端设备掉帧明显（第十八章的性能原则）。",[10,12537,12539,12540,12542],{"id":12538},"二十容器查询supports-与调试排错","二十、容器查询、",[36,12541,8494],{}," 与调试排错",[304,12544],{"height":5840,"src":12545,"title":12546},"\u002Ftutorials\u002Fcss\u002Fdemos\u002F20a-container-queries.html","示例 20a：container-type、@container、cqi 单位与 :has() 组合",[24,12548,12549],{"id":12549},"两条语句就够",[29,12551,12553],{"className":375,"code":12552,"language":377,"meta":34,"style":34},"\u002F* 一、把某个祖先声明为查询容器 *\u002F\n.card-zone { container-type: inline-size; container-name: cardzone; }\n\u002F* 二、子树内部按它的尺寸写规则（查询的是祖先，样式给后代） *\u002F\n@container cardzone (min-width: 340px) { .media { grid-template-columns: 128px 1fr; } }\n",[36,12554,12555,12560,12579,12584],{"__ignoreMap":34},[39,12556,12557],{"class":41,"line":42},[39,12558,12559],{"class":45},"\u002F* 一、把某个祖先声明为查询容器 *\u002F\n",[39,12561,12562,12565,12567,12570,12573,12576],{"class":41,"line":49},[39,12563,12564],{"class":60},".card-zone",[39,12566,109],{"class":52},[39,12568,12569],{"class":112},"container-type",[39,12571,12572],{"class":52},": inline-size; ",[39,12574,12575],{"class":112},"container-name",[39,12577,12578],{"class":52},": cardzone; }\n",[39,12580,12581],{"class":41,"line":82},[39,12582,12583],{"class":45},"\u002F* 二、子树内部按它的尺寸写规则（查询的是祖先，样式给后代） *\u002F\n",[39,12585,12586,12588,12591,12594,12596,12598,12600,12603,12605,12607,12609],{"class":41,"line":89},[39,12587,9349],{"class":122},[39,12589,12590],{"class":52}," cardzone (min-width: 340px) { ",[39,12592,12593],{"class":60},".media",[39,12595,109],{"class":52},[39,12597,5177],{"class":112},[39,12599,116],{"class":52},[39,12601,12602],{"class":112},"128",[39,12604,123],{"class":122},[39,12606,3741],{"class":112},[39,12608,1619],{"class":122},[39,12610,6712],{"class":52},[15,12612,12613,12614,12616,12617,590],{},"也可以不写 ",[36,12615,12575],{},"（匿名容器），但同名查询会命中「最近的」容器，跨组件复用时容易串味——给容器命名是更稳的习惯。简写形式：",[36,12618,12619],{},"container: inline-size \u002F cardzone;",[15,12621,12622,12623,12626],{},"它的价值：同一张卡片放进侧栏（窄）、主区（中）、整页 banner（宽），",[19,12624,12625],{},"组件源码完全相同","，表现由容器决定。媒体查询回答「屏幕多大」，容器查询回答「我被放进多大的地方」——后者才是组件级响应式。",[24,12628,12630,12632],{"id":12629},"container-type-的三个值与代价",[36,12631,12569],{}," 的三个值与代价",[219,12634,12635,12647],{},[222,12636,12637],{},[225,12638,12639,12641,12644],{},[228,12640,5858],{},[228,12642,12643],{},"可查询",[228,12645,12646],{},"副作用",[238,12648,12649,12665,12679],{},[225,12650,12651,12656,12659],{},[243,12652,12653],{},[36,12654,12655],{},"inline-size",[243,12657,12658],{},"只有宽度轴",[243,12660,12661,12664],{},[19,12662,12663],{},"最常用","：不影响自身高度，不会产生循环依赖",[225,12666,12667,12671,12674],{},[243,12668,12669],{},[36,12670,2615],{},[243,12672,12673],{},"两个轴",[243,12675,12676,12677],{},"容器高度必须与内容无关（否则「内容决定高度、高度又决定内容」）——通常要显式给 ",[36,12678,1343],{},[225,12680,12681,12686,12689],{},[243,12682,12683],{},[36,12684,12685],{},"normal",[243,12687,12688],{},"不查询",[243,12690,12691],{},"默认，取消容器身份",[15,12693,12694,12695,4390,12697,12699,12700,12703,12704,1831],{},"另外两条必须知道：",[36,12696,12569],{},[36,12698,12685],{}," 时，元素会建立",[19,12701,12702],{},"独立格式化上下文","（内部 margin 不再与外部塌陷，见第九章），并成为绝对定位后代的",[19,12705,11608],{},[24,12707,12709,12710,918,12713,918,12716,918,12719],{"id":12708},"容器单位cqi-cqb-cqmin-cqmax","容器单位：",[36,12711,12712],{},"cqi",[36,12714,12715],{},"cqb",[36,12717,12718],{},"cqmin",[36,12720,12721],{},"cqmax",[29,12723,12725],{"className":375,"code":12724,"language":377,"meta":34,"style":34},".title { font-size: 8cqi; }   \u002F* 字号相对容器宽度的 1% *\u002F\n.card  { padding: 2cqi; }\n",[36,12726,12727,12746],{"__ignoreMap":34},[39,12728,12729,12731,12733,12735,12737,12739,12741,12743],{"class":41,"line":42},[39,12730,395],{"class":60},[39,12732,109],{"class":52},[39,12734,2536],{"class":112},[39,12736,116],{"class":52},[39,12738,4853],{"class":112},[39,12740,12712],{"class":122},[39,12742,3661],{"class":52},[39,12744,12745],{"class":45},"\u002F* 字号相对容器宽度的 1% *\u002F\n",[39,12747,12748,12750,12752,12754,12756,12758,12760],{"class":41,"line":49},[39,12749,721],{"class":60},[39,12751,3759],{"class":52},[39,12753,1334],{"class":112},[39,12755,116],{"class":52},[39,12757,2313],{"class":112},[39,12759,12712],{"class":122},[39,12761,779],{"class":52},[219,12763,12764,12772],{},[222,12765,12766],{},[225,12767,12768,12770],{},[228,12769,1508],{},[228,12771,1511],{},[238,12773,12774,12787,12804,12817],{},[225,12775,12776,12780],{},[243,12777,12778],{},[36,12779,12712],{},[243,12781,12782,12783,12786],{},"容器",[19,12784,12785],{},"内联轴","（水平书写模式下 = 宽度）的 1%",[225,12788,12789,12793],{},[243,12790,12791],{},[36,12792,12715],{},[243,12794,12782,12795,12798,12799,1793,12802],{},[19,12796,12797],{},"块轴","（= 高度）的 1%，需要 ",[36,12800,12801],{},"container-type: size",[36,12803,3925],{},[225,12805,12806,12814],{},[243,12807,12808,918,12811],{},[36,12809,12810],{},"cqw",[36,12812,12813],{},"cqh",[243,12815,12816],{},"宽度 \u002F 高度的 1%",[225,12818,12819,12825],{},[243,12820,12821,918,12823],{},[36,12822,12718],{},[36,12824,12721],{},[243,12826,12827],{},"两者中较小 \u002F 较大者的 1%",[15,12829,12228,12830,12832,12833,12835,12836,12838,12839,12842,12843,12845,12846,12848],{},[36,12831,1569],{}," 的关系一句话：",[36,12834,1569],{}," 相对视口，",[36,12837,12712],{}," 相对最近的尺寸容器——",[19,12840,12841],{},"组件内部一律用后者","（第十三章的 ",[36,12844,6947],{}," 适合页面级排版，",[36,12847,12712],{}," 适合组件内）。",[24,12850,12851],{"id":12851},"与媒体查询的分工",[219,12853,12854,12864],{},[222,12855,12856],{},[225,12857,12858,12861],{},[228,12859,12860],{},"问题",[228,12862,12863],{},"用什么",[238,12865,12866,12876,12885,12896,12905],{},[225,12867,12868,12871],{},[243,12869,12870],{},"整页骨架变化（三栏 → 一栏、导航 → 汉堡）",[243,12872,12873,12875],{},[36,12874,6578],{},"：这是页面级事实，只有视口能回答",[225,12877,12878,12881],{},[243,12879,12880],{},"组件在不同槽位里的形态",[243,12882,12883],{},[36,12884,9349],{},[225,12886,12887,12890],{},[243,12888,12889],{},"卡片墙要几列",[243,12891,12892,12895],{},[36,12893,12894],{},"auto-fit + minmax()","（第十一章），能不用查询就不用",[225,12897,12898,12901],{},[243,12899,12900],{},"字号随所在容器缩放",[243,12902,12903],{},[36,12904,12712],{},[225,12906,12907,12910],{},[243,12908,12909],{},"系统偏好（深浅色、减少动效、指针类型）",[243,12911,12912,12914],{},[36,12913,6578],{}," 特性查询（第十三章）",[15,12916,12917],{},"三者可以叠加：外层媒体查询定骨架，内层容器查询定组件形态。",[24,12919,12228,12921,12923],{"id":12920},"与-has-组合能替掉一大类-js",[36,12922,8501],{}," 组合，能替掉一大类 JS",[29,12925,12927],{"className":375,"code":12926,"language":377,"meta":34,"style":34},"@container (min-width: 420px) {\n  .list { grid-auto-flow: column; grid-auto-columns: 1fr; }\n  .list:has(> :nth-child(4)) { grid-auto-flow: row; grid-template-columns: repeat(2, 1fr); }\n}\n",[36,12928,12929,12936,12962,13007],{"__ignoreMap":34},[39,12930,12931,12933],{"class":41,"line":42},[39,12932,9349],{"class":122},[39,12934,12935],{"class":52}," (min-width: 420px) {\n",[39,12937,12938,12941,12943,12945,12947,12949,12951,12954,12956,12958,12960],{"class":41,"line":49},[39,12939,12940],{"class":60},"  .list",[39,12942,109],{"class":52},[39,12944,5292],{"class":112},[39,12946,116],{"class":52},[39,12948,4493],{"class":112},[39,12950,126],{"class":52},[39,12952,12953],{"class":112},"grid-auto-columns",[39,12955,116],{"class":52},[39,12957,2017],{"class":112},[39,12959,1619],{"class":122},[39,12961,779],{"class":52},[39,12963,12964,12967,12969,12971,12974,12976,12978,12981,12983,12985,12987,12989,12991,12993,12995,12997,12999,13001,13003,13005],{"class":41,"line":82},[39,12965,12966],{"class":60},"  .list:has",[39,12968,173],{"class":52},[39,12970,866],{"class":122},[39,12972,12973],{"class":60}," :nth-child",[39,12975,173],{"class":52},[39,12977,3593],{"class":112},[39,12979,12980],{"class":52},")) { ",[39,12982,5292],{"class":112},[39,12984,116],{"class":52},[39,12986,4502],{"class":112},[39,12988,126],{"class":52},[39,12990,5177],{"class":112},[39,12992,116],{"class":52},[39,12994,3004],{"class":112},[39,12996,173],{"class":52},[39,12998,2313],{"class":112},[39,13000,392],{"class":52},[39,13002,2017],{"class":112},[39,13004,1619],{"class":122},[39,13006,3475],{"class":52},[39,13008,13009],{"class":41,"line":89},[39,13010,432],{"class":52},[15,13012,13013],{},"「容器够宽就横排，但项数 ≥4 时改成两列」——这条需求两年前必须写 JS，现在是两条 CSS 规则。",[304,13015],{"height":5840,"src":13016,"title":13017},"\u002Ftutorials\u002Fcss\u002Fdemos\u002F20b-supports-debug.html","示例 20b：@supports 能力检测、DevTools 四面板与常见坑现场",[24,13019,13021,13023],{"id":13020},"supports测试的是声明不是特性名",[36,13022,8494],{},"：测试的是「声明」，不是「特性名」",[29,13025,13027],{"className":375,"code":13026,"language":377,"meta":34,"style":34},"@supports (display: grid) { … }\n@supports (position: sticky) { … }\n@supports (display: grid) and (not (display: subgrid)) { … }\n@supports selector(:has(*)) { … }      \u002F* 选择器支持测试：参数是选择器而不是声明 *\u002F\n",[36,13028,13029,13043,13057,13090],{"__ignoreMap":34},[39,13030,13031,13033,13035,13037,13039,13041],{"class":41,"line":42},[39,13032,8494],{"class":122},[39,13034,6581],{"class":52},[39,13036,1350],{"class":112},[39,13038,116],{"class":52},[39,13040,1360],{"class":112},[39,13042,8443],{"class":52},[39,13044,13045,13047,13049,13051,13053,13055],{"class":41,"line":49},[39,13046,8494],{"class":122},[39,13048,6581],{"class":52},[39,13050,1353],{"class":112},[39,13052,116],{"class":52},[39,13054,5948],{"class":112},[39,13056,8443],{"class":52},[39,13058,13059,13061,13063,13065,13067,13069,13071,13074,13076,13079,13081,13083,13085,13087],{"class":41,"line":82},[39,13060,8494],{"class":122},[39,13062,6581],{"class":52},[39,13064,1350],{"class":112},[39,13066,116],{"class":52},[39,13068,1360],{"class":112},[39,13070,1033],{"class":52},[39,13072,13073],{"class":122},"and",[39,13075,6581],{"class":52},[39,13077,13078],{"class":122},"not",[39,13080,6581],{"class":52},[39,13082,1350],{"class":112},[39,13084,116],{"class":52},[39,13086,5623],{"class":112},[39,13088,13089],{"class":52},")) { … }\n",[39,13091,13092,13094,13097,13099,13101,13103,13106],{"class":41,"line":89},[39,13093,8494],{"class":122},[39,13095,13096],{"class":52}," selector(",[39,13098,8562],{"class":60},[39,13100,173],{"class":52},[39,13102,743],{"class":56},[39,13104,13105],{"class":52},")) { … }      ",[39,13107,13108],{"class":45},"\u002F* 选择器支持测试：参数是选择器而不是声明 *\u002F\n",[15,13110,13111],{},"浏览器会去解析括号里的声明块，能接受就命中——所以判断准确率高，不需要维护特性名表。三个边界要知道：",[434,13113,13114,13120,13127],{},[319,13115,13116,13117,672],{},"它只判断「语法是否被接受」，",[19,13118,13119],{},"不判断实现是否有 bug 或只是部分支持",[319,13121,13122,13123,13126],{},"判断不了前缀差异（老 Safari 的 ",[36,13124,13125],{},"-webkit-"," 写法要并列写两份测试）；",[319,13128,13129,13130,590],{},"不支持时整块规则被丢弃，因此",[19,13131,13132],{},"默认（基线）样式必须自身成立",[15,13134,13135],{},"三种写法模式：",[29,13137,13139],{"className":375,"code":13138,"language":377,"meta":34,"style":34},"\u002F* A. 基线 + 增强（推荐） *\u002F\n.bar { display: flex; gap: 8px; }\n@supports (container-type: inline-size) { .zone { container-type: inline-size; } }\n\n\u002F* B. 新方案 + 显式降级 *\u002F\n.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }\n@supports not (display: grid) { .grid > * { display: inline-block; width: 48%; } }\n",[36,13140,13141,13146,13170,13191,13195,13200,13244],{"__ignoreMap":34},[39,13142,13143],{"class":41,"line":42},[39,13144,13145],{"class":45},"\u002F* A. 基线 + 增强（推荐） *\u002F\n",[39,13147,13148,13150,13152,13154,13156,13158,13160,13162,13164,13166,13168],{"class":41,"line":49},[39,13149,7959],{"class":60},[39,13151,109],{"class":52},[39,13153,1350],{"class":112},[39,13155,116],{"class":52},[39,13157,1357],{"class":112},[39,13159,126],{"class":52},[39,13161,2224],{"class":112},[39,13163,116],{"class":52},[39,13165,4853],{"class":112},[39,13167,123],{"class":122},[39,13169,779],{"class":52},[39,13171,13172,13174,13176,13178,13181,13184,13186,13188],{"class":41,"line":82},[39,13173,8494],{"class":122},[39,13175,6581],{"class":52},[39,13177,12569],{"class":112},[39,13179,13180],{"class":52},": inline-size) { ",[39,13182,13183],{"class":60},".zone",[39,13185,109],{"class":52},[39,13187,12569],{"class":112},[39,13189,13190],{"class":52},": inline-size; } }\n",[39,13192,13193],{"class":41,"line":89},[39,13194,86],{"emptyLinePlaceholder":85},[39,13196,13197],{"class":41,"line":95},[39,13198,13199],{"class":45},"\u002F* B. 新方案 + 显式降级 *\u002F\n",[39,13201,13202,13205,13207,13209,13211,13213,13215,13217,13219,13221,13223,13225,13227,13229,13231,13234,13236,13238,13240,13242],{"class":41,"line":147},[39,13203,13204],{"class":60},".grid",[39,13206,109],{"class":52},[39,13208,1350],{"class":112},[39,13210,116],{"class":52},[39,13212,1360],{"class":112},[39,13214,126],{"class":52},[39,13216,5177],{"class":112},[39,13218,116],{"class":52},[39,13220,3004],{"class":112},[39,13222,173],{"class":52},[39,13224,5494],{"class":112},[39,13226,392],{"class":52},[39,13228,5536],{"class":112},[39,13230,173],{"class":52},[39,13232,13233],{"class":112},"150",[39,13235,123],{"class":122},[39,13237,392],{"class":52},[39,13239,2017],{"class":112},[39,13241,1619],{"class":122},[39,13243,9011],{"class":52},[39,13245,13246,13248,13251,13253,13255,13257,13259,13261,13263,13265,13267,13269,13271,13273,13275,13277,13279,13281,13283,13285],{"class":41,"line":152},[39,13247,8494],{"class":122},[39,13249,13250],{"class":122}," not",[39,13252,6581],{"class":52},[39,13254,1350],{"class":112},[39,13256,116],{"class":52},[39,13258,1360],{"class":112},[39,13260,6693],{"class":52},[39,13262,13204],{"class":60},[39,13264,812],{"class":122},[39,13266,8928],{"class":56},[39,13268,109],{"class":52},[39,13270,1350],{"class":112},[39,13272,116],{"class":52},[39,13274,3931],{"class":112},[39,13276,126],{"class":52},[39,13278,1340],{"class":112},[39,13280,116],{"class":52},[39,13282,5371],{"class":112},[39,13284,1552],{"class":122},[39,13286,6712],{"class":52},[24,13288,13290],{"id":13289},"devtools-四面板各自回答什么问题","DevTools 四面板：各自回答什么问题",[219,13292,13293,13306],{},[222,13294,13295],{},[225,13296,13297,13300,13303],{},[228,13298,13299],{},"面板",[228,13301,13302],{},"回答",[228,13304,13305],{},"最有用的三个动作",[238,13307,13308,13324,13343,13356],{},[225,13309,13310,13315,13318],{},[243,13311,13312],{},[19,13313,13314],{},"Styles",[243,13316,13317],{},"「哪条规则胜出、为什么」",[243,13319,13320,13321,13323],{},"逐条取消勾选看变化；看被划掉的声明与旁边的警告图标；展开 ",[36,13322,1091],{},"、层名（第十六章）与优先级数字",[225,13325,13326,13330,13333],{},[243,13327,13328],{},[19,13329,1469],{},[243,13331,13332],{},"「最终计算值是多少」",[243,13334,13335,13336,13339,13340,13342],{},"看盒子图（margin\u002Fborder\u002Fpadding\u002Fcontent 各层实测像素，第六章）；",[36,13337,13338],{},"Ctrl+F"," 搜属性；展开 ",[36,13341,1860],{}," 看变量解析结果",[225,13344,13345,13350,13353],{},[243,13346,13347],{},[19,13348,13349],{},"Layout",[243,13351,13352],{},"「几何问题出在哪」",[243,13354,13355],{},"开启 sticky \u002F scroll-overflow \u002F Grid overlay，直接看轨道尺寸与被吸住的元素",[225,13357,13358,13363,13366],{},[243,13359,13360],{},[19,13361,13362],{},"Rendering",[243,13364,13365],{},"「性能与状态」",[243,13367,13368,13371,13372,1416,13375],{},[36,13369,13370],{},"Paint flashing","（绿闪=重绘）、Layers（合成层）、模拟 ",[36,13373,13374],{},"prefers-reduced-motion",[36,13376,13377],{},"prefers-color-scheme",[15,13379,13380,13381,13384,13385,1331,13387,1331,13389,13391],{},"三个不装插件就能做的动作：Elements 面板右键元素 → ",[19,13382,13383],{},"State…"," 强制 ",[36,13386,1091],{},[36,13388,1095],{},[36,13390,8519],{},"；Styles 面板右上 ⋮ → Show all user-agent styles 看默认样式表；Network 面板禁用缓存 + 用无痕窗口排除扩展干扰。",[24,13393,13394],{"id":13394},"六个高频坑的复现与修法",[219,13396,13397,13409],{},[222,13398,13399],{},[225,13400,13401,13403,13406],{},[228,13402,5737],{},[228,13404,13405],{},"根因",[228,13407,13408],{},"修法",[238,13410,13411,13434,13453,13476,13492,13503],{},[225,13412,13413,13417,13420],{},[243,13414,13415,5769],{},[36,13416,5768],{},[243,13418,13419],{},"父级没有确定高度",[243,13421,13422,13423,13425,13426,13428,13429,1331,13431,13433],{},"给父显式高度；或父用 Grid\u002FFlex 靠 ",[36,13424,4556],{},"；或整条链改用 ",[36,13427,2378],{},"；或用 ",[36,13430,6826],{},[36,13432,1581],{}," 表达「占满」",[225,13435,13436,13439,13447],{},[243,13437,13438],{},"内容撑破容器",[243,13440,13441,13442,6003,13444,13446],{},"Flex 子项 ",[36,13443,2101],{},[36,13445,4878],{},"（第十章）",[243,13448,13449,2357,13451],{},[36,13450,4998],{},[36,13452,2799],{},[225,13454,13455,13458,13465],{},[243,13456,13457],{},"意外的横向滚动条",[243,13459,13460,13461,13464],{},"负 margin、",[36,13462,13463],{},"width: 100vw","（含滚动条宽度）、未换行长串、跑到外面的绝对定位",[243,13466,13467,13468,13471,13472,13475],{},"Console 里过滤 ",[36,13469,13470],{},"el.scrollWidth > el.clientWidth"," 定位元凶；",[36,13473,13474],{},"scrollbar-gutter: stable"," 防弹层抖动",[225,13477,13478,13481,13484],{},[243,13479,13480],{},"margin 跑到父元素上",[243,13482,13483],{},"塌陷穿透（第六章）",[243,13485,13486,13487,13489,13490],{},"父加 ",[36,13488,4401],{},"，或改用 ",[36,13491,2224],{},[225,13493,13494,13497,13500],{},[243,13495,13496],{},"加了样式没变化",[243,13498,13499],{},"选择器没命中，或被更高权重\u002F更晚层覆盖（第四、十六章）",[243,13501,13502],{},"Styles 面板看有没有列出这条、被划掉的是哪条",[225,13504,13505,13508,13526],{},[243,13506,13507],{},"只在真机上不对",[243,13509,13510,13511,1331,13513,1416,13516,13518,13519,1331,13522,13525],{},"视口单位（",[36,13512,1581],{},[36,13514,13515],{},"dvh",[36,13517,1572],{},"）、安全区、",[36,13520,13521],{},"hover",[36,13523,13524],{},"pointer"," 判定",[243,13527,13528],{},"第十三章 + 第五章的相关条目",[15,13530,13531,13532,13535],{},"一行排查用的临时样式（只写在 DevTools 里，",[19,13533,13534],{},"不要提交","）：",[29,13537,13539],{"className":375,"code":13538,"language":377,"meta":34,"style":34},"* { outline: 1px dashed rgba(255,0,0,.3); }   \u002F* 谁比想象中宽\u002F高，一眼看出 *\u002F\nimg { background: #ff0; }                      \u002F* 看图片实际渲染尺寸 *\u002F\n[style] { border: 2px solid red; }             \u002F* 揪出内联样式 *\u002F\n",[36,13540,13541,13582,13601],{"__ignoreMap":34},[39,13542,13543,13545,13547,13549,13551,13553,13555,13558,13560,13562,13564,13566,13568,13570,13572,13574,13577,13579],{"class":41,"line":42},[39,13544,743],{"class":56},[39,13546,109],{"class":52},[39,13548,3690],{"class":112},[39,13550,116],{"class":52},[39,13552,2017],{"class":112},[39,13554,123],{"class":122},[39,13556,13557],{"class":112}," dashed",[39,13559,3777],{"class":112},[39,13561,173],{"class":52},[39,13563,3252],{"class":112},[39,13565,3255],{"class":52},[39,13567,134],{"class":112},[39,13569,3255],{"class":52},[39,13571,134],{"class":112},[39,13573,3255],{"class":52},[39,13575,13576],{"class":112},".3",[39,13578,7596],{"class":52},[39,13580,13581],{"class":45},"\u002F* 谁比想象中宽\u002F高，一眼看出 *\u002F\n",[39,13583,13584,13586,13588,13590,13592,13595,13598],{"class":41,"line":49},[39,13585,4008],{"class":56},[39,13587,109],{"class":52},[39,13589,1347],{"class":112},[39,13591,116],{"class":52},[39,13593,13594],{"class":112},"#ff0",[39,13596,13597],{"class":52},"; }                      ",[39,13599,13600],{"class":45},"\u002F* 看图片实际渲染尺寸 *\u002F\n",[39,13602,13603,13605,13607,13609,13611,13613,13615,13617,13619,13622,13624],{"class":41,"line":82},[39,13604,1898],{"class":52},[39,13606,100],{"class":60},[39,13608,1909],{"class":52},[39,13610,1337],{"class":112},[39,13612,116],{"class":52},[39,13614,2313],{"class":112},[39,13616,123],{"class":122},[39,13618,2022],{"class":112},[39,13620,13621],{"class":112}," red",[39,13623,2273],{"class":52},[39,13625,13626],{"class":45},"\u002F* 揪出内联样式 *\u002F\n",[24,13628,13629],{"id":13629},"浏览器基线与降级策略汇总",[15,13631,13632],{},"本教程用到的较新能力，按「不支持会怎样」分类（版本号请以 caniuse 当前数据为准，这里给的是量级判断）：",[219,13634,13635,13650],{},[222,13636,13637],{},[225,13638,13639,13642,13645],{},[228,13640,13641],{},"能力",[228,13643,13644],{},"不支持时的表现",[228,13646,13647,13648],{},"要不要包 ",[36,13649,8494],{},[238,13651,13652,13677,13690,13702,13714,13728],{},[225,13653,13654,13671,13674],{},[243,13655,13656,1092,13658,1331,13660,1092,13662,13664,13665,1092,13667,1092,13669],{},[36,13657,8501],{},[36,13659,1237],{},[36,13661,1233],{},[36,13663,339],{},"、原生嵌套、",[36,13666,2224],{},[36,13668,6826],{},[36,13670,6947],{},[243,13672,13673],{},"整条规则被忽略，布局退化为基线形态",[243,13675,13676],{},"一般不需要，写清基线样式即可；追求极端兼容时包",[225,13678,13679,13684,13687],{},[243,13680,13681,13682],{},"容器查询与 ",[36,13683,12712],{},[243,13685,13686],{},"组件停在「窄容器」默认形态",[243,13688,13689],{},"建议包，避免中间态视觉",[225,13691,13692,13696,13699],{},[243,13693,13694],{},[36,13695,5623],{},[243,13697,13698],{},"卡片行不对齐，其他正常",[243,13700,13701],{},"建议包",[225,13703,13704,13708,13711],{},[243,13705,13706],{},[36,13707,7611],{},[243,13709,13710],{},"变量过渡退化成跳变",[243,13712,13713],{},"不需要",[225,13715,13716,13719,13722],{},[243,13717,13718],{},"滚动驱动动画",[243,13720,13721],{},"进度条停在首\u002F末帧",[243,13723,13724,13727],{},[19,13725,13726],{},"必须包","，且要保证静态形态可读",[225,13729,13730,13734,13737],{},[243,13731,13732],{},[36,13733,6222],{},[243,13735,13736],{},"半透明面板糊在一起",[243,13738,13739],{},"建议包，并给一个不透明的回退底色",[10,13741,13743],{"id":13742},"二十一综合实战把一团-div-变成现代布局","二十一、综合实战：把一团 div 变成现代布局",[15,13745,13746],{},"前面二十章的东西在真实项目里是同时发生的。这一章把一份「能跑但处处是隐患」的首页改写成现代写法，逐条对照。",[24,13748,13750],{"id":13749},"改造前八类典型问题","改造前：八类典型问题",[304,13752],{"height":2979,"src":13753,"title":13754},"\u002Ftutorials\u002Fcss\u002Fdemos\u002F21-project-before.html","示例 21：改造前 —— 固定 960px、float 两列、颜色写死",[15,13756,13757],{},"问题清单（每条都对应前面某一章）：",[316,13759,13760,13772,13791,13799,13815,13830,13845,13858],{},[319,13761,13762,2390,13765,13768,13769,590],{},[19,13763,13764],{},"固定像素宽度 + 居中",[36,13766,13767],{},"width: 960px; margin: 0 auto","）：窄屏出横向滚动条，宽屏两侧空白 → 第十三章 ",[36,13770,13771],{},"min(100% - 2rem, 68rem)",[319,13773,13774,13777,13778,13781,13782,13785,13786,13788,13789,590],{},[19,13775,13776],{},"float 两列","：需要空 ",[36,13779,13780],{},"div.clearfix","、需要 ",[36,13783,13784],{},".last"," 抹掉末位边距、需要 ",[36,13787,2214],{}," 修高度塌陷 → 第十一章 Grid 命名区域 + ",[36,13790,2224],{},[319,13792,13793,13796,13797,590],{},[19,13794,13795],{},"卡片列数靠复制类名","（两列一套、单列一套）：改需求要两边同动 → 第十一章 ",[36,13798,12894],{},[319,13800,13801,2390,13804,13807,13808,13810,13811,1331,13813,590],{},[19,13802,13803],{},"颜色与字号硬编码且重复",[36,13805,13806],{},"#0066cc"," 出现 5 次、全部 ",[36,13809,123],{},"）：暗色主题没有可能 → 第十四章令牌 + 第十三章 ",[36,13812,1523],{},[36,13814,6947],{},[319,13816,13817,2390,13820,13823,13824,13826,13827,13829],{},[19,13818,13819],{},"靠堆权重覆盖",[36,13821,13822],{},".container .content .main .item .t","）：任何定制只能 ",[36,13825,327],{}," → 第四章降权重 + 第十五章 ",[36,13828,1237],{}," + 第十四章组件变量。",[319,13831,13832,13838,13839,13842,13843,590],{},[19,13833,13834,13837],{},[36,13835,13836],{},"padding-top: 70px"," 手算垂直居中","：字号一改就歪 → 第十章 ",[36,13840,13841],{},"align-items: center"," \u002F 第十一章 ",[36,13844,5690],{},[319,13846,13847,13853,13854,2357,13856,590],{},[19,13848,13849,13850,13852],{},"图片位靠 ",[36,13851,1343],{}," 写死","：真图进来要么变形要么留白 → 第十三章 ",[36,13855,6826],{},[36,13857,3073],{},[319,13859,13860,13868,13869,13871],{},[19,13861,13862,13863,13865,13866],{},"只有 ",[36,13864,1091],{}," 没有 ",[36,13867,1098],{},"：键盘用户看不见焦点，触屏点了不还原 → 第八\u002F十五章焦点样式 + 第十三章 ",[36,13870,6810],{}," 判定。",[24,13873,13875],{"id":13874},"改造后同一份内容一半代码","改造后：同一份内容，一半代码",[304,13877],{"height":5840,"src":13878,"title":13879},"\u002Ftutorials\u002Fcss\u002Fdemos\u002F21b-project-after.html","示例 21：改造后 —— 令牌主题 + Grid\u002FFlex + 容器查询 + 可降级动效",[15,13881,13882],{},"改造后的写法逐条对应：",[316,13884,13885,13910,13919,13938,13954,13967,13983,14002],{},[319,13886,13887,676,13890,1092,13892,1092,13894,1092,13896,1092,13898,1092,13900,13903,13904,13906,13907,13909],{},[19,13888,13889],{},"令牌层",[36,13891,7630],{},[36,13893,7432],{},[36,13895,7346],{},[36,13897,7366],{},[36,13899,7355],{},[36,13901,13902],{},"--z-header"," 一次声明；",[36,13905,7761],{}," 只替换令牌，所有组件规则零改动，并配 ",[36,13908,7655],{}," 让浏览器控件一起换（第十四章）。",[319,13911,13912,676,13915,13918],{},[19,13913,13914],{},"容器层",[36,13916,13917],{},".wrap { width: min(100% - 2 * var(--space-3), 68rem); margin-inline: auto; }","——无需断点的居中容器（第十三章）。",[319,13920,13921,13924,13925,2357,13927,13930,13931,13934,13935,13937],{},[19,13922,13923],{},"骨架层","：页头 ",[36,13926,5977],{},[36,13928,13929],{},"z-index: var(--z-header)","；主体 Grid 单列，",[36,13932,13933],{},"@media (min-width: 52rem)"," 变两列（",[36,13936,4995],{}," 防溢出，第十一\u002F十二章）。",[319,13939,13940,13943,13944,13947,13948,2357,13951,13953],{},[19,13941,13942],{},"组件层","：卡片一份样式，",[36,13945,13946],{},"repeat(auto-fit, minmax(min(220px, 100%), 1fr))"," 自己算列数；内部 ",[36,13949,13950],{},"flex-direction: column",[36,13952,5152],{}," 让页脚对齐（第十\u002F十一章）。",[319,13955,13956,13959,13960,2612,13963,13966],{},[19,13957,13958],{},"槽位自适应","：侧栏列表声明 ",[36,13961,13962],{},"container-type: inline-size",[36,13964,13965],{},"@container (min-width: 22rem)"," 时才横排——同一个组件放进宽槽会自动变横排（第二十章）。",[319,13968,13969,676,13972,13974,13975,13977,13978,2612,13980,13982],{},[19,13970,13971],{},"动效",[36,13973,13521],{}," 只动 ",[36,13976,1370],{}," 与伪元素 ",[36,13979,1367],{},[36,13981,13374],{}," 下整组过渡被关闭（第十八章）。",[319,13984,13985,676,13988,13990,13991,13994,13995,1092,13998,14001],{},[19,13986,13987],{},"可访问性",[36,13989,1098],{}," 描边、",[36,13992,13993],{},"aria-current=\"page\""," 标当前页、装饰色块加 ",[36,13996,13997],{},"aria-hidden",[36,13999,14000],{},"sr-only"," 补列表说明（第十五章 + HTML 教程第十七章）。",[319,14003,14004,676,14007,14010],{},[19,14005,14006],{},"API 化的组件",[36,14008,14009],{},".badge { --badge-bg: …; --badge-fg: …; }","，使用方给祖先设变量就能定制，不需要修饰类（第十四章）。",[24,14012,14014],{"id":14013},"对照检查清单新项目起手就用它","对照检查清单（新项目起手就用它）",[434,14016,14019,14031,14037,14049,14058,14067,14073,14082,14091,14100,14116,14125],{"className":14017},[14018],"contains-task-list",[319,14020,14023,14026,14027,14030],{"className":14021},[14022],"task-list-item",[4011,14024],{"disabled":85,"type":14025},"checkbox"," 是否有一条 ",[36,14028,14029],{},"* { box-sizing: border-box; }","（第六章）",[319,14032,14034,14036],{"className":14033},[14022],[4011,14035],{"disabled":85,"type":14025}," 颜色\u002F间距\u002F圆角\u002F层级是否只出现在令牌里（第十四章）",[319,14038,14040,14042,14043,14045,14046,14048],{"className":14039},[14022],[4011,14041],{"disabled":85,"type":14025}," 是否有硬编码 ",[36,14044,123],{}," 字号、是否给正文留了 ",[36,14047,1523],{}," 缩放余地（第七、十三章）",[319,14050,14052,14054,14055,14057],{"className":14051},[14022],[4011,14053],{"disabled":85,"type":14025}," 布局是否用 Grid 定骨架、Flex 定一维，",[36,14056,2332],{}," 只留在图文环绕（第九~十一章）",[319,14059,14061,14063,14064,14066],{"className":14060},[14022],[4011,14062],{"disabled":85,"type":14025}," 卡片墙是否用 ",[36,14065,12894],{}," 而不是复制列数类（第十一章）",[319,14068,14070,14072],{"className":14069},[14022],[4011,14071],{"disabled":85,"type":14025}," 组件是否用容器查询而不是猜视口宽度（第二十章）",[319,14074,14076,14078,14079,14081],{"className":14075},[14022],[4011,14077],{"disabled":85,"type":14025}," 每个可交互元素是否有 ",[36,14080,1098],{}," 样式，对比度是否达标（第八章）",[319,14083,14085,14087,14088,14090],{"className":14084},[14022],[4011,14086],{"disabled":85,"type":14025}," 动效是否有 ",[36,14089,13374],{}," 降级（第十三、十八章）",[319,14092,14094,14096,14097,14099],{"className":14093},[14022],[4011,14095],{"disabled":85,"type":14025}," 新特性是否包了 ",[36,14098,8494],{},"，并确认不支持时的形态可接受（第二十章）",[319,14101,14103,14105,14106,1331,14108,14110,14111,2357,14113,14115],{"className":14102},[14022],[4011,14104],{"disabled":85,"type":14025}," 图片是否有 ",[36,14107,1340],{},[36,14109,1343],{},"（防布局抖动）、",[36,14112,6826],{},[36,14114,3073],{}," 是否配合（第十三章 + HTML 教程第六章）",[319,14117,14119,14121,14122,14124],{"className":14118},[14022],[4011,14120],{"disabled":85,"type":14025}," 是否存在靠 ",[36,14123,327],{}," 或超长选择器维持的覆盖（第四、十五章）",[319,14126,14128,14130],{"className":14127},[14022],[4011,14129],{"disabled":85,"type":14025}," 层叠顺序是否清晰：未分层样式有没有意外压过组件库（第十二、十六章）",[24,14132,14134],{"id":14133},"结语css-的心智模型只有三句话","结语：CSS 的心智模型只有三句话",[316,14136,14137,14146,14152],{},[319,14138,14139,14142,14143,14145],{},[19,14140,14141],{},"谁生效"," = 层叠（权重、书写顺序、",[36,14144,327],{},"、层、上下文）——第四、十二、十六章；",[319,14147,14148,14151],{},[19,14149,14150],{},"生效成什么样"," = 盒模型 + 布局算法（普通流、Flex、Grid、定位）——第六、九~十二章；",[319,14153,14154,14157,14158,14160,14161,14163],{},[19,14155,14156],{},"能不能被所有人用"," = 排版与可访问性 + 渐进增强（",[36,14159,1523],{},"、焦点、降级、",[36,14162,8494],{},"）——第七、十三、二十章。",[15,14165,14166],{},"剩下的一切——颜色、渐变、阴影、动画——都是这三条之上的表现层。把这三句话记住，遇到「为什么不是我想的样子」时，先问它属于哪一句，答案通常就在对应那一章里。",[100,14168,14169],{},"html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .s4JwU, html code.shiki .s4JwU{--shiki-default:#85E89D}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .s6RL2, html code.shiki .s6RL2{--shiki-default:#FDAEB7;--shiki-default-font-style:italic}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}",{"title":34,"searchDepth":49,"depth":49,"links":14171},[14172,14176,14182,14189,14195,14200,14210,14220,14231,14242,14254,14266,14277,14287,14298,14310,14320,14331,14347,14359,14375],{"id":12,"depth":49,"text":13,"children":14173},[14174,14175],{"id":26,"depth":82,"text":27},{"id":311,"depth":82,"text":311},{"id":367,"depth":49,"text":368,"children":14177},[14178,14179,14180,14181],{"id":371,"depth":82,"text":372},{"id":460,"depth":82,"text":460},{"id":526,"depth":82,"text":527},{"id":593,"depth":82,"text":593},{"id":696,"depth":49,"text":697,"children":14183},[14184,14185,14186,14187,14188],{"id":700,"depth":82,"text":701},{"id":786,"depth":82,"text":787},{"id":886,"depth":82,"text":886},{"id":992,"depth":82,"text":992},{"id":1086,"depth":82,"text":1086},{"id":1128,"depth":49,"text":1129,"children":14190},[14191,14192,14193,14194],{"id":1132,"depth":82,"text":1133},{"id":1250,"depth":82,"text":1251},{"id":1278,"depth":82,"text":1278},{"id":1446,"depth":82,"text":1447},{"id":1480,"depth":49,"text":1481,"children":14196},[14197,14198,14199],{"id":1484,"depth":82,"text":1484},{"id":1687,"depth":82,"text":1687},{"id":1810,"depth":82,"text":1811},{"id":1946,"depth":49,"text":1947,"children":14201},[14202,14204,14206,14207,14209],{"id":1957,"depth":82,"text":14203},"content-box 与 border-box：width 到底指哪一层",{"id":2115,"depth":82,"text":14205},"margin 与 padding：一个占外面、一个占里面",{"id":2180,"depth":82,"text":2181},{"id":2235,"depth":82,"text":14208},"负 margin：合法但危险",{"id":2341,"depth":82,"text":2341},{"id":2382,"depth":49,"text":2383,"children":14211},[14212,14213,14215,14216,14217,14219],{"id":2413,"depth":82,"text":2414},{"id":2533,"depth":82,"text":14214},"font-size、font-weight、line-height",{"id":2626,"depth":82,"text":2627},{"id":2669,"depth":82,"text":2669},{"id":2774,"depth":82,"text":14218},"white-space、断行与截断",{"id":2929,"depth":82,"text":2929},{"id":2975,"depth":49,"text":2976,"children":14221},[14222,14224,14225,14227,14228,14230],{"id":2984,"depth":82,"text":14223},"background-image 与 background-size",{"id":3198,"depth":82,"text":3199},{"id":3400,"depth":82,"text":14226},"渐变：它是 \u003Cimage>，不是颜色",{"id":3531,"depth":82,"text":3532},{"id":3700,"depth":82,"text":14229},"box-shadow 的四个可省参数",{"id":3851,"depth":82,"text":3852},{"id":3907,"depth":49,"text":14232,"children":14233},"九、display、可见性与 float：历史与今天的分工",[14234,14236,14237,14239,14240],{"id":3922,"depth":82,"text":14235},"block \u002F inline \u002F inline-block",{"id":4062,"depth":82,"text":4063},{"id":4263,"depth":82,"text":14238},"float：它唯一被设计出来的用途是文字环绕",{"id":4372,"depth":82,"text":4373},{"id":4405,"depth":82,"text":14241},"其余 display 值速查",{"id":4451,"depth":49,"text":4452,"children":14243},[14244,14245,14247,14249,14251,14253],{"id":4470,"depth":82,"text":4471},{"id":4578,"depth":82,"text":14246},"gap：容器间距的正确写法",{"id":4644,"depth":82,"text":14248},"flex-grow \u002F flex-shrink \u002F flex-basis",{"id":4803,"depth":82,"text":14250},"flex-wrap 与 order",{"id":4868,"depth":82,"text":14252},"最经典的坑：min-width 不是 0",{"id":5009,"depth":82,"text":5009},{"id":5162,"depth":49,"text":5163,"children":14255},[14256,14258,14259,14260,14262,14264,14265],{"id":5174,"depth":82,"text":14257},"grid-template-columns 与 fr",{"id":5303,"depth":82,"text":5304},{"id":5456,"depth":82,"text":5457},{"id":5488,"depth":82,"text":14261},"一行代码的响应式：minmax() + auto-fit \u002F auto-fill",{"id":5620,"depth":82,"text":14263},"subgrid：让子卡片共享外层轨道",{"id":5672,"depth":82,"text":5673},{"id":5728,"depth":82,"text":5728},{"id":5824,"depth":49,"text":5825,"children":14267},[14268,14270,14272,14274,14276],{"id":5845,"depth":82,"text":14269},"五种 position 的差别在参考系",{"id":5994,"depth":82,"text":14271},"inset 简写与三种绝对居中",{"id":6170,"depth":82,"text":14273},"z-index：只在自己的层叠上下文里比大小",{"id":6312,"depth":82,"text":14275},"fixed 会被祖先「抢走」",{"id":6339,"depth":82,"text":6339},{"id":6533,"depth":49,"text":6534,"children":14278},[14279,14280,14282,14283,14285],{"id":6548,"depth":82,"text":6549},{"id":6638,"depth":82,"text":14281},"移动优先：默认写窄屏，逐级 min-width 增强",{"id":6760,"depth":82,"text":6761},{"id":6943,"depth":82,"text":14284},"流式排版：clamp() \u002F min() \u002F max()",{"id":7178,"depth":82,"text":14286},"aspect-ratio 与 object-fit：图片适配的两个正交属性",{"id":7320,"depth":49,"text":7321,"children":14288},[14289,14290,14291,14293,14294,14295,14296,14297],{"id":7331,"depth":82,"text":7332},{"id":7426,"depth":82,"text":7426},{"id":7482,"depth":82,"text":14292},"var() 的回退值与「无效」行为",{"id":7615,"depth":82,"text":7616},{"id":7775,"depth":82,"text":7776},{"id":7899,"depth":82,"text":7899},{"id":8051,"depth":82,"text":8052},{"id":8290,"depth":82,"text":8290},{"id":8353,"depth":49,"text":8354,"children":14299},[14300,14302,14304,14306,14307,14309],{"id":8365,"depth":82,"text":14301},":is() 与 :where()：把选择器体积收敛掉",{"id":8498,"depth":82,"text":14303},":has()：真正的父向选择器",{"id":8638,"depth":82,"text":14305},":not() 的多参数与结构伪类",{"id":8731,"depth":82,"text":8732},{"id":8894,"depth":82,"text":14308},"calc() 与混合单位",{"id":9090,"depth":82,"text":9090},{"id":9119,"depth":49,"text":14311,"children":14312},"十六、原生嵌套与 @layer",[14313,14315,14316,14318,14319],{"id":9140,"depth":82,"text":14314},"原生嵌套：& 是「外层选择器原文」",{"id":9400,"depth":82,"text":9401},{"id":9461,"depth":82,"text":14317},"@layer：把优先级写成一句声明",{"id":9600,"depth":82,"text":9601},{"id":9677,"depth":82,"text":9677},{"id":9708,"depth":49,"text":9709,"children":14321},[14322,14324,14326,14328,14329,14330],{"id":9723,"depth":82,"text":14323},"只有一个前提：必须有 content",{"id":9779,"depth":82,"text":14325},"content 的取值形态",{"id":9971,"depth":82,"text":14327},"counter()：章节自动编号",{"id":10117,"depth":82,"text":10118},{"id":10234,"depth":82,"text":10235},{"id":10665,"depth":82,"text":10665},{"id":10721,"depth":49,"text":10722,"children":14332},[14333,14335,14336,14338,14340,14342,14343,14345,14346],{"id":10739,"depth":82,"text":14334},"transition 的四要素",{"id":10873,"depth":82,"text":10873},{"id":10928,"depth":82,"text":14337},"transform：2D、3D 与支点",{"id":11093,"depth":82,"text":14339},"只动 transform 与 opacity",{"id":11303,"depth":82,"text":14341},"@keyframes 与 animation 属性族",{"id":11483,"depth":82,"text":11484},{"id":11565,"depth":82,"text":14344},"will-change：先测量再加",{"id":11615,"depth":82,"text":11616},{"id":11665,"depth":82,"text":11665},{"id":11691,"depth":49,"text":11692,"children":14348},[14349,14350,14352,14354,14356,14358],{"id":11709,"depth":82,"text":11710},{"id":11967,"depth":82,"text":14351},"filter：改自己的绘制结果",{"id":12050,"depth":82,"text":14353},"backdrop-filter：毛玻璃",{"id":12187,"depth":82,"text":14355},"mask 与 clip-path：软边界与硬边界",{"id":12416,"depth":82,"text":14357},"mix-blend-mode 与 background-blend-mode",{"id":12506,"depth":82,"text":12506},{"id":12538,"depth":49,"text":14360,"children":14361},"二十、容器查询、@supports 与调试排错",[14362,14363,14365,14367,14368,14370,14372,14373,14374],{"id":12549,"depth":82,"text":12549},{"id":12629,"depth":82,"text":14364},"container-type 的三个值与代价",{"id":12708,"depth":82,"text":14366},"容器单位：cqi \u002F cqb \u002F cqmin \u002F cqmax",{"id":12851,"depth":82,"text":12851},{"id":12920,"depth":82,"text":14369},"与 :has() 组合，能替掉一大类 JS",{"id":13020,"depth":82,"text":14371},"@supports：测试的是「声明」，不是「特性名」",{"id":13289,"depth":82,"text":13290},{"id":13394,"depth":82,"text":13394},{"id":13629,"depth":82,"text":13629},{"id":13742,"depth":49,"text":13743,"children":14376},[14377,14378,14379,14380],{"id":13749,"depth":82,"text":13750},{"id":13874,"depth":82,"text":13875},{"id":14013,"depth":82,"text":14014},{"id":14133,"depth":82,"text":14134},"\u002Fimg\u002Fcss-cover.svg","2026-10-03","从选择器到容器查询：Flex\u002FGrid 布局、主题化、现代选择器与动画，21 章循序渐进，每章配可运行示例。","md",{},"\u002Ftutorials\u002Fcss",{"title":5,"description":14383},{"loc":14386},"tutorials\u002Fcss","opsYVXU5-xq0tz5SZi4_64HRM8L7sFsIM_Z3rvOtRmU",[14392,14394,14398,14402,14406,14409,14413,14417,14421,14425,14428,14432,14436,14440,14444,14448,14451,14455,14459,14463,14467,14470,14474,14478,14482,14485,14489,14493,14497,14501,14505,14509,14513,14517,14521,14525,14529,14533,14536,14540,14544,14548,14552,14556,14560,14563,14567,14571,14575,14579,14583,14587,14591,14595,14599,14603,14607,14611,14614,14618,14622,14626,14630,14634,14638,14642,14646,14650,14654,14658,14662,14666,14670,14674,14678,14682,14686,14690,14693,14697,14701,14705,14709,14713,14717,14721,14725,14728,14732,14736,14740,14744,14748,14752,14756,14760,14764,14768,14772,14776,14780,14784,14788,14792,14796,14800,14804,14808,14812,14816,14820,14824,14828,14832,14836,14840,14844,14848,14852,14856,14860,14864,14868,14872,14875,14879,14883,14887,14891,14895,14899,14903,14907,14911,14914,14918,14922,14926],{"id":14386,"title":5,"titles":14393,"content":14383,"level":42},[],{"id":14395,"title":13,"titles":14396,"content":14397,"level":49},"\u002Ftutorials\u002Fcss#一css-是什么三种引入方式与层叠起点",[5],"HTML 决定「这是什么内容」，CSS 决定「它怎么呈现」。CSS 的全部机制都建立在一个前提上：同一个元素的同一个属性可以被多条规则命中，最终只有一条赢。理解这场裁决（层叠，cascade），后面所有「我明明写了却没生效」的问题都有了解法。",{"id":14399,"title":27,"titles":14400,"content":14401,"level":82},"\u002Ftutorials\u002Fcss#外链内联块与-import各自的代价",[5,13],"\u003C!-- ① 外链样式表：正式项目的唯一正确做法 -->\n\u003Clink rel=\"stylesheet\" href=\"\u002Fcss\u002Fmain.css\">\n\n\u003C!-- ② 页面内 style 块：单页 demo、首屏关键 CSS -->\n\u003Cstyle> body { max-width: 700px; margin: 0 auto; } \u003C\u002Fstyle>\n\n\u003C!-- ③ @import：写在 CSS 文件顶部 -->\n\u003Cstyle> @import url(\"\u002Fcss\u002Freset.css\"); \u003C\u002Fstyle>\n\n\u003C!-- ④ 元素上的 style 属性：权重最高，只用于必须动态计算的值 -->\n\u003Cdiv style=\"width: 42%\">…\u003C\u002Fdiv> 方式 优点 代价 link 外链 多页共享、可长期缓存、与 HTML 并行下载 多一次请求 \u003Cstyle> 内联块 零请求，适合把首屏关键 CSS 直接嵌进 HTML 不随页面复用，改一次要动 HTML @import 组织上像 include 被引入的文件要等主 CSS 下载完才开始下载（串行），首屏变慢；生产环境几乎总该换成 link style=\"\" 属性 能被 JS 单点修改、权重最高 无法复用、写不了伪类、难以维护",{"id":14403,"title":311,"titles":14404,"content":14405,"level":82},"\u002Ftutorials\u002Fcss#一条声明怎么胜出",[5,13],"浏览器对每个元素的每个属性只保留一条获胜声明，裁判顺序是： 重要性与来源：用户带 !important 的样式 > 作者带 !important 的 > 作者普通 > 用户普通 > 浏览器默认。 层（@layer）：未分层的声明，优先级高于所有分层的声明（第十六章）。 权重（specificity）：id \u002F class \u002F 元素三个数量级比较（第四章）。 书写顺序：前三步比不出结果时，写在后面的赢。 「后写的覆盖先写的」只在权重相同的前提下成立——这是新手最容易记错的一条。",{"id":14407,"title":368,"titles":14408,"content":34,"level":49},"\u002Ftutorials\u002Fcss#二语法与书写规范",[5],{"id":14410,"title":372,"titles":14411,"content":14412,"level":82},"\u002Ftutorials\u002Fcss#规则的结构选择器-声明块",[5,368],"\u002F*  选择器（命中谁）  *\u002F\nh1, .title {\n  color: #24292f;      \u002F* 声明 = 属性 + 冒号 + 值 + 分号 *\u002F\n  line-height: 1.3;\n} 逗号是「或」：h1, .title { } 等于两条规则合并。 最后一条的分号可以省略，但别省：追加声明、被压缩工具合并时会出错。 花括号内一条声明缺分号会吞掉下一条；少一个花括号，破坏面能扩到整段样式表。",{"id":14414,"title":460,"titles":14415,"content":14416,"level":82},"\u002Ftutorials\u002Fcss#注释与分组",[5,368],"CSS 只有 \u002F* … *\u002F 一种注释，\u002F\u002F 是 Sass\u002FLess 的能力。错误恢复是整块规则级别的：一个选择器解析失败，浏览器会丢弃直到下一个 } 为止的全部内容，所以一个拼错的选择器影响的往往不止它自己。 声明简写有个必须知道的隐藏行为：简写会把没提到的分量重置为初始值。写了 background: red 之后再单写 background-position，位置可能已经被前一条清掉了——这是「明明写了却不生效」的高频原因之一。 margin: 10px 20px;               \u002F* 上下 10，左右 20（顺序：上 右 下 左，顺时针） *\u002F\nborder: 1px solid #d0d7de;       \u002F* 宽度 样式 颜色 *\u002F\nbackground: #f6f8fa url(a.png) no-repeat center \u002F cover;  \u002F* 一行写完多个分量 *\u002F",{"id":14418,"title":527,"titles":14419,"content":14420,"level":82},"\u002Ftutorials\u002Fcss#命名约定bem-风格",[5,368],"本站所有组件用这一套： .chip            { }  \u002F* 块：组件本体 *\u002F\n.chip__count     { }  \u002F* 元素：块内部的组成部分，双下划线 *\u002F\n.chip--primary   { }  \u002F* 修饰符：同一种东西的变体，双连字符 *\u002F\n.chip.is-disabled{ }  \u002F* 状态：由 JS 加上的类，配 is-\u002Fhas- 前缀 *\u002F BEM 不是标准，而是一种能防止选择器膨胀的命名纪律。三条收益：看类名就知道归属、每条规则能单独读懂、权重始终是「单个 class」因此永远低位、方便覆盖。命名带用途而不是带外观：is-error 好于 red-text。",{"id":14422,"title":593,"titles":14423,"content":14424,"level":82},"\u002Ftutorials\u002Fcss#常见语法错误与排查",[5,368],"写法 后果 colo: red（属性拼错） 该声明被忽略，块内其余照常 color red;（漏冒号） 该声明被忽略 margin: 10px 20px（漏分号） 下一条声明被吞 少一个 } 直到下一个 } 的整块内容失效 width: 100（长度漏单位） 除 0 和单位无关关键字外，长度必须带单位 中文全角分号 ；、全角冒号 ： 中文输入法下的第一大坑，症状同上 排查只用 DevTools 的 Styles 面板：被划掉的规则说明被更高权重或 !important 压制（面板会标出是谁压的），根本没出现的规则说明没命中或整块解析失败。",{"id":14426,"title":697,"titles":14427,"content":34,"level":49},"\u002Ftutorials\u002Fcss#三选择器基础",[5],{"id":14429,"title":701,"titles":14430,"content":14431,"level":82},"\u002Ftutorials\u002Fcss#类型classid-与通配",[5,697],"p { }        \u002F* 类型选择器：命中所有 p，权重 0,0,1 *\u002F\n.card { }    \u002F* class：权重 0,1,0 —— 日常主力 *\u002F\n#header { }  \u002F* id：权重 1,0,0 —— 别拿它写样式（第四章） *\u002F\n* { }        \u002F* 通配：权重 0，唯一正当用途是重置 *\u002F\n*, *::before, *::after { box-sizing: border-box; }",{"id":14433,"title":787,"titles":14434,"content":14435,"level":82},"\u002Ftutorials\u002Fcss#组合子空格-与",[5,697],".card p       { }   \u002F* 空格 = 后代，任意深度 *\u002F\n.card > p     { }   \u002F* > = 子代，只下一层 *\u002F\nh4 + h4       { }   \u002F* + = 紧邻兄弟，紧跟在后面的那一个 *\u002F\np ~ span      { }   \u002F* ~ = 后续兄弟，之后的所有同级 *\u002F\nA B C > D     { }   \u002F* 混用；从右往左读：D 是 C 的子，C 是 B 的后代 *\u002F 选择器从右往左匹配，所以最右侧的「关键选择器」越具体越快。长链 body > div .box ul li a 既慢又脆，DOM 一调整就断——这是重构时最先该删的东西。",{"id":14437,"title":886,"titles":14438,"content":14439,"level":82},"\u002Ftutorials\u002Fcss#属性选择器全家福",[5,697],"语法 含义 [href] 存在该属性 [href=\"x\"] \u002F [href=\"x\" i] 精确等于 \u002F 忽略大小写 [href^=\"https\"] 前缀 [href$=\".pdf\"] 后缀 [href*=\"docs\"] 包含 [rel~=\"noopener\"] 空格分隔的值列表中含某项 [class|=\"btn\"] 等于 btn 或以 btn- 开头 它们配合 data-*（HTML 教程第十五章）能实现「数据驱动样式」：JS 只改属性，样式跟着变。",{"id":14441,"title":992,"titles":14442,"content":14443,"level":82},"\u002Ftutorials\u002Fcss#结构伪类",[5,697],":first-child \u002F :last-child          \u002F* 首尾 *\u002F\n:nth-child(2n)  \u002F  :nth-child(even) \u002F* 偶数；也可 (2n+1)、odd、from-end(2) *\u002F\n:nth-child(-n+3)                    \u002F* 前 3 个 *\u002F\n:only-child                         \u002F* 独子 *\u002F\n:empty                              \u002F* 无子节点也无文本（空白符也算文本，格式化容易破坏它） *\u002F\n:not(.is-done)                      \u002F* 排除 *\u002F",{"id":14445,"title":1086,"titles":14446,"content":14447,"level":82},"\u002Ftutorials\u002Fcss#伪类与伪元素的分界",[5,697],":hover、:focus、:focus-visible、:active 描述状态（单冒号）；::before、::after、::placeholder、::selection 创建 DOM 里不存在的额外内容（双冒号，第十七章展开）。历史单冒号写法（:before）仍兼容，新代码请统一双冒号——这样一眼能看出这条规则到底有没有真的往页面里加东西。",{"id":14449,"title":1129,"titles":14450,"content":34,"level":49},"\u002Ftutorials\u002Fcss#四层叠优先级与继承",[5],{"id":14452,"title":1133,"titles":14453,"content":14454,"level":82},"\u002Ftutorials\u002Fcss#权重计算三个数字",[5,1129],"成分 来自 记为 id 的个数 #buy 1,0,0 class \u002F 属性 \u002F 伪类的个数 .btn、[type=text]、:hover、:not() 的参数 0,1,0 类型与伪元素的个数 p、::before 0,0,1 三个常见误解： 权重不是十进制，不会进位：11 个 class（0,11,0）也压不过 1 个 id（1,0,0）。 * 和组合子（> + ~ 空格）权重为 0；:where() 权重为 0，而 :is() 取参数里最高的那个。 元素的 style=\"\" 不参与这套计数，它高于所有规则（带 !important 的声明除外）。",{"id":14456,"title":1251,"titles":14457,"content":14458,"level":82},"\u002Ftutorials\u002Fcss#important-的代价",[5,1129],"用了它，唯一的反制手段是「更具体的选择器 + 另一个 !important」。项目里一旦开始出现「为了盖住一行 !important 再加一行 !important」，样式表就已经失控。合理用法只有三类：第三方样式表的临时补丁、工具类（如 .visually-hidden）、用户自己写的无障碍样式表。 顺带一条：!important 只影响这一条声明，但简写的每个分量都会变得重要——margin: 0 !important 同时锁死四个方向。",{"id":14460,"title":1278,"titles":14461,"content":14462,"level":82},"\u002Ftutorials\u002Fcss#继承与四个关键字",[5,1129],"只有「与文字相关」的大多数属性会继承： 继承 不继承 color、font-*、line-height、text-*、letter-spacing、visibility、cursor、writing-mode 盒模型（margin\u002Fpadding\u002Fborder\u002Fwidth\u002Fheight）、background、display、position 与定位、flex\u002Fgrid 全部、overflow、opacity、transform 四个随时手动改变继承行为的关键字： color: inherit;   \u002F* 强制继承父元素的值 *\u002F\ncolor: initial;   \u002F* 强制回到该属性的初始值（切断继承） *\u002F\ncolor: unset;     \u002F* 可继承属性 = inherit，不可继承属性 = initial *\u002F\ncolor: revert;    \u002F* 回到上一层来源的值，通常是浏览器默认样式表 *\u002F revert 与 unset 的区别很实用：浏览器给 ul 的默认 padding-inline-start: 40px，写 unset 得 0，写 revert 也回到默认——但当你要「撤销用户样式覆盖」或恢复用户代理样式时，只有 revert 语义正确。另有 revert-layer，用于撤销当前 @layer 内的结果（第十六章）。",{"id":14464,"title":1447,"titles":14465,"content":14466,"level":82},"\u002Ftutorials\u002Fcss#后写的为什么没生效四条排查思路",[5,1129],"Styles 面板看那条规则有没有被划掉，划掉会附带「被谁压制」的提示。 规则根本没出现在面板里 → 选择器没命中，或整块解析失败。 用 Computed 面板搜属性名，能看到最终值来自哪一条声明。 怀疑是继承：给元素显式写 color: initial，值变了说明原先那个值是继承来的。",{"id":14468,"title":1481,"titles":14469,"content":34,"level":49},"\u002Ftutorials\u002Fcss#五单位与颜色",[5],{"id":14471,"title":1484,"titles":14472,"content":14473,"level":82},"\u002Ftutorials\u002Fcss#绝对单位与相对单位",[5,1481],"px 是屏幕上最稳的长度单位（1px = 一个设备像素，高倍屏由浏览器处理）。cm\u002Fin\u002Fpt 属于打印样式世界，别拿来做网页布局。 单位 相对什么 典型用途 rem 根元素字号 字号与间距的首选：改根字号即全站等比缩放 em 当前元素的字号（继承类属性看父元素） 组件内部尺寸随自身字号走，例如按钮内边距 % 视属性而定：宽度对父宽、高度对父高、padding 对父元素宽度、字号对父字号 栅格、流体容器 vw \u002F vh 视口宽 \u002F 高 整屏高度建议用 svh（小视口），避开手机地址栏收起造成的跳动 ch 「0」字符宽度 限制正文行长（一屏 45–75 字符最易读） ic 一个「水」字宽度 中文排版很直观：max-width: 38ic ≈ 一行 38 字 fr Grid 的剩余空间 只出现在 grid-template-*（第十一章） 还有几类不需要长度单位：line-height: 1.6（无单位数字 = 字号倍数，比 1.6em 安全，不会随继承重复相乘）、margin: 0（0 不需要单位）、flex-grow、z-index、opacity、font-weight。角度有 deg\u002Fturn\u002Frad（转 90° 写 .25turn 比 90deg 更直观），时间有 s\u002Fms。",{"id":14475,"title":1687,"titles":14476,"content":14477,"level":82},"\u002Ftutorials\u002Fcss#颜色的六种写法",[5,1481],"#0969da             \u002F* RRGGBB *\u002F\n#0969da80           \u002F* RRGGBBAA：最后两位是透明度，00 全透明 *\u002F\n#069                \u002F* 三位缩写 = #006699，只有每对数字相同才能缩写；#069da（5 位）非法 *\u002F\nrgb(9 105 218)      \u002F* 现代语法用空格分隔，逗号写法同样支持 *\u002F\nrgb(9 105 218 \u002F .5) \u002F* 透明度单独给 *\u002F\nhsl(212 92% 45% \u002F 50%)\nhwb(212 4% 15%)     \u002F* 白量、黑量，比 hsl 更符合「调深浅」的直觉 *\u002F\noklch(52% 0.19 253) \u002F* 感知均匀 *\u002F\nroyalblue           \u002F* 147 个 CSS 命名色之一，正式项目不建议 *\u002F\ntransparent  currentColor  inherit 选写法的依据：固定品牌色用 #RRGGBB；要成组调明暗、生成色阶用 hsl() 或 hwb()（改一个数字出一系列）；JS 计算出的色值用 rgb(… \u002F a)；做色阶系统用 oklch()——HSL 的「50% 亮度」在不同色相下视觉明度差很多（黄色亮、蓝紫暗），OKLCH 是感知均匀的，同一 L 值的各色看起来真的同样亮。",{"id":14479,"title":1811,"titles":14480,"content":14481,"level":82},"\u002Ftutorials\u002Fcss#透明度currentcolor-与暗色主题",[5,1481],"alpha 与 opacity 不是一件事：background: rgb(9 105 218 \u002F .5) 只让这一层背景透明，文字仍然清晰；opacity: .5 把整层（含子元素、边框）一起透明，并且会创建层叠上下文（第十二章）。 currentColor 取当前元素的 color 值，于是 border-color: currentColor、box-shadow: 0 0 0 3px currentColor 会随主题自动跟随，不必额外维护变量。 暗色主题的正解是把颜色收进自定义属性（第十四章）： :root { --c-bg: #fff; --c-text: #24292f; --c-primary: #0969da; }\nhtml[data-theme='dark'] { --c-bg: #0d1117; --c-text: #e6edf3; --c-primary: #6aa8ff; } 不要把颜色简单取反：深蓝底配高饱和品牌色会「发光」刺眼，通常要降饱和、提明度。另外 color-scheme: light dark 这一行能让浏览器的默认控件、滚动条、表单底色一起切换——成本极低，收益明显（本站全站样式里就有这一条）。",{"id":14483,"title":1947,"titles":14484,"content":1950,"level":49},"\u002Ftutorials\u002Fcss#六盒模型所有尺寸问题最后都回到这四层",[5],{"id":14486,"title":14203,"titles":14487,"content":14488,"level":82},"\u002Ftutorials\u002Fcss#content-box-与-border-boxwidth-到底指哪一层",[5,1947],"浏览器默认是 content-box：width 只描述内容区，padding 和 border 在它外面往外撑。于是这个经典事故： .card { width: 100%; padding: 16px; border: 1px solid #ddd; }  \u002F* 实际占位 = 100% + 34px，横向溢出 *\u002F 改成 border-box 之后，width 变成「最终占位宽」，padding 和 border 从里面扣，width: 100% 就真的是 100%。所以现代项目的第一行几乎都写成： *, *::before, *::after { box-sizing: border-box; } 选择器里的 *::before, *::after 不能省：伪元素同样是盒子，用 * 选不到它们，很多「加了装饰就溢出」的问题出在这。 两条边界情况值得提前知道： border-box 下 width 不再等于内容宽。文字类容器要保底，用 min-width； 全局 box-sizing: border-box 之后，某些第三方 CSS（老式表单样式、部分日历组件）会算错尺寸，这时对那几个选择器单独写回 box-sizing: content-box，不要反过来取消全局声明。",{"id":14490,"title":14205,"titles":14491,"content":14492,"level":82},"\u002Ftutorials\u002Fcss#margin-与-padding一个占外面一个占里面",[5,1947],"判断标准很简单：背景色要不要覆盖这块区域。要覆盖（内文离边缘的距离、可点击区域的大小）就用 padding；只是把邻居推开就用 margin。 由此引出几条实用的差别： padding 会扩大背景与点击热区，导航项的可点击范围不足时，先加 padding 而不是加 margin； padding 不吃百分比的高度语义：padding: 5% 的上下部分也是按父元素宽度算的（历史上为了做等高列），这条最容易记错； margin 有 auto 这个特殊值：margin-inline: auto 让块级元素在父容器里水平居中，这是「不定宽容器居中」的最短写法。",{"id":14494,"title":2181,"titles":14495,"content":14496,"level":82},"\u002Ftutorials\u002Fcss#外边距塌陷16px-16px-为什么只有-16px",[5,1947],"两个相邻块级元素的垂直 margin 会合并成一个，取绝对值较大的那个。所以「上下相邻的两个卡片各写 margin: 16px」得到的间距是 16px，不是 32px。合并规则有三种情形：正正取大、负负取绝对值大的、正负相加。 更常见的是第二种塌陷——父与子的 margin 穿透：父元素没有 padding-top、没有 border-top、且不是 BFC 时，子的 margin-top 会把父元素一起推下去，看起来像「margin 加到了父身上」。老代码里给父容器随手写 overflow: hidden 就是在处理这个问题（它在创建 BFC）。 今天的最优解不是背塌陷规则，而是改用 Flex\u002FGrid 的 gap：Flex 与 Grid 的子项之间不发生 margin 合并，间距由 gap 一处声明，首尾不会多出空白，也不需要 :last-child { margin: 0 }。这一条能消掉大部分「间距玄学」。",{"id":14498,"title":14208,"titles":14499,"content":14500,"level":82},"\u002Ftutorials\u002Fcss#负-margin合法但危险",[5,1947],"margin-left: -12px 能把元素往左拽回 12px，头像列表相互叠压、把内容对齐到视觉基线（数字悬挂在标点左侧）都会用到。风险是它把元素推到容器之外，窄屏会直接产生横向滚动条。 .avatars img { margin-left: -8px; }             \u002F* 叠压效果 *\u002F\n.avatars img:first-child { margin-left: 0; }    \u002F* 第一个不叠，否则整体左移 *\u002F\n.avatars img { border: 2px solid #fff; }        \u002F* 必须给描边，否则叠在一起看不出层次 *\u002F 只在一维上用负 margin。两列布局用负 margin 拼间距是二十年前的做法（float + 负 margin 的栅格），今天写 gap 或 minmax()。",{"id":14502,"title":2341,"titles":14503,"content":14504,"level":82},"\u002Ftutorials\u002Fcss#自查清单",[5,1947],"排「尺寸不对」时按这个顺序看： Computed 面板的盒子图，确认 box-sizing 生效（被 reset 文件覆盖是常见事故）； width + padding + border 是否超过父容器； 上下间距不对时，先确认有没有塌陷（把 margin 换成 gap 或 padding，如果问题消失，就是塌陷）； 内容把容器撑爆时，查 min-width\u002Fmin-height（Flex\u002FGrid 子项的自动最小尺寸，见第十章与十一章）。",{"id":14506,"title":2383,"titles":14507,"content":14508,"level":49},"\u002Ftutorials\u002Fcss#七文本与字体中文排版的三个特殊点",[5],"文字是网页的主要内容，而 CSS 里跟文字有关的属性分两组：一组决定用什么样的字（font-*），一组决定这些字怎么排（text-*、white-space、word-break）。",{"id":14510,"title":2414,"titles":14511,"content":14512,"level":82},"\u002Ftutorials\u002Fcss#字体栈与-fallback-顺序",[5,2383],"body {\n  font-family: system-ui, -apple-system, \"Segoe UI\", \"PingFang SC\",\n               \"Hiragino Sans GB\", \"Microsoft YaHei\", sans-serif;\n} font-family 是一个候选列表，浏览器从左往右取第一个「本机装有」的字体，全部落空才用最后的通用族关键字。因此三条规则： 带空格的名字必须加引号（\"PingFang SC\"），关键字（sans-serif、system-ui、monospace）不加； 末尾一定要放通用族兜底； 中文站一定要写中文族名。只写 Arial 时中文交给浏览器随机 fallback，Windows 与 macOS 的字重表现差别很大，bold 在一种系统上偏细、在另一种上糊成一团。 system-ui 取操作系统界面字体，优点是零下载、风格与用户设备一致；缺点是各平台长得不一样，做品牌感强的标题时通常换成西文品牌字体 + 中文族名的组合。 网络字体用 @font-face 声明，配 font-display: swap（先回退字显示、下载完再换），否则首屏会出现一段纯白文字（FOIT）。中文字体动辄几 MB，务必只加载需要的字重，或按章节做子集化。",{"id":14514,"title":14214,"titles":14515,"content":14516,"level":82},"\u002Ftutorials\u002Fcss#font-sizefont-weightline-height",[5,2383],"字号用 rem：根字号是用户\u002F浏览器设置的入口，全站用 rem 时这一设置才真的起作用。正文不小于 14px，可点击文字建议 16px。 字重优先用数字（400\u002F600\u002F700），别依赖 bold 关键字：bold 固定映射到 700，而中文字体常常只有 400 与 700 两档，浏览器会合成加粗（人为描边），中文一多就糊。中文正文里 font-weight: 600 往往比 bold 更耐看。 行高写无单位数字：line-height: 1.7 相对本元素字号计算且继承的是这个数字；写成 1.7em 时子元素会按自己的字号再乘一次，嵌套层级一深就翻倍。中文正文建议 1.6–1.8，标题 1.2–1.3。 font 简写顺序固定：font: style variant weight size\u002Fline-height family，size 与 family 必填，缺省时其余部分会被重置为初始值——这也是为什么「只想要 font: 16px sans-serif 而不重置行高」是错的写法。",{"id":14518,"title":2627,"titles":14519,"content":14520,"level":82},"\u002Ftutorials\u002Fcss#字距词距与大小写",[5,2383],"letter-spacing 用 em 为单位才随字号变化：大标题需要负字距（-0.02em）才不显松散，全大写的小标签需要正字距（.08em–.12em）。word-spacing 只影响词间空白，中文几乎没有词，主要作用于西文。 text-transform: uppercase 只改显示、不改 DOM 文本，因此对搜索、复制、读屏都可能造成偏差；中文还有 full-width 值。做小标签时用它，但正文内容不要用（英语句首大写规则会丢失）。",{"id":14522,"title":2669,"titles":14523,"content":14524,"level":82},"\u002Ftutorials\u002Fcss#对齐与装饰",[5,2383],"text-align 管行内内容在块里的对齐：left\u002Fright\u002Fcenter\u002Fjustify。justify 在西文里要配 hyphens: auto 和正确的 lang，否则词间空隙会夸张到出现「河流」；中文用 justify 效果接近两端对齐但没有连字符机制。text-align-last 单独控制最后一行。 text-decoration 家族需要注意它是画在文字上而非盒子下： a { text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; } text-underline-offset 让下划线离开基线，中文尤其需要（汉字下沿低，默认位置容易贴着笔画）。删除上下划线时写 text-decoration-line: none 而不是 text-decoration: none，后者会重置整族属性。",{"id":14526,"title":14218,"titles":14527,"content":14528,"level":82},"\u002Ftutorials\u002Fcss#white-space断行与截断",[5,2383],"这一组属性治的是「文字撑破容器」： white-space: nowrap 禁止折行（表格单元格里让数字成行最方便）； white-space: pre-wrap 保留用户输入的换行和空格（评论区必需）； overflow-wrap: anywhere 让超长单词（长 URL、base64）强制拆断； word-break: break-all 允许在任意字符间断行，中英混排有时需要，但纯西文会拆得很丑；keep-all 禁止中文断行（避免句首出现孤立标点时可用 line-break: strict）； hyphens: auto 需要元素或祖先有正确的 lang。 单行截断是固定的三件套： .truncate { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } 多行截断目前仍是带前缀的写法（但所有主流内核都支持，属事实标准）： .clamp-2 { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; } 被截断的文字仍在 DOM 里：读屏会念全文，用户选中复制也能拿到全文，但看不见的那部分等于不存在——关键信息不要靠截断承载，配合 title 属性或「展开」按钮。",{"id":14530,"title":2929,"titles":14531,"content":14532,"level":82},"\u002Ftutorials\u002Fcss#中文排版的三个特殊点",[5,2383],"标点悬挂（hanging-punctuation）与行首禁止字符（line-break: strict）能消掉中文段落「行首一个逗号」的难看；Safari 支持较好，Chrome 一线在演进，写它属于渐进增强。 行高与视觉密度：汉字是方块字，没有西文的上伸下延，同样行高下中文显得更密。中文段落行高比同字号西文再加大约 0.1–0.2 才舒服。 行长用 ch 或 ic 限制：西文正文一行 45–75 字符最易读，max-width: 65ch；中文可以用 max-width: 38ic（ic = 一个「水」字的宽度）达到同样效果。",{"id":14534,"title":2976,"titles":14535,"content":34,"level":49},"\u002Ftutorials\u002Fcss#八背景边框与阴影视觉层次靠这三样",[5],{"id":14537,"title":14223,"titles":14538,"content":14539,"level":82},"\u002Ftutorials\u002Fcss#background-image-与-background-size",[5,2976],"背景的多条轴各自独立：image（图或渐变）、position、size、repeat、origin、clip、attachment。最常配的是封面图三件套： .hero { background-image: url(hero.jpg); background-size: cover; background-position: center; } cover 铺满且不变形，代价是可能裁掉内容；contain 完整显示，代价是可能留白。人物照片做背景时 cover 常把脸裁掉，用 object-fit + \u003Cimg>（第十三章）比背景图更好控制，因为可以用 object-position 精确指定保留区域，且图片能被 alt 与懒加载覆盖。 background-position 的百分比语义容易记错：50% 50% 是「图片的 50% 处对齐容器的 50% 处」，不是「距左 50%」。 background-origin\u002Fbackground-clip 决定绘制从哪算起、画到哪结束。最常用的是文字裁切： .gradient-text {\n  background: linear-gradient(90deg, #0969da, #8250df);\n  -webkit-background-clip: text;\n  background-clip: text;\n  color: transparent;\n} （background-clip: text 现在主流内核都支持，但必须保证文字有回退色，且它会让真实 color 失效——不要对正文大范围使用，装饰标题为宜。）",{"id":14541,"title":3199,"titles":14542,"content":14543,"level":82},"\u002Ftutorials\u002Fcss#多层背景先写的在上面",[5,2976],".card-hero {\n  background-image:\n    radial-gradient(circle at 20% 30%, rgba(255,255,255,.35), transparent 40%),\n    repeating-linear-gradient(90deg, rgba(255,255,255,.12) 0 6px, transparent 6px 14px),\n    linear-gradient(135deg, #0969da, #8250df);\n  background-size: auto, auto, 100% 100%;\n} 逗号分隔的每一层对应一组值；某一层少写的值会往回取该属性的第一个值（所以只写一个 background-position 时所有层共用它）。层与层之间可以用 background-blend-mode 指定混合方式。这个「一层高光 + 一层纹理 + 一层底色」的结构，就是不用图片做出有质感封面的标准配方。",{"id":14545,"title":14226,"titles":14546,"content":14547,"level":82},"\u002Ftutorials\u002Fcss#渐变它是-image不是颜色",[5,2976],"linear-gradient()、radial-gradient()、conic-gradient()（第十九章细讲）都能出现在任何接受图片值的地方。两个高频技巧： \u002F* 硬切色带：同一位置写两次色标 *\u002F\n.progress { background: linear-gradient(90deg, var(--c-primary) 62%, #eaeef2 62%); }\n\u002F* 斜纹\u002F斑马线：repeating-linear-gradient *\u002F\n.zebra { background: repeating-linear-gradient(45deg, #fff8c5 0 10px, transparent 10px 20px); }",{"id":14549,"title":3532,"titles":14550,"content":14551,"level":82},"\u002Ftutorials\u002Fcss#边框宽度样式圆角",[5,2976],"border 是盒子的一部分（border-box 下从宽度里扣），改宽度会挤动内容。四条规则： .card:hover { border-color: #0969da; }        \u002F* 只换色不换宽：避免 hover 时内容跳动 *\u002F\n.card { border: 1px solid #d0d7de; border-left: 4px solid #0969da; }  \u002F* 左侧强调条 *\u002F\n.pill { border-radius: 999px; }               \u002F* 胶囊 *\u002F\n.leaf { border-radius: 12px 4px 12px 4px; }   \u002F* 四角不同：左上 右上 右下 左下 *\u002F border-radius 可以写 12px \u002F 24px（水平\u002F垂直半径不同）做出椭圆角；border-radius: 50% 得到圆（元素必须是正方形，否则是椭圆）。圆形头像更稳的做法是图片自身保持正方形 + object-fit: cover + 圆角。 边框想「不占空间」时用 outline：它在盒子外绘制、不影响布局，但保持矩形（新内核已跟随圆角）。所以焦点环用 outline，装饰用 box-shadow。",{"id":14553,"title":14229,"titles":14554,"content":14555,"level":82},"\u002Ftutorials\u002Fcss#box-shadow-的四个可省参数",[5,2976],"语法 inset? offset-x offset-y blur? spread? color。模糊半径为 0 时得到硬阴影，做复古\u002F新粗野风格；inset 得到内阴影，可当描边；一个选择器里可以叠多层： .tile { box-shadow: inset 0 0 0 1px #d0d7de; }              \u002F* 不占布局的 1px 描边 *\u002F\n.pop  { box-shadow: 0 1px 3px rgba(0,0,0,.12), 0 8px 24px rgba(0,0,0,.14); }  \u002F* 近处锐利 + 远处扩散 *\u002F 两层阴影是「像真的」的关键：只有一层大模糊的阴影看起来发灰，像蒙了雾。同理，暗色主题下阴影几乎看不见，应改用更亮的边框表达层次，而不是加深阴影。 性能：box-shadow 的动画代价高（要重绘），需要动效时改为「阴影写在伪元素上、动它的 opacity」（第十八章）。",{"id":14557,"title":3852,"titles":14558,"content":14559,"level":82},"\u002Ftutorials\u002Fcss#焦点可见性不是装饰是合规",[5,2976],":focus-visible { outline: 3px solid var(--c-primary); outline-offset: 2px; } outline: none 单独出现就是可访问性缺陷；要么保留默认焦点环，要么换一条足够明显的替代样式。:focus-visible 与 :focus 的区别（只在键盘导航时显示焦点环）见第十五章。",{"id":14561,"title":14232,"titles":14562,"content":34,"level":49},"\u002Ftutorials\u002Fcss#九display可见性与-float历史与今天的分工",[5],{"id":14564,"title":14235,"titles":14565,"content":14566,"level":82},"\u002Ftutorials\u002Fcss#block-inline-inline-block",[5,14232],"display 决定元素参与哪一种布局算法，而不是「是否可见」。三种最基础的： 常见标签 宽高 垂直 margin 独占一行 block div p section li 生效 生效（会塌陷） 是 inline a span b code img input 无效 无效 否 inline-block 按钮、徽章、图标 生效 生效（不塌陷） 否 行内元素「设了宽高没反应」是初学者最常见的困惑，正确答案通常是把它变成 inline-block，或者更好的是——给父级写 display: flex（第十章），让子项自动获得块级尺寸能力。 inline-block 之间那道缝来自 HTML 源码里的换行符被当作空白渲染。font-size: 0、写成一行、或者用 Flex 都能消掉，其中用 Flex 是唯一没有副作用的。",{"id":14568,"title":4063,"titles":14569,"content":14570,"level":82},"\u002Ftutorials\u002Fcss#三种看不见的代价完全不同",[5,14232],"写法 是否占位 是否可交互 读屏能否念到 能否做过渡 display: none 不占 否 否（移出可访问性树） 否 visibility: hidden 占位 否 否 可（离散切换） opacity: 0 占位 是（仍可点，注意误触） 是 是（首选动画属性） 选择依据： 需要淡入淡出 → opacity 配 visibility，动画结束后再用 visibility: hidden 彻底移出： .popover { opacity: 0; visibility: hidden; transition: opacity .18s ease, visibility .18s; }\n.popover.is-open { opacity: 1; visibility: visible; }\n只是不想出现在布局里 → display: none，但它会打断过渡； 视觉隐藏但对读屏保留（例如「已选中」状态、图例说明）用 .sr-only 那套绝对定位 + clip-path 的写法，不要用 opacity: 0（会被读出但也可被点击）或 display: none（读不到）。",{"id":14572,"title":14238,"titles":14573,"content":14574,"level":82},"\u002Ftutorials\u002Fcss#float它唯一被设计出来的用途是文字环绕",[5,14232],"float 让元素脱离正常流并贴到一侧，后续行内内容绕着它排——这是报纸版面需求。今天仍然该用 float 的只有一种场景：图文环绕（首图在段落左上，文字绕排）。Flex\u002FGrid 做不到绕排。 副作用则是所有人都熟悉的「父容器高度塌陷」：浮动元素不撑高父级，父级后面的内容会被压上来。四种清除方式： .clearfix::after { content: \"\"; display: block; clear: both; }  \u002F* 传统 *\u002F\n.parent { overflow: hidden; }    \u002F* 顺带创建 BFC，但会裁掉溢出内容 *\u002F\n.parent { display: flow-root; }  \u002F* 语义最准确、无副作用的现代写法 *\u002F 两列\u002F三列布局、等高卡片、导航条——这些历史上用 float + 负 margin 完成的事情，现在都归 Flex 与 Grid。float 还剩一个合理去处是 HTML 邮件（客户端 CSS 支持极差）。",{"id":14576,"title":4373,"titles":14577,"content":14578,"level":82},"\u002Ftutorials\u002Fcss#bfc-顺手解决边距塌陷",[5,14232],"块级格式化上下文（BFC）是一个「内部布局与外界隔离」的盒子。它不影响外部 margin 塌陷，但父容器一旦成为 BFC，子的 margin-top 就不再穿透。触发条件（任一即可）：float、position: absolute\u002Ffixed、display: flow-root\u002Finline-block\u002Ftable-cell\u002Fflex\u002Fgrid、overflow 非 visible、contain: paint。 不用背——遇到「margin 莫名跑到父元素上」时，给父容器加 display: flow-root 即可。",{"id":14580,"title":14241,"titles":14581,"content":14582,"level":82},"\u002Ftutorials\u002Fcss#其余-display-值速查",[5,14232],"grid \u002F flex 是布局算法（第十、十一章）；inline-flex、inline-grid 是它们的行内版本；table \u002F table-cell 仍是不定高内容垂直居中最省事的办法（虽然语义上应该用 Flex）；contents 让盒子自身「消失」、子元素直接参与父级布局，方便但会丢掉该元素自身的背景与边框，并曾引发展示与可访问性问题，谨慎使用。列表 ul 上写 list-style: none 会让 Safari\u002FVoiceOver 不再播报列表语义，需要用 role=\"list\" 补回（这条属于 HTML 教程第十七章的可访问性清单）。",{"id":14584,"title":4452,"titles":14585,"content":14586,"level":49},"\u002Ftutorials\u002Fcss#十flexbox从主轴到实战",[5],"一维布局（一行或一列）交给 Flex。它的模型只有一个概念需要真正理解：主轴与交叉轴，而这两根轴会随 flex-direction 旋转——这也是 Flex 最大的困惑来源。",{"id":14588,"title":4471,"titles":14589,"content":14590,"level":82},"\u002Ftutorials\u002Fcss#主轴与交叉轴属性名分两套",[5,4452],"justify-* 永远管主轴，align-* 永远管交叉轴。direction: row 时 justify 是水平、align 是垂直；改成 column 后两者表现整体旋转 90°。判断方法只有一个：先确认主轴方向，再决定该写 justify 还是 align。 flex-direction 四个值：row（默认）、row-reverse、column、column-reverse。*-reverse 只反转视觉顺序，DOM 顺序、Tab 焦点顺序、读屏顺序都不变——这会造成「看到的顺序与听到的顺序不一致」，属于可访问性风险，能用 DOM 顺序解决就别反转。 justify-content 的五个常用值只有在容器有剩余空间时才有区别：flex-start、center、flex-end、space-between（两端贴边）、space-around \u002F space-evenly（首尾也留空隙，后者所有空隙严格相等）。 align-items 有 stretch（默认，需子项不设高度）、flex-start、center、flex-end、baseline。字号不同的两项并排时 baseline 比 center 更整齐。单个子项要叛逆时用 align-self。",{"id":14592,"title":14246,"titles":14593,"content":14594,"level":82},"\u002Ftutorials\u002Fcss#gap容器间距的正确写法",[5,4452],".list { display: flex; gap: 12px 20px; }   \u002F* 行间距 列间距 *\u002F gap 只加在相邻项之间，首尾不多出空白，因此从此不需要 :last-child { margin-right: 0 }。子项换行时（flex-wrap）行与行之间的间距同样由它管。Flex、Grid、多列 column-* 都支持 gap。",{"id":14596,"title":14248,"titles":14597,"content":14598,"level":82},"\u002Ftutorials\u002Fcss#flex-grow-flex-shrink-flex-basis",[5,4452],"三个属性分别管三件事： flex-grow：容器有剩余空间时按份数分给谁。分的是剩余空间，不是总宽度——所以两个 grow: 1 的项如果内容宽度不同，最终宽度也不相等。 flex-shrink：容器不够宽时谁让步（默认 1）。实际收缩量按 shrink × basis 加权，不是按数字直接分。不想被压的（图标、关闭按钮、固定侧栏）写 flex-shrink: 0。 flex-basis：伸缩的起点尺寸，优先级高于 width（在主轴方向上）。 flex 简写有四个必须记住的展开： 写法 展开 意图 flex: 1 1 1 0% 严格等宽（basis 是 0，忽略内容宽度） flex: auto 1 1 auto 按内容比例分配剩余，能长能缩 flex: initial 0 1 auto 默认值：不生长，但会被压缩 flex: none 0 0 auto 完全固定 「等宽但内容长的那一项溢出」通常是误用了 flex: auto；「固定 240px 侧栏」的正确写法是 flex: 0 0 240px（或 flex-basis: 240px; flex-shrink: 0），只写 width: 240px 会被压缩。",{"id":14600,"title":14250,"titles":14601,"content":14602,"level":82},"\u002Ftutorials\u002Fcss#flex-wrap-与-order",[5,4452],"flex-wrap: wrap 让子项放不下时换行，配合 flex-basis 就是最省事的响应式标签云\u002F工具条： .tags { display: flex; flex-wrap: wrap; gap: 8px; } order 只改视觉顺序（默认 0，可负），典型用途是「DOM 按语义写、移动端把主内容提到前面」。风险与 *-reverse 相同：Tab 顺序跟着 DOM 走，键盘用户会跳来跳去。",{"id":14604,"title":14252,"titles":14605,"content":14606,"level":82},"\u002Ftutorials\u002Fcss#最经典的坑min-width-不是-0",[5,4452],"Flex 子项的自动最小尺寸是 min-content，因此子项无法被压缩到内容宽度以下。这直接导致「text-overflow: ellipsis 在 flex 子项里不生效」这个高频问题： .row { display: flex; }\n.row .side { flex-shrink: 0; }        \u002F* 图标\u002F按钮不让步 *\u002F\n.row .text { min-width: 0; }          \u002F* 关键：允许收缩到内容以下，省略号才生效 *\u002F\n.row .text span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } 同一类问题在嵌套 Flex、Grid 子项（1fr 的下限是 auto）里都会出现，写 minmax(0, 1fr) 或 min-width: 0。纵向（column）时对应的是 min-height: 0，否则子项会撑破滚动容器。",{"id":14608,"title":5009,"titles":14609,"content":14610,"level":82},"\u002Ftutorials\u002Fcss#三个高频实战配方",[5,4452],"\u002F* 居中：完全居中一行 *\u002F  .c { display: flex; align-items: center; justify-content: center; }\n\u002F* 工具条：左标题右操作 *\u002F .bar { display: flex; justify-content: space-between; align-items: center; gap: 12px; }\n\u002F* 吸底页脚 *\u002F            body { min-height: 100svh; display: flex; flex-direction: column; } main { flex: 1; } 等高卡片靠 align-items: stretch（Flex 的默认值）自动实现，卡片内部把页脚写成 margin-top: auto 或给它 flex: 1 吃掉中间空白，就能「底部对齐」。这是 Flex 比 float 简单得多的地方。",{"id":14612,"title":5163,"titles":14613,"content":5166,"level":49},"\u002Ftutorials\u002Fcss#十一grid从网格轨道到自适应布局",[5],{"id":14615,"title":14257,"titles":14616,"content":14617,"level":82},"\u002Ftutorials\u002Fcss#grid-template-columns-与-fr",[5,5163],".g { display: grid; grid-template-columns: 200px 1fr 1fr; gap: 16px; } fr 是剩余空间的等份，只在 grid-template-* 里可用（写成 width: 1fr 无效）。2fr 1fr 是二比一，但比例算的是扣掉固定轨道与 gap 之后的剩余空间，所以固定列宽变化时比例看起来会变，这是正常的。 repeat(12, 1fr) 是简写；repeat(3, minmax(0, 1fr)) 是防御性写法（理由见上一章的 min-content 问题）；grid-template-columns: [侧栏] 240px [主区] 1fr 给轨道命名，子项就能写 grid-column: 侧栏。 行也一样：grid-template-rows 描述你写明的轨道，超出的部分进入隐式轨道，尺寸由 grid-auto-rows 决定（默认 auto），排布方向由 grid-auto-flow（row \u002F column \u002F dense）控制。",{"id":14619,"title":5304,"titles":14620,"content":14621,"level":82},"\u002Ftutorials\u002Fcss#命名区域把布局写成-ascii-图",[5,5163],".page {\n  display: grid;\n  grid-template-columns: 216px minmax(0, 1fr) 232px;\n  grid-template-rows: 48px 1fr 40px;\n  grid-template-areas:\n    \"head head head\"\n    \"nav  main aside\"\n    \"foot foot foot\";\n}\nheader { grid-area: head; }\nmain   { grid-area: main; } 这是 Grid 比 Flex 更适合「整页骨架」的原因：响应式换布局只需重写 grid-template-areas 那几行，HTML 与子项选择器一行不动。约束是区域名组成的矩形必须完整（不能有 L 形空洞），否则整条声明静默失效；空格子用 . 表示。 本站教程详情页的三栏（左目录 \u002F 正文 \u002F 右目录）就是这个思路——只是用 max-width 媒体查询把三栏收成单栏，并让左栏变成横向滚动的 chip 条。",{"id":14623,"title":5457,"titles":14624,"content":14625,"level":82},"\u002Ftutorials\u002Fcss#跨行跨列数的是线",[5,5163],"N 条线围成 N-1 个格子，所以「占第 2、3 列」写作 grid-column: 2 \u002F 4。-1 是最后一条线，grid-column: 1 \u002F -1 就是横跨整行——写整行标题、整行页脚最常用。 grid-area 的四值顺序是 行开始 \u002F 列开始 \u002F 行结束 \u002F 列结束（与 margin 的顺时针一样）。grid-column: span 3 让自动放置决定起点，比写死线号更适合响应式（断点变化时线号会全部错位）。",{"id":14627,"title":14261,"titles":14628,"content":14629,"level":82},"\u002Ftutorials\u002Fcss#一行代码的响应式minmax-auto-fit-auto-fill",[5,5163],".cards {\n  display: grid;\n  grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));\n  gap: 16px;\n} auto-fit 与 auto-fill 的差别只在末尾有没有空轨道：auto-fill 保留算出来但没内容的轨道（卡片会显得靠左一小堆），auto-fit 把空轨道压成 0，让现存卡片继续伸展铺满。内容少又要「铺满」用 auto-fit；内容多、希望网格始终对齐用 auto-fill。 min(240px, 100%) 里那个 100% 是防窄屏横向滚动条的：容器比 240px 还窄时，minmax 的下限会强行撑破容器。 这套写法能替掉大量「卡片墙 \u002F 图库 \u002F 相关列表」的媒体查询——按内容自身宽度决定断点，比按设备宽度更稳。",{"id":14631,"title":14263,"titles":14632,"content":14633,"level":82},"\u002Ftutorials\u002Fcss#subgrid让子卡片共享外层轨道",[5,5163],".panel { display: grid; grid-row: span 3; grid-template-rows: subgrid; } 跨的格子不再是「自己的轨道」而是复用父网格的，于是每张卡片的标题行、正文行、按钮行严格对齐——以前要每张卡硬写行高才能做到的事。浏览器基线：subgrid 需要较新的内核（Firefox 71 \u002F Chrome 117 \u002F Safari 16 一线），旧内核会退化成普通 Grid 而不破坏内容；上线前请以 caniuse 当前数据为准，并配 @supports (grid-template-rows: subgrid) 做渐进增强（第二十章）。",{"id":14635,"title":5673,"titles":14636,"content":14637,"level":82},"\u002Ftutorials\u002Fcss#grid-的三套对齐属性",[5,5163],"justify-items \u002F align-items：格子内部内容在水平\u002F垂直的位置；place-items 是两者简写（display: grid; place-items: center; 是最短的完全居中）； justify-content \u002F align-content：整个网格轨道在容器里的分布（有剩余空间才看得出）； justify-self \u002F align-self：单个子项叛逆。 Flex 只有 align-items\u002Fjustify-content 这一套；Grid 因为有两个明确的轴向，同名属性含义不同（Grid 的 justify-* 管水平、align-* 管垂直）。这正是「同一行 CSS 在两种布局下表现不同」的来源，别混着记。",{"id":14639,"title":5728,"titles":14640,"content":14641,"level":82},"\u002Ftutorials\u002Fcss#常见坑速查",[5,5163],"现象 原因与修法 设了 1fr 仍横向溢出 1fr 下限是 auto（= min-content）→ 写 minmax(0, 1fr) 子项 height: 100% 不生效 用 grid-template-rows 或依赖默认的 align-items: stretch，别猜父高 四周空白不对称 四周来自容器 padding，gap 只管轨道之间 auto-fit 把卡片拉得很宽 给上限：minmax(240px, 320px)，外层再 justify-content: center 子项叠在同一格 忘记 gap 或显式写了相同的 grid-area（Grid 允许重叠，做叠层时是特性）",{"id":14643,"title":5825,"titles":14644,"content":14645,"level":49},"\u002Ftutorials\u002Fcss#十二定位与层叠上下文",[5],"position 决定元素相对谁偏移；z-index 只在同一个层叠上下文内比大小。这两条理解到位，「弹层被挡住」「absolute 跑到左上角」之类的排错时间能砍掉一半。",{"id":14647,"title":14269,"titles":14648,"content":14649,"level":82},"\u002Ftutorials\u002Fcss#五种-position-的差别在参考系",[5,5825],"值 参考系 是否脱离文档流 典型用途 static —（top\u002Fleft 完全无效） 否 默认 relative 自身正常位置 否（原空间保留） 给子绝对定位当锚点、微调图标 absolute 最近的已定位祖先 是 徽标、下拉、遮罩 fixed 视口（祖先有 transform 类属性时改变） 是 吸底按钮、对话框 sticky 滚动容器 + 自身所在区块范围 否 表头、分区标题、吸附导航 sticky 失效的三个常见原因：没写 top 等偏移值、某个祖先设了 overflow（改变了滚动容器）、父容器高度不足以容纳滑动范围（吸附不了几像素就跟着走了）。top 在有吸顶页头的站点里通常要写成 var(--header-h)，否则会被盖住——本站左右目录栏正是用 position: sticky + top 与页头高度联动。 表格 \u003Cthead> 也能 sticky，但需要 border-collapse: separate（合并边框时边框不跟随）。",{"id":14651,"title":14271,"titles":14652,"content":14653,"level":82},"\u002Ftutorials\u002Fcss#inset-简写与三种绝对居中",[5,5825],"inset: 8px 12px auto auto 是 top right bottom left，顺序与 margin 一致。绝对居中三种写法： \u002F* 一：Grid（推荐） *\u002F .wrap { display: grid; place-items: center; }\n\u002F* 二：transform（不要求父级尺寸） *\u002F .m { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }\n\u002F* 三：inset + auto margin（要求固定宽高） *\u002F .m { position: absolute; inset: 0; margin: auto; width: 120px; height: 40px; } translate(-50%, -50%) 的百分比相对自身尺寸，这是它能在不知宽高时居中的原因。",{"id":14655,"title":14273,"titles":14656,"content":14657,"level":82},"\u002Ftutorials\u002Fcss#z-index只在自己的层叠上下文里比大小",[5,5825],"z-index 只在同一个层叠上下文内有意义。父级一旦形成层叠上下文，子级写 z-index: 9999 也出不去——它只能在那个盒子内部称王，外面一个 z-index: 2 的兄弟就能盖住它。 创建层叠上下文的条件（任一成立）： position 非 static 且 z-index 非 auto（最常见的来源）； opacity 小于 1； transform \u002F filter \u002F backdrop-filter \u002F perspective \u002F mask 相关属性； will-change 里声明了上述任一属性； isolation: isolate（专门用来创建上下文的属性，语义最干净）； position: fixed； Flex \u002F Grid 子项的 z-index 非 auto； contain: paint \u002F content-visibility 等生成独立绘制层的属性。 排错顺序固定：① 从目标元素往上找最近的层叠上下文祖先；② 只在这一层里比 z-index；③ 需要「跳出去」时，要么去掉祖先的 transform\u002Ffilter，要么把浮层挂到更外层的容器（或用原生 \u003Cpopover>、position: fixed）。 数值请建自己的刻度而不是 9999：10 下拉、50 遮罩、100 对话框、200 toast。当所有人都写 9999 时，任何一层都赢不了。 顺带区分两件事：层叠上下文（本节的几何\u002F属性问题）与层叠层级（@layer，第十六章的声明顺序问题）名字相近，机制完全无关。",{"id":14659,"title":14275,"titles":14660,"content":14661,"level":82},"\u002Ftutorials\u002Fcss#fixed-会被祖先抢走",[5,5825],"祖先一旦有 transform \u002F filter \u002F perspective \u002F backdrop-filter \u002F will-change \u002F contain: paint，fixed 的参考系就从视口变成那个祖先，表现为「弹窗跟着页面乱跑」。动画里给祖先加 transform 时尤其容易碰上。",{"id":14663,"title":6339,"titles":14664,"content":14665,"level":82},"\u002Ftutorials\u002Fcss#实战配方",[5,5825],"\u002F* 下拉菜单 *\u002F .dd { position: relative; } .dd-menu { position: absolute; top: calc(100% + 4px); left: 0; }\n\u002F* 徽标 *\u002F .badge-wrap { position: relative; } .badge { position: absolute; top: -6px; right: -6px; }\n\u002F* 遮罩 *\u002F .mask { position: fixed; inset: 0; background: rgb(0 0 0 \u002F .5); z-index: 50; } 下拉要同时写 :hover 和 :focus-within，否则键盘用户打不开。弹出层靠近视口边缘被裁掉时，用 position: fixed + 定位 API，或直接改用原生 \u003Cpopover> \u002F anchor()（仍在演进，见 HTML 教程第十三章）。",{"id":14667,"title":6534,"titles":14668,"content":14669,"level":49},"\u002Ftutorials\u002Fcss#十三响应式与流式排版能连续变化的就别用断点",[5],"响应式的目标不是「适配三种手机」，而是任何宽度都不破。做法上分两层：能用连续函数解决的（字号、间距、卡片列数）用流式；真的需要结构切换时（三栏变一栏、导航变汉堡）才用媒体查询。",{"id":14671,"title":6549,"titles":14672,"content":14673,"level":82},"\u002Ftutorials\u002Fcss#断点跟着内容走不跟着机型走",[5,6534],"把浏览器从 320px 慢慢拉宽，在哪里变丑就在哪里设断点——通常 2 到 4 个就够。照抄某个框架的 576\u002F768\u002F992\u002F1200 能用，但那些数字与你的内容无关。 单位建议写 rem（min-width: 40rem）而不是 px：用户放大根字号时媒体查询会提前触发，避免文字溢出。 新语法支持范围表达式，读起来更直观： @media (40rem \u003C= width \u003C= 60rem) { … }   \u002F* 等价于 min-width 与 max-width 的 and 组合 *\u002F\n@media (min-width: 60rem), (orientation: landscape) { … }   \u002F* 逗号 = or *\u002F",{"id":14675,"title":14281,"titles":14676,"content":14677,"level":82},"\u002Ftutorials\u002Fcss#移动优先默认写窄屏逐级-min-width-增强",[5,6534],".layout { display: grid; gap: 12px; }                        \u002F* 默认：单列，不包在媒体查询里 *\u002F\n@media (min-width: 40rem) { .layout { grid-template-columns: 1fr 1fr; } }\n@media (min-width: 60rem) { .layout { grid-template-columns: 200px 1fr 200px; } } 好处是基础样式就是最小屏样式，逐级叠加；反过来的桌面优先（默认给桌面、逐级 max-width 降级）容易漏掉基础样式，也让覆盖关系变成「后写的规则更弱」，与维护成本相悖。",{"id":14679,"title":6761,"titles":14680,"content":14681,"level":82},"\u002Ftutorials\u002Fcss#不只是宽度这些也属于媒体查询",[5,6534],"特性查询 用途 prefers-color-scheme: dark 跟随系统深浅色（本站用 html[data-theme] 手动切换，见第十四章） prefers-reduced-motion: reduce 关闭\u002F收敛动效，必须提供（第十八章） hover: hover and pointer: fine 只给鼠标设备写 hover 效果，避免触屏「点一下卡在 hover 态」 orientation \u002F aspect-ratio 横竖屏、宽高比 display-mode: standalone PWA 已安装态 forced-colors: active Windows 高对比模式，需要专门准备描边 print 打印：隐藏导航、展开折叠内容、break-inside: avoid、给外链补真实地址 全站级降级写法（可接受，但更好的做法是逐条设计静态替代方案）： @media (prefers-reduced-motion: reduce) {\n  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }\n}",{"id":14683,"title":14284,"titles":14684,"content":14685,"level":82},"\u002Ftutorials\u002Fcss#流式排版clamp-min-max",[5,6534],"clamp(最小, 理想, 最大) 让数值随视口连续变化： h1 { font-size: clamp(1.5rem, 1.06rem + 2.2vw, 3rem); }\nsection { padding-block: clamp(24px, 4vw, 64px); gap: clamp(8px, 1.5vw, 20px); } 理想值必须是带视口单位的表达式才会真的流动（只写单值就退化成 min\u002Fmax 选择）。斜率换算：(最大px − 最小px) ÷ (最大视口px − 最小视口px) × 100，基准 = 最小px − 斜率 × 最小视口px ÷ 100。 min() \u002F max() 常一行替掉一条媒体查询： .wrap { width: min(100% - 2rem, 68rem); margin-inline: auto; }   \u002F* 上限 68rem，窄屏自动留边距 *\u002F\n.gutter { padding-inline: max(1rem, env(safe-area-inset-left)); }  \u002F* 刘海屏安全区 *\u002F",{"id":14687,"title":14286,"titles":14688,"content":14689,"level":82},"\u002Ftutorials\u002Fcss#aspect-ratio-与-object-fit图片适配的两个正交属性",[5,6534],"aspect-ratio: 16 \u002F 9 让盒子保持比例（取代 padding-top: 56.25% 那套 hack）；object-fit 让替换元素的内容在这个盒子里如何被裁： 值 行为 用途 fill 默认，拉伸变形 几乎不用 contain 完整显示，可能留白 logo、截图、图表 cover 铺满并裁切 等尺寸缩略图、卡片封面 none 原尺寸居中裁 图标 scale-down none 与 contain 中取较小的 大图不放大 配 object-position: right top 指定裁切时保留哪一侧（人像图常用 center 25% 保住脸）。卡片封面的标准配方就是两者相加：aspect-ratio: 16 \u002F 9 + object-fit: cover——本站教程入口卡片正是这个写法，所以三张 16:9 的封面 SVG 放进去不会被裁掉内容。 还有一条防布局抖动的规则（CLS）：\u003Cimg> 必须写 width\u002Fheight 属性，配合 img { max-width: 100%; height: auto; }，比例由 HTML 属性提供、尺寸由 CSS 限制。",{"id":14691,"title":7321,"titles":14692,"content":7324,"level":49},"\u002Ftutorials\u002Fcss#十四自定义属性与主题化",[5],{"id":14694,"title":7332,"titles":14695,"content":14696,"level":82},"\u002Ftutorials\u002Fcss#声明与读取两条语法",[5,7321],":root { --brand-500: #0969da; --radius-3: 10px; --space-3: 16px; }\n.btn { background: var(--brand-500); border-radius: var(--radius-3); padding: var(--space-3); } 它与预处理器变量的本质区别：预处理器变量在编译期被替换成常量，自定义属性在渲染期按元素逐个求解。所以它是活的——会继承、会被就近覆盖、能被 JS 在运行时改，也能被媒体查询改写。",{"id":14698,"title":7426,"titles":14699,"content":14700,"level":82},"\u002Ftutorials\u002Fcss#命名与作用域",[5,7321],"命名建议「类别-语义-刻度」：--text-1、--bg-2、--brand-500、--space-3、--radius-2。反面例子是 --blue 和 --big：这类「描述外观」的名字在换主题时会立刻失效（暗色下那个蓝已经不是你写的蓝），而描述意图的名字只需要改取值。 作用域由声明它的那个选择器决定： 写在 :root → 全站可见； 写在组件类上 → 只有该子树可见； 写在 @media 里 → 响应式变量（本站的 --header-h 就随窄屏变化）； 写在元素的内联 style 上 → 只有这一个元素及其后代可见，也是「使用方定制组件」的入口。",{"id":14702,"title":14292,"titles":14703,"content":14704,"level":82},"\u002Ftutorials\u002Fcss#var-的回退值与无效行为",[5,7321],".x { color: var(--maybe, blue); }          \u002F* 变量不存在时用回退值 *\u002F\n.y { padding: var(--a, var(--b, 8px)); }   \u002F* 回退可以嵌套 *\u002F\n.z { width: calc(var(--w, 100px) * 2); }   \u002F* 回退参与计算 *\u002F 变量未定义且没给回退时，整条声明在该元素上被视为无效（相当于回到继承值或初始值），不会报错、不会崩溃——所以「变量拼错」的表现是样式静默丢失，排查要看 Computed 面板。 一个必须知道的特例：用 @property 注册过的变量有「guaranteed-invalid」之外的初值语义，值为空时行为与未定义不同；未注册的变量请一律给回退值。",{"id":14706,"title":7616,"titles":14707,"content":14708,"level":82},"\u002Ftutorials\u002Fcss#主题化只改变量一条规则都不动",[5,7321],":root { --bg-1: #fff; --text-1: #24292f; --brand-500: #0969da; color-scheme: light; }\nhtml[data-theme='dark'] { --bg-1: #0d1117; --text-1: #e6edf3; --brand-500: #6aa8ff; color-scheme: dark; } 三件配套事项： 写 color-scheme：一行让浏览器的默认控件、滚动条、表单底色、高亮色一起切换，成本极低； 暗色下品牌色要重新调：降饱和、提明度（#0969da → #6aa8ff）。深蓝底配高饱和原色会「发光」刺眼；简单取反（黑底白字）也不是好主题； 切换与持久化：JS 改 \u003Chtml> 的 data-theme，把选择存进 localStorage，并在首屏绘制前用一段内联脚本应用，否则会闪一下浅色（FOUC）。 本站就是这一套：main.css 里 html[data-theme='dark'] 覆盖同一批变量名，所有组件的规则完全不用改。 如果你更希望跟随系统而不是手动切换，把选择器换成 @media (prefers-color-scheme: dark)（第十三章）；两者可以共存：先按系统给默认值，再用 data-theme 让用户覆盖。",{"id":14710,"title":7776,"titles":14711,"content":14712,"level":82},"\u002Ftutorials\u002Fcss#组件级变量把变量当公共-api",[5,7321],".badge { --badge-bg: #eaeef2; --badge-fg: #24292f; background: var(--badge-bg); color: var(--badge-fg); } 使用方不需要新增类名、不需要 !important，只要给祖先或自身设变量就能定制： \u003Cspan class=\"badge\" style=\"--badge-bg:#ddf4ff\">定制色\u003C\u002Fspan>\n\u003Cdiv class=\"zone\">\u003C!-- 这里的 badge 全部换色 -->\u003C\u002Fdiv> 这比「写十个修饰类」更可组合，尤其适合图表、卡片、主题色块一类需要按数据着色的组件。",{"id":14714,"title":7899,"titles":14715,"content":14716,"level":82},"\u002Ftutorials\u002Fcss#用变量驱动计算与响应式",[5,7321],".grid-auto { --cols: 3; grid-template-columns: repeat(var(--cols), 1fr); gap: var(--space-3); }\n.bar { --pct: 62%; } .bar > i { width: var(--pct); }\n@media (max-width: 40rem) { :root { --cols: 1; --space-3: 12px; --header-h: 96px; } } 把「断点决定的一组尺寸」集中成变量，比在每个规则里重复写媒体查询干净得多——这也是本站把吸顶高度写成 --header-h 并在滚动判定里读取的原因。",{"id":14718,"title":8052,"titles":14719,"content":14720,"level":82},"\u002Ftutorials\u002Fcss#用-js-读写变量",[5,7321],"getComputedStyle(el).getPropertyValue('--brand-500').trim();   \u002F\u002F 读解析后的值\nel.style.setProperty('--pct', '80%');                          \u002F\u002F 写（只影响这棵子树）\nel.style.removeProperty('--pct');                              \u002F\u002F 删内联值，落回样式表 反过来「JS 把状态传给 CSS」也用它，比切一堆类名更可组合： \u003Cdiv style=\"--index: 3\">…\u003C\u002Fdiv> .item { transition-delay: calc(var(--index) * 60ms); } 一个限制：变量本身不能被平滑过渡（浏览器不知道该按什么规则插值）。要动画变量，先用 @property 注册语法类型： @property --pct { syntax: \"\u003Cpercentage>\"; inherits: false; initial-value: 0%; }\n.bar > i { width: var(--pct); transition: --pct .6s ease; }   \u002F* 现在可动画了 *\u002F 浏览器基线：@property 在 Chrome 85 \u002F Safari 16.4 \u002F Firefox 128 一线支持，属渐进增强能力，不支持时过渡静默退化为跳变，布局不受影响；落笔前请以 caniuse 当前数据为准。",{"id":14722,"title":8290,"titles":14723,"content":14724,"level":82},"\u002Ftutorials\u002Fcss#常见误区速查",[5,7321],"误区 事实 变量是常量 按元素逐个求解，会继承、会被就近覆盖 值只能是颜色或长度 可以是任意 token 序列，包括整串阴影值 calc() 里可以随便乘变量 长度计算要求带单位，纯数字变量要写成 calc(var(--n) * 1px) 循环引用会崩 相关声明静默无效（不报错，但很难查） 变量性能差 解析成本可忽略，别为了「少几个变量」放弃主题化",{"id":14726,"title":8354,"titles":14727,"content":8357,"level":49},"\u002Ftutorials\u002Fcss#十五现代选择器与函数少写权重少写类名",[5],{"id":14729,"title":14301,"titles":14730,"content":14731,"level":82},"\u002Ftutorials\u002Fcss#is-与-where把选择器体积收敛掉",[5,8354],"\u002F* 展开写法：4 个前缀 × 3 个后缀 = 12 条 *\u002F\n.card .title, .card .meta, .panel .title, .panel .meta { … }\n\u002F* 收敛写法：一条 *\u002F\n:is(.card, .panel) :is(.title, .meta) { … } 两者唯一的但关键的差别是权重： :is(A, B) 的权重 = 参数里最高的那个； :where(A, B) 的权重 = 0。 所以给组件写「默认样式」时用 :where()（使用方随手就能覆盖，不需要 !important），需要强调时用 :is()。 解析风险必须知道：:is() \u002F :where() 参数里出现浏览器无法解析的选择器片段，会导致整条规则被丢弃。因此不要把「很新的选择器」塞进它们的参数里当降级方案——那种情况请用 @supports（第二十章）或独立规则。",{"id":14733,"title":14303,"titles":14734,"content":14735,"level":82},"\u002Ftutorials\u002Fcss#has真正的父向选择器",[5,8354],".item:has(input:checked) { border-color: #0969da; }   \u002F* 状态上移到容器 *\u002F\n.card:has(img) { padding-top: 0; }                    \u002F* 有封面图的卡片去掉顶部留白 *\u002F\nli:has(> ul) { font-weight: 700; }                    \u002F* 「有子列表」的项加粗 *\u002F\nbody:has(#search:focus) .hero { opacity: .35; }       \u002F* 页面级联动，谨慎使用 *\u002F 参数里还能写相对关系：:has(+ .next)（紧跟其后的兄弟存在）、:has(~ .x)（之后同级存在）、:has(> .x)（直接子元素）。它替掉了「用 JS 监听后给父加类」这一大类代码。 浏览器基线：:has() 已在 Chrome \u002F Edge \u002F Safari \u002F Firefox 全量支持（Firefox 121 起），属 Baseline 可用。代价是浏览器要在结构变化时重算，避免在超大列表上写高成本的选择器链（例如 body:has(...) 这种全局查询）。",{"id":14737,"title":14305,"titles":14738,"content":14739,"level":82},"\u002Ftutorials\u002Fcss#not-的多参数与结构伪类",[5,8354],".btn:not(.primary, [disabled]) { … }    \u002F* 逗号 = and，等价于串联两个 :not() *\u002F\nli:nth-child(2 of .tag) { … }           \u002F* 「.tag 里的第 2 个」 *\u002F\ntr:nth-child(odd of :is(.tag, .note)) { … }\nli:nth-last-child(-n+2) { … }           \u002F* 倒数两项 *\u002F :nth-child(An+B of S) 解决了「跳过表头后再数奇偶」「只在某类元素里数第 N 个」这两个长期只能靠 JS 的需求。浏览器基线：这一形态同样已是主流内核全量支持（Firefox 113 \u002F Chrome 111 一线起）。",{"id":14741,"title":8732,"titles":14742,"content":14743,"level":82},"\u002Ftutorials\u002Fcss#状态伪类表单与交互的真相来源",[5,8354],"选择器 含义 注意 :focus-visible 只在「该显示焦点环」时命中（键盘导航） 替代 outline: none 的正确写法，可访问性硬要求 :focus-within 后代任一元素获得焦点时命中容器 搜索框整块高亮的最省方案 :valid \u002F :invalid 校验状态 未交互的空必填项也算 invalid，直接上红框会吓人 :user-invalid 用户改过之后才判无效 做红框提示比 :invalid 合适（较新内核） :placeholder-shown 占位符仍显示 浮动 label 老配方，现在可用 :has() 更直观 :checked \u002F :default \u002F :indeterminate 选中 \u002F 默认选中 \u002F 半选 :indeterminate 只能由 JS 设置 :open \u003Cdetails> 展开 纯 CSS 折叠面板的状态源（第十七章配合伪元素） :target URL 的 hash 指向它 「定位高亮」零成本 :lang(zh) 按 lang 匹配 中英文的标点、字距、字体差异靠它",{"id":14745,"title":14308,"titles":14746,"content":14747,"level":82},"\u002Ftutorials\u002Fcss#calc-与混合单位",[5,8354],".el { width: calc(100% - 2 * 16px); }               \u002F* %、px 必须在 calc 里才能相减 *\u002F\n.el { font-size: calc(1rem + 0.5vw); }\n.el { padding: max(12px, calc((100% - 640px) \u002F 2)); }\n.el { margin-top: calc(var(--n) * 6px); } 三条规则：+ - 两侧要有空格；* \u002F 的乘除数必须是纯数字（带单位非法）；参与长度计算的变量必须自带单位。clamp()\u002Fmin()\u002Fmax() 与 calc() 可以互相嵌套（第十三章的流式排版正是这个组合）。 更新的数学函数（round()、mod()、sign()、hypot()、tan() 等）已进入主流内核，用于生产前请用 @supports 检查（第二十章）。",{"id":14749,"title":9090,"titles":14750,"content":14751,"level":82},"\u002Ftutorials\u002Fcss#什么时候不该用现代选择器",[5,8354],"用 :has() 表达「需要 JS 才能算出的业务状态」——状态该由 JS 写类，选择器只负责样式； 在 :is() 里混入不支持的选择器，整条规则被丢弃； 用超长选择器链去「抢权重」——权重问题回第四章，靠更合理的类名结构解决； 依赖 @scope \u002F :scope 做常规样式：仍在演进，生产项目请谨慎。",{"id":14753,"title":14311,"titles":14754,"content":14755,"level":49},"\u002Ftutorials\u002Fcss#十六原生嵌套与-layer",[5],"CSS 规范补上了两件 Sass 早就有的能力：原生嵌套（少写重复上下文）与层叠层（把「谁优先」变成显式声明）。",{"id":14757,"title":14314,"titles":14758,"content":14759,"level":82},"\u002Ftutorials\u002Fcss#原生嵌套-是外层选择器原文",[5,14311],".card {\n  border: 1px solid #d0d7de;\n  &:hover { border-color: #0969da; }        \u002F* → .card:hover *\u002F\n  & .meta { color: #57606a; }               \u002F* → .card .meta *\u002F\n  & + .card { margin-top: 10px; }           \u002F* → .card + .card *\u002F\n  &.is-active { border-width: 2px; }        \u002F* → .card.is-active —— 注意 & 与修饰符之间没有空格 *\u002F\n  &:has(img) { padding-top: 0; }\n  &::after { content: \"\"; }\n}\n.btn { &--primary { … } }                    \u002F* → .btn--primary，BEM 修饰符最短写法 *\u002F 空格是有语义的：&--hot 是 .card--hot，& --hot 是后代选择器。这是嵌套最常见的笔误。 & 出现在最前面时可以省略（ .card { h3 { … } }），但不建议——省略后隐含的是后代关系，权重和匹配范围都变了，可读性也下降。 条件规则可以写在规则内部，包括媒体查询、@supports、@container： .menu { @media (max-width: 24rem) { & { font-size: 13px; } } } 浏览器基线：原生嵌套（含 &、条件规则内嵌）在 Safari 16.5 \u002F Chrome 112 \u002F Firefox 117 一线已全量支持，属 Baseline 可用。需要兼容更旧内核时，让构建工具（Sass、PostCSS、Lightning CSS）降级展开，不要在生产里裸写。",{"id":14761,"title":9401,"titles":14762,"content":14763,"level":82},"\u002Ftutorials\u002Fcss#嵌套的代价选择器膨胀",[5,14311],"\u002F* 四层嵌套写起来爽，展开后是这种怪物： *\u002F\n.page .section .list .item:hover .title span { … }   \u002F* 权重 (0,4,3)，几乎无法覆盖 *\u002F 症状：想改一个标题颜色只能加 !important；改一处 DOM 结构样式全断。四条经验值： 嵌套深度 ≤ 2 层（组件本体 + 一个子元素或状态）； 不要把布局上下文写进组件——组件不该知道自己被放在哪个 .page .section 里； 需要跨层级联动时用「变量或状态类」而不是选择器链（第十四章的组件变量）； 权重问题回第四章解决，靠类名结构而不是嵌套堆叠。",{"id":14765,"title":14317,"titles":14766,"content":14767,"level":82},"\u002Ftutorials\u002Fcss#layer把优先级写成一句声明",[5,14311],"@layer reset, base, vendors, components, utilities, overrides;   \u002F* 越靠后越优先 *\u002F\n\n@layer base     { .panel { border-color: #bf8700; } }\n@layer vendors  { .panel { border-color: #cf222e; } }   \u002F* 后声明的层赢，与书写顺序无关 *\u002F 它解决的是老问题：第三方库和工具类的样式总在悄悄抢权重。有了层，你不再靠「写得靠后」或「加 !important」取胜，而是靠声明层顺序。 同名层会合并；@layer components { @layer button { … } } 形成 components.button 子层；还可以让第三方 CSS 进层而不改它源码： @layer vendors { @import \"reset.css\"; }",{"id":14769,"title":9601,"titles":14770,"content":14771,"level":82},"\u002Ftutorials\u002Fcss#完整的层叠顺序必须记住的一张表",[5,14311],"从高到低： 进行中的过渡\u002F动画声明（第十八章）； 用户 !important（扩展、用户样式表）； 作者 !important：未分层最高，各层之间则反向（越早声明的层越优先）——这条最反直觉； 未分层（unlayered）作者样式：比所有已声明的层都高； 分层作者样式：按 @layer a, b, c; 顺序，c > b > a，同层内回到第四章的权重规则； 用户样式表； 浏览器默认。 第 4 条是实践中最容易踩的：「随手加的一行补丁」默认就是最强，会压住你所有分层规则。想让补丁被层管理，就把它放进最末的层。 另外区分两个名字相近、机制无关的概念：层叠上下文（第十二章的几何问题）与层叠层级（本节的声明顺序问题）。 浏览器基线：@layer 与 layer() 函数在 Chrome 99 \u002F Safari 15.4 \u002F Firefox 103 一线已全量支持。用法建议：项目从零开始才引入分层；给已有大项目补层容易和未分层样式打架。",{"id":14773,"title":9677,"titles":14774,"content":14775,"level":82},"\u002Ftutorials\u002Fcss#自查",[5,14311],"「嵌套写了没生效」→ 检查 & 与空格（&--hot vs & --hot）； 「层里的样式被随手一行盖掉」→ 那是未分层默认最高，符合规范，把补丁挪进 overrides 层； 「加了 !important 反而输给早层」→ 正确行为； 「DevTools 里看不懂谁赢」→ Styles 面板会显示层名与权重，逐条取消勾选验证（第二十章）。",{"id":14777,"title":9709,"titles":14778,"content":14779,"level":49},"\u002Ftutorials\u002Fcss#十七伪元素与生成内容",[5],"::before \u002F ::after 是「不写进 HTML 的装饰盒子」。它的价值在于让表现性内容与文档结构分离——代价是这份内容对搜索、复制、辅助技术都不可靠。",{"id":14781,"title":14323,"titles":14782,"content":14783,"level":82},"\u002Ftutorials\u002Fcss#只有一个前提必须有-content",[5,9709],".x::before { content: \"\"; }      \u002F* 生成一个空盒子 —— 装饰全靠它 *\u002F\n.x::before { content: none; }    \u002F* 完全不生成，伪元素不存在 *\u002F 不写 content 时伪元素不会渲染。单冒号 :before 也能工作，但规范用双冒号区分伪元素与伪类（单冒号）。",{"id":14785,"title":14325,"titles":14786,"content":14787,"level":82},"\u002Ftutorials\u002Fcss#content-的取值形态",[5,9709],".x::before { content: \"文字\"; }\n.x::before { content: attr(data-icon) \" \"; }                    \u002F* 属性值，可拼接 *\u002F\n.x::after  { content: \"（来源：\" attr(data-src, \"未标注\") \"）\"; }  \u002F* attr() 第二参数是回退值 *\u002F\n.x::after  { content: url(arrow.svg); }                          \u002F* 图片 *\u002F\n.x::before { content: counter(n) \".\" counter(m); }               \u002F* 计数器 *\u002F\n.x::before { content: open-quote; }                              \u002F* 引号，跟随 lang 与 quotes *\u002F\n.x::before { content: \"\\201C 转义字符\"; }                        \u002F* Unicode 转义后要有空格 *\u002F",{"id":14789,"title":14327,"titles":14790,"content":14791,"level":82},"\u002Ftutorials\u002Fcss#counter章节自动编号",[5,9709],"body { counter-reset: sect sub; }              \u002F* 声明计数器（初值 0） *\u002F\n.sect { counter-increment: sect; }\n.sect::before { content: \"第 \" counter(sect) \" 节：\"; }\n.sub { counter-increment: sub; }\n.sub::before { content: counter(sect) \".\" counter(sub); }        \u002F* 两级编号 *\u002F counter() 的第二个参数可以指定样式：upper-roman、lower-alpha、cjk-decimal、decimal-leading-zero。它的价值不在替代 \u003Col>，而在「多级编号 + 非列表元素 + 跨元素拼字符串」这类真实需求（论文式标题、题号、章节引用）。 本站教程正文刻意不用自动编号：标题文字本身就是内容，编号写进正文而不是靠 CSS 生成，这样搜索结果、复制、读屏拿到的都是完整标题。",{"id":14793,"title":10118,"titles":14794,"content":14795,"level":82},"\u002Ftutorials\u002Fcss#其它伪元素一个比一个更只能装饰",[5,9709],"伪元素 能做什么 限制 ::before \u002F ::after 任意装饰盒子 每个元素只有两个 ::first-line \u002F ::first-letter 首行\u002F首字样式（杂志风） 只接受少量属性；::first-letter 不能作用于行内非替换元素 ::marker 列表记号的颜色、字重，甚至用 content 换成箭头 只开放 content\u002Fcolor\u002Ffont-* 等少数属性 ::selection 选中高亮配色 只允许 color\u002Fbackground\u002Ftext-shadow 等；对比度必须够 ::placeholder 占位符样式 默认带透明度，需要显式覆盖 ::backdrop \u003Cdialog>\u002F全屏时遮罩层样式 配合 color-mix() 做半透明遮罩很合适",{"id":14797,"title":10235,"titles":14798,"content":14799,"level":82},"\u002Ftutorials\u002Fcss#五个纯-css-装饰配方",[5,9709],"\u002F* 圆形序号徽标：counter + inline-grid 居中 *\u002F\n.steps { counter-reset: step; list-style: none; }\n.steps li { counter-increment: step; }\n.steps li::before { content: counter(step); display: inline-grid; place-items: center;\n                    width: 20px; height: 20px; border-radius: 50%; background: #0969da; color: #fff; }\n\u002F* 尖角 tooltip：零尺寸盒子 + 四条透明 border，只给一侧上色 *\u002F\n.tip::after { content: \"\"; position: absolute; top: 100%; border: 6px solid transparent; border-top-color: #24292f; }\n\u002F* hover 下划线：动 ::after 的 scaleX —— text-decoration 不能平滑过渡 *\u002F\n.ul-anim::after { content: \"\"; position: absolute; left: 0; right: 0; bottom: -2px; height: 2px;\n                  background: #0969da; transform: scaleX(0); transform-origin: left; transition: transform .22s; }\n.ul-anim:hover::after { transform: scaleX(1); }\n\u002F* 骨架屏：background-position 动画，不需要图片 *\u002F\n.skeleton { background: linear-gradient(90deg, #eaeef2 0 25%, #f6f8fa 37%, #eaeef2 63%) 0 0\u002F400% 100%;\n            animation: shimmer 1.4s ease infinite; } （伪元素与过渡\u002F动画的组合见第十八章；content 参与媒体查询做不同装饰也完全合法，见第十三章。）",{"id":14801,"title":10665,"titles":14802,"content":14803,"level":82},"\u002Ftutorials\u002Fcss#三个必须知道的限制",[5,9709],"不能嵌 HTML：content 里写 \u003Cb> 只会显示字面量。需要结构就写进 DOM。 不可选中、不可搜索、复制会丢失：所以「必需信息」不要只存在于伪元素里（价格、状态文字、必填星号的说明）。读屏支持参差不齐，把它当纯装饰最安全。 每个元素只有两个：需要三层装饰时——给父用 ::before、子元素用 ::after，或者改用真实 \u003Cspan>、多重 box-shadow、多层 background（第八章）。 一条判断标准：图片的说明文字属于 HTML（alt），装饰符号属于 CSS（content）。前者是内容，后者是表现。",{"id":14805,"title":10722,"titles":14806,"content":14807,"level":49},"\u002Ftutorials\u002Fcss#十八过渡变形与动画",[5],"动效的目标是「解释变化」，不是「装饰页面」。技术上只需要区分两件事：过渡负责两个状态之间，动画负责多帧序列。",{"id":14809,"title":14334,"titles":14810,"content":14811,"level":82},"\u002Ftutorials\u002Fcss#transition-的四要素",[5,10722],".btn { transition: background-color 200ms ease-out 0s, border-color 200ms ease-in 50ms; } 顺序是 属性 \u002F 时长 \u002F 缓动 \u002F 延迟；两个时间同时出现时第一个是时长、第二个是延迟，写反含义就变。 最常见的笔误是把 transition 只写在 :hover 里——那样只有悬停时有过渡，移开时瞬间跳回。正确做法是写在基础状态上： .a { transition: all .3s; }        \u002F* ✓ *\u002F\n.a:hover { transform: translateY(-2px); } 不写 transition-property 时默认是 all，会带来意外的连锁动画（连布局属性都在补帧），建议显式列出要过渡的属性。",{"id":14813,"title":10873,"titles":14814,"content":14815,"level":82},"\u002Ftutorials\u002Fcss#缓动决定手感",[5,10722],"进入用 ease-out（快起手、慢落位）； 离开用 ease-in； 来回运动用 ease-in-out； 需要「有重量」的弹跳用 cubic-bezier(.34, 1.56, .64, 1)（控制点 y 超出 1 会过冲回弹）； 精灵图\u002F打字机用 steps(6, end)； 新写法 linear(0, .6 20%, 1 40%, .8 55%, 1) 直接按关键帧描述曲线，回弹不必再手算贝塞尔控制点。 一个常被忽略的细节：animation-timing-function 作用于每两个关键帧之间（不是整段动画），也可以写在关键帧内部逐段指定。",{"id":14817,"title":14337,"titles":14818,"content":14819,"level":82},"\u002Ftutorials\u002Fcss#transform2d3d-与支点",[5,10722],".x:hover { transform: translate(6px, -4px) rotate(-6deg) scale(1.1); }\n.wrap { perspective: 500px; }                 \u002F* 给 3D 一个观察距离 *\u002F\n.card:hover { transform: rotateY(180deg); }\n.origin { transform-origin: top left; }       \u002F* 旋转\u002F缩放的支点 *\u002F 三条要点： 顺序有意义：transform 是矩阵相乘，先 translate 再 rotate 与反过来结果不同； translate 的百分比相对自身尺寸——这是「未知宽高也能居中」的依据（第十二章）； scale 不改变布局占位，只是绘制时被放大，相邻元素不会让位（可能重叠）。 翻牌卡片：两面绝对定位叠在一起 + backface-visibility: hidden；立方体一类立体组合需要父级 transform-style: preserve-3d。",{"id":14821,"title":14339,"titles":14822,"content":14823,"level":82},"\u002Ftutorials\u002Fcss#只动-transform-与-opacity",[5,10722],"属性 代价 transform、opacity 只需合成，不触发布局与重排 → 动画首选 width\u002Fheight\u002Ftop\u002Fleft\u002Fmargin\u002Fpadding 触发布局（layout），多元素同时动会掉帧 box-shadow、border-radius、background-color 触发重绘（paint），大面积时明显 用 left\u002Ftop 做位移 改用 transform: translate()，视觉一致、成本低得多 想给阴影加过渡时不要直接动 box-shadow（中间帧发灰且要重绘整块模糊），把阴影画在伪元素上、动它的 opacity： .lift::after { content: \"\"; position: absolute; inset: 0; border-radius: inherit; z-index: -1;\n               box-shadow: 0 8px 22px rgba(0,0,0,.22); opacity: 0; transition: opacity .22s; }\n.lift:hover::after { opacity: 1; }",{"id":14825,"title":14341,"titles":14826,"content":14827,"level":82},"\u002Ftutorials\u002Fcss#keyframes-与-animation-属性族",[5,10722],"@keyframes rise { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }\n.item { animation: rise .5s ease-out both; animation-delay: calc(var(--i, 0) * 80ms); } 九个 longhand 里必须真正理解的三个： animation-fill-mode：forwards 结束后停在最后一帧，backwards 让延迟期间就显示第一帧，进入动画通常写 both（否则元素会先闪一下原位再飞入）； animation-delay 可以为负值：表示从动画中段开始播，做错峰循环很方便； animation-iteration-count 可以是小数：播到该比例停止。 多动画并列用逗号（animation: fade-in .6s both, nudge 1.4s infinite alternate;），第一个名字对应第一个时长。 进行中的动画声明优先级高于普通声明和 !important（第十六章的层叠表第 1 位）。所以「动画一跑 hover 就没反应」是规范行为，要先结束动画。",{"id":14829,"title":11484,"titles":14830,"content":14831,"level":82},"\u002Ftutorials\u002Fcss#重放暂停与错峰",[5,10722],"\u002F* 暂停：CSS 就能控制，不需要 JS 计时 *\u002F\n.paused .box { animation-play-state: paused; }\n\u002F* 重新触发同名动画：必须先移除、强制回流、再加回（JS 里的一行技巧） *\u002F\nel.classList.remove('run'); void el.offsetWidth; el.classList.add('run');\n\u002F* 错峰：把延迟交给变量，避免给每项写一条规则 *\u002F\n.item { animation-delay: calc(var(--i) * 80ms); }   \u002F* \u003Cli style=\"--i:2\"> *\u002F",{"id":14833,"title":14344,"titles":14834,"content":14835,"level":82},"\u002Ftutorials\u002Fcss#will-change先测量再加",[5,10722],".box { will-change: transform; }   \u002F* 提前把元素提升为合成层，避免动画开始时建层卡顿 *\u002F 三条纪律：只给「马上要动」的元素加（每个合成层都吃显存，几十层就负收益）；动画结束后移除；现代内核已经会对 transform\u002Fopacity 动画自动分层，实测收益常为零——先用 DevTools 的 Rendering（Paint flashing）与 Layers 面板确认再决定。 副作用要记住：will-change 会创建层叠上下文与包含块，可能改变 fixed 的参考系（第十二章）。",{"id":14837,"title":11616,"titles":14838,"content":14839,"level":82},"\u002Ftutorials\u002Fcss#滚动驱动动画新增能力",[5,10722],".bar { animation: grow linear both; animation-timeline: scroll(self); }\n\u002F* 也可以用命名滚动轴或元素可见度：animation-timeline: view(block 20% 60%) *\u002F 浏览器基线：滚动驱动动画目前在 Chromium 系（Chrome\u002FEdge 115+）可用，Safari\u002FFirefox 仍在演进，属渐进增强——必须保证「动画不跑时视图也成立」（例如进度条不跑时停在 0，而不是盖住内容）。落笔与上线前请以 caniuse 当前数据为准。",{"id":14841,"title":11665,"titles":14842,"content":14843,"level":82},"\u002Ftutorials\u002Fcss#动效的三条纪律",[5,10722],"只用于解释变化（位置、状态、加载进度），装饰性动效一律从简；时长 150–300ms 足够，超过 500ms 就会被感知为「慢」。 必须提供降级：@media (prefers-reduced-motion: reduce) 下关闭无限循环、把位移换成淡入（第十三章的全站写法）。 不要同时动很多个大面积元素：性能与注意力都是有限资源。",{"id":14845,"title":11692,"titles":14846,"content":14847,"level":49},"\u002Ftutorials\u002Fcss#十九视觉进阶渐变滤镜遮罩与混合",[5],"这一章的工具全部服务于同一句话：让「不需要作为内容存在」的视觉，不用图片也能做出来。反过来也是判断标准——如果一块视觉承载了信息（截图、图表、产品图），它就该是 \u003Cimg> 而不是 CSS。",{"id":14849,"title":11710,"titles":14850,"content":14851,"level":82},"\u002Ftutorials\u002Fcss#渐变从线性到锥形",[5,11692],"四种函数构成全部渐变能力： linear-gradient(135deg, #0969da, #8250df)                      \u002F* 角度或关键词 *\u002F\nradial-gradient(circle at 30% 30%, #fff 0 8%, #0969da 30%)     \u002F* 形状 + 圆心 + 色标区间 *\u002F\nconic-gradient(from 45deg at 50% 50%, red, gold, green, red)   \u002F* 绕一圈，色相环\u002F饼图 *\u002F\nrepeating-linear-gradient(...) \u002F repeating-conic-gradient(...) \u002F* 重复，条纹\u002F放射纹 *\u002F 两个立刻能用的配方： \u002F* 硬切色带：同一位置写两次色标 → 进度条、双色块 *\u002F\n.progress { background: linear-gradient(90deg, var(--brand-500) 62%, var(--bg-3) 62%); }\n\n\u002F* 环形进度：conic 上色 + mask 挖中心，纯 CSS 无 SVG *\u002F\n.ring { aspect-ratio: 1; border-radius: 50%;\n        background: conic-gradient(var(--brand-500) 0 var(--pct), var(--bg-3) var(--pct) 100%);\n        mask: radial-gradient(circle, transparent 0 55%, #000 56%); } 多层渐变叠加是「有质感的封面」的标准做法：一层径向高光 + 一层细密纹理 + 一层底色渐变，配合 background-blend-mode 决定层间混合方式（本章示例最后那个 hero 就是三层）。",{"id":14853,"title":14351,"titles":14854,"content":14855,"level":82},"\u002Ftutorials\u002Fcss#filter改自己的绘制结果",[5,11692],"filter: grayscale(1) saturate(1.6) blur(2px) drop-shadow(3px 4px 0 rgba(9,105,218,.5)); 可用函数：blur() brightness() contrast() grayscale() hue-rotate() invert() opacity() saturate() sepia() drop-shadow()； drop-shadow() 与 box-shadow 的区别：前者贴着透明轮廓画，适合异形\u002F带透明通道的图片，后者只按矩形盒子； 三个副作用：创建层叠上下文（第十二章）、改变 fixed 的参考系、动画 filter 成本高（模糊半径变化要重绘）。 实用配方：禁用态 grayscale(1) + opacity(.6)；hover 轻微提饱和比加遮罩更省；缩略图统一色调用 filter 而不是重新处理图片。",{"id":14857,"title":14353,"titles":14858,"content":14859,"level":82},"\u002Ftutorials\u002Fcss#backdrop-filter毛玻璃",[5,11692],".glass { background: rgba(255,255,255,.18);\n         backdrop-filter: blur(6px) saturate(1.4);\n         -webkit-backdrop-filter: blur(6px) saturate(1.4);\n         border: 1px solid rgba(255,255,255,.35); } 三条注意：需要 Safari 前缀；背后必须有内容才看得出效果（纯色底上等于白做）；大面积高斯模糊在低端设备上很贵，别给整页背景加。那条半透明 border 是让玻璃「看得见边界」的关键，缺了它面板会糊成一片。",{"id":14861,"title":14355,"titles":14862,"content":14863,"level":82},"\u002Ftutorials\u002Fcss#mask-与-clip-path软边界与硬边界",[5,11692],"mask clip-path 表达 Alpha\u002F亮度决定「哪里可见」，可以有渐变过渡 几何裁剪，只有硬边界 语法 与 background 几乎一致（mask-image\u002Fsize\u002Fposition\u002Frepeat） inset() circle() ellipse() polygon() path() 典型用途 图片右缘渐隐、用 SVG 当图标形状（颜色交给 CSS） 切角卡片、星形、hover 时从方到圆的形变 .fade-out { mask: linear-gradient(90deg, #000 40%, transparent); }        \u002F* 列表末尾渐隐 *\u002F\n.icon { mask: url(star.svg) center\u002Fcontain no-repeat; background: currentColor; }  \u002F* 随文字色变化的图标 *\u002F\n.card { clip-path: polygon(0 0, 100% 0, 100% 70%, 70% 100%, 0 100%); } 两者都会创建层叠上下文，也都会裁掉溢出内容与阴影（第十二章的包含块规则同样适用）。clip-path 在两个形状函数相同、点数一致时可以平滑过渡——这是形变动效的做法；无障碍角度注意：被裁掉的文字仍会被读屏念到，视觉信息丢失要自己兜住。",{"id":14865,"title":14357,"titles":14866,"content":14867,"level":82},"\u002Ftutorials\u002Fcss#mix-blend-mode-与-background-blend-mode",[5,11692],".overlay { mix-blend-mode: multiply; }        \u002F* 与背后元素混合 *\u002F\n.bg { background-blend-mode: multiply; }      \u002F* 自己的多层背景之间混合 *\u002F 常用值：multiply（变暗，适合阴影\u002F水印）、screen（变亮，适合光效）、overlay \u002F soft-light（保对比的叠加）、difference \u002F exclusion（反色文字）、hue \u002F luminosity（给图片换色相）。 关键的一条：给混合区域加 isolation: isolate，否则它会跟整个祖先背景混合，页面别处会出现莫名其妙的颜色变化（同时你也顺手创建了层叠上下文，见第十二章）。",{"id":14869,"title":12506,"titles":14870,"content":14871,"level":82},"\u002Ftutorials\u002Fcss#什么时候不要用这些",[5,11692],"首屏大图：仍然应该 \u003Cimg> + srcset（能缓存、能裁切、能懒加载、有 alt）； 需要印刷\u002F导出 PDF 的视觉：filter 与 mask 在打印管线里表现不一致； 大面积持续动画的 filter\u002Fbackdrop-filter：低端设备掉帧明显（第十八章的性能原则）。",{"id":14873,"title":14360,"titles":14874,"content":34,"level":49},"\u002Ftutorials\u002Fcss#二十容器查询supports-与调试排错",[5],{"id":14876,"title":12549,"titles":14877,"content":14878,"level":82},"\u002Ftutorials\u002Fcss#两条语句就够",[5,14360],"\u002F* 一、把某个祖先声明为查询容器 *\u002F\n.card-zone { container-type: inline-size; container-name: cardzone; }\n\u002F* 二、子树内部按它的尺寸写规则（查询的是祖先，样式给后代） *\u002F\n@container cardzone (min-width: 340px) { .media { grid-template-columns: 128px 1fr; } } 也可以不写 container-name（匿名容器），但同名查询会命中「最近的」容器，跨组件复用时容易串味——给容器命名是更稳的习惯。简写形式：container: inline-size \u002F cardzone;。 它的价值：同一张卡片放进侧栏（窄）、主区（中）、整页 banner（宽），组件源码完全相同，表现由容器决定。媒体查询回答「屏幕多大」，容器查询回答「我被放进多大的地方」——后者才是组件级响应式。",{"id":14880,"title":14364,"titles":14881,"content":14882,"level":82},"\u002Ftutorials\u002Fcss#container-type-的三个值与代价",[5,14360],"值 可查询 副作用 inline-size 只有宽度轴 最常用：不影响自身高度，不会产生循环依赖 size 两个轴 容器高度必须与内容无关（否则「内容决定高度、高度又决定内容」）——通常要显式给 height normal 不查询 默认，取消容器身份 另外两条必须知道：container-type 非 normal 时，元素会建立独立格式化上下文（内部 margin 不再与外部塌陷，见第九章），并成为绝对定位后代的包含块（第十二章）。",{"id":14884,"title":14366,"titles":14885,"content":14886,"level":82},"\u002Ftutorials\u002Fcss#容器单位cqi-cqb-cqmin-cqmax",[5,14360],".title { font-size: 8cqi; }   \u002F* 字号相对容器宽度的 1% *\u002F\n.card  { padding: 2cqi; } 单位 相对什么 cqi 容器内联轴（水平书写模式下 = 宽度）的 1% cqb 容器块轴（= 高度）的 1%，需要 container-type: size 或 block cqw \u002F cqh 宽度 \u002F 高度的 1% cqmin \u002F cqmax 两者中较小 \u002F 较大者的 1% 与 vw 的关系一句话：vw 相对视口，cqi 相对最近的尺寸容器——组件内部一律用后者（第十三章的 clamp() 适合页面级排版，cqi 适合组件内）。",{"id":14888,"title":12851,"titles":14889,"content":14890,"level":82},"\u002Ftutorials\u002Fcss#与媒体查询的分工",[5,14360],"问题 用什么 整页骨架变化（三栏 → 一栏、导航 → 汉堡） @media：这是页面级事实，只有视口能回答 组件在不同槽位里的形态 @container 卡片墙要几列 auto-fit + minmax()（第十一章），能不用查询就不用 字号随所在容器缩放 cqi 系统偏好（深浅色、减少动效、指针类型） @media 特性查询（第十三章） 三者可以叠加：外层媒体查询定骨架，内层容器查询定组件形态。",{"id":14892,"title":14369,"titles":14893,"content":14894,"level":82},"\u002Ftutorials\u002Fcss#与-has-组合能替掉一大类-js",[5,14360],"@container (min-width: 420px) {\n  .list { grid-auto-flow: column; grid-auto-columns: 1fr; }\n  .list:has(> :nth-child(4)) { grid-auto-flow: row; grid-template-columns: repeat(2, 1fr); }\n} 「容器够宽就横排，但项数 ≥4 时改成两列」——这条需求两年前必须写 JS，现在是两条 CSS 规则。",{"id":14896,"title":14371,"titles":14897,"content":14898,"level":82},"\u002Ftutorials\u002Fcss#supports测试的是声明不是特性名",[5,14360],"@supports (display: grid) { … }\n@supports (position: sticky) { … }\n@supports (display: grid) and (not (display: subgrid)) { … }\n@supports selector(:has(*)) { … }      \u002F* 选择器支持测试：参数是选择器而不是声明 *\u002F 浏览器会去解析括号里的声明块，能接受就命中——所以判断准确率高，不需要维护特性名表。三个边界要知道： 它只判断「语法是否被接受」，不判断实现是否有 bug 或只是部分支持； 判断不了前缀差异（老 Safari 的 -webkit- 写法要并列写两份测试）； 不支持时整块规则被丢弃，因此默认（基线）样式必须自身成立。 三种写法模式： \u002F* A. 基线 + 增强（推荐） *\u002F\n.bar { display: flex; gap: 8px; }\n@supports (container-type: inline-size) { .zone { container-type: inline-size; } }\n\n\u002F* B. 新方案 + 显式降级 *\u002F\n.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }\n@supports not (display: grid) { .grid > * { display: inline-block; width: 48%; } }",{"id":14900,"title":13290,"titles":14901,"content":14902,"level":82},"\u002Ftutorials\u002Fcss#devtools-四面板各自回答什么问题",[5,14360],"面板 回答 最有用的三个动作 Styles 「哪条规则胜出、为什么」 逐条取消勾选看变化；看被划掉的声明与旁边的警告图标；展开 :hover、层名（第十六章）与优先级数字 Computed 「最终计算值是多少」 看盒子图（margin\u002Fborder\u002Fpadding\u002Fcontent 各层实测像素，第六章）；Ctrl+F 搜属性；展开 :root 看变量解析结果 Layout 「几何问题出在哪」 开启 sticky \u002F scroll-overflow \u002F Grid overlay，直接看轨道尺寸与被吸住的元素 Rendering 「性能与状态」 Paint flashing（绿闪=重绘）、Layers（合成层）、模拟 prefers-reduced-motion 与 prefers-color-scheme 三个不装插件就能做的动作：Elements 面板右键元素 → State… 强制 :hover\u002F:focus\u002F:checked；Styles 面板右上 ⋮ → Show all user-agent styles 看默认样式表；Network 面板禁用缓存 + 用无痕窗口排除扩展干扰。",{"id":14904,"title":13394,"titles":14905,"content":14906,"level":82},"\u002Ftutorials\u002Fcss#六个高频坑的复现与修法",[5,14360],"现象 根因 修法 height: 100% 不生效 父级没有确定高度 给父显式高度；或父用 Grid\u002FFlex 靠 stretch；或整条链改用 min-height；或用 aspect-ratio\u002Fsvh 表达「占满」 内容撑破容器 Flex 子项 min-width 是 min-content（第十章） min-width: 0 + overflow-wrap: anywhere 意外的横向滚动条 负 margin、width: 100vw（含滚动条宽度）、未换行长串、跑到外面的绝对定位 Console 里过滤 el.scrollWidth > el.clientWidth 定位元凶；scrollbar-gutter: stable 防弹层抖动 margin 跑到父元素上 塌陷穿透（第六章） 父加 display: flow-root，或改用 gap 加了样式没变化 选择器没命中，或被更高权重\u002F更晚层覆盖（第四、十六章） Styles 面板看有没有列出这条、被划掉的是哪条 只在真机上不对 视口单位（svh\u002Fdvh 与 vh）、安全区、hover\u002Fpointer 判定 第十三章 + 第五章的相关条目 一行排查用的临时样式（只写在 DevTools 里，不要提交）： * { outline: 1px dashed rgba(255,0,0,.3); }   \u002F* 谁比想象中宽\u002F高，一眼看出 *\u002F\nimg { background: #ff0; }                      \u002F* 看图片实际渲染尺寸 *\u002F\n[style] { border: 2px solid red; }             \u002F* 揪出内联样式 *\u002F",{"id":14908,"title":13629,"titles":14909,"content":14910,"level":82},"\u002Ftutorials\u002Fcss#浏览器基线与降级策略汇总",[5,14360],"本教程用到的较新能力，按「不支持会怎样」分类（版本号请以 caniuse 当前数据为准，这里给的是量级判断）： 能力 不支持时的表现 要不要包 @supports :has()、:is()\u002F:where()、@layer、原生嵌套、gap、aspect-ratio、clamp() 整条规则被忽略，布局退化为基线形态 一般不需要，写清基线样式即可；追求极端兼容时包 容器查询与 cqi 组件停在「窄容器」默认形态 建议包，避免中间态视觉 subgrid 卡片行不对齐，其他正常 建议包 @property 变量过渡退化成跳变 不需要 滚动驱动动画 进度条停在首\u002F末帧 必须包，且要保证静态形态可读 backdrop-filter 半透明面板糊在一起 建议包，并给一个不透明的回退底色",{"id":14912,"title":13743,"titles":14913,"content":13746,"level":49},"\u002Ftutorials\u002Fcss#二十一综合实战把一团-div-变成现代布局",[5],{"id":14915,"title":13750,"titles":14916,"content":14917,"level":82},"\u002Ftutorials\u002Fcss#改造前八类典型问题",[5,13743],"问题清单（每条都对应前面某一章）： 固定像素宽度 + 居中（width: 960px; margin: 0 auto）：窄屏出横向滚动条，宽屏两侧空白 → 第十三章 min(100% - 2rem, 68rem)。 float 两列：需要空 div.clearfix、需要 .last 抹掉末位边距、需要 overflow: hidden 修高度塌陷 → 第十一章 Grid 命名区域 + gap。 卡片列数靠复制类名（两列一套、单列一套）：改需求要两边同动 → 第十一章 auto-fit + minmax()。 颜色与字号硬编码且重复（#0066cc 出现 5 次、全部 px）：暗色主题没有可能 → 第十四章令牌 + 第十三章 rem\u002Fclamp()。 靠堆权重覆盖（.container .content .main .item .t）：任何定制只能 !important → 第四章降权重 + 第十五章 :is() + 第十四章组件变量。 padding-top: 70px 手算垂直居中：字号一改就歪 → 第十章 align-items: center \u002F 第十一章 place-items。 图片位靠 height 写死：真图进来要么变形要么留白 → 第十三章 aspect-ratio + object-fit。 只有 :hover 没有 :focus-visible：键盘用户看不见焦点，触屏点了不还原 → 第八\u002F十五章焦点样式 + 第十三章 hover: hover 判定。",{"id":14919,"title":13875,"titles":14920,"content":14921,"level":82},"\u002Ftutorials\u002Fcss#改造后同一份内容一半代码",[5,13743],"改造后的写法逐条对应： 令牌层：--bg-1、--text-1、--brand-500、--space-3、--radius-3、--z-header 一次声明；html[data-theme='dark'] 只替换令牌，所有组件规则零改动，并配 color-scheme 让浏览器控件一起换（第十四章）。 容器层：.wrap { width: min(100% - 2 * var(--space-3), 68rem); margin-inline: auto; }——无需断点的居中容器（第十三章）。 骨架层：页头 position: sticky + z-index: var(--z-header)；主体 Grid 单列，@media (min-width: 52rem) 变两列（minmax(0, 1fr) 防溢出，第十一\u002F十二章）。 组件层：卡片一份样式，repeat(auto-fit, minmax(min(220px, 100%), 1fr)) 自己算列数；内部 flex-direction: column + margin-top: auto 让页脚对齐（第十\u002F十一章）。 槽位自适应：侧栏列表声明 container-type: inline-size，@container (min-width: 22rem) 时才横排——同一个组件放进宽槽会自动变横排（第二十章）。 动效：hover 只动 transform 与伪元素 opacity，prefers-reduced-motion 下整组过渡被关闭（第十八章）。 可访问性：:focus-visible 描边、aria-current=\"page\" 标当前页、装饰色块加 aria-hidden、sr-only 补列表说明（第十五章 + HTML 教程第十七章）。 API 化的组件：.badge { --badge-bg: …; --badge-fg: …; }，使用方给祖先设变量就能定制，不需要修饰类（第十四章）。",{"id":14923,"title":14014,"titles":14924,"content":14925,"level":82},"\u002Ftutorials\u002Fcss#对照检查清单新项目起手就用它",[5,13743],"是否有一条 * { box-sizing: border-box; }（第六章） 颜色\u002F间距\u002F圆角\u002F层级是否只出现在令牌里（第十四章） 是否有硬编码 px 字号、是否给正文留了 rem 缩放余地（第七、十三章） 布局是否用 Grid 定骨架、Flex 定一维，float 只留在图文环绕（第九~十一章） 卡片墙是否用 auto-fit + minmax() 而不是复制列数类（第十一章） 组件是否用容器查询而不是猜视口宽度（第二十章） 每个可交互元素是否有 :focus-visible 样式，对比度是否达标（第八章） 动效是否有 prefers-reduced-motion 降级（第十三、十八章） 新特性是否包了 @supports，并确认不支持时的形态可接受（第二十章） 图片是否有 width\u002Fheight（防布局抖动）、aspect-ratio + object-fit 是否配合（第十三章 + HTML 教程第六章） 是否存在靠 !important 或超长选择器维持的覆盖（第四、十五章） 层叠顺序是否清晰：未分层样式有没有意外压过组件库（第十二、十六章）",{"id":14927,"title":14134,"titles":14928,"content":14929,"level":82},"\u002Ftutorials\u002Fcss#结语css-的心智模型只有三句话",[5,13743],"谁生效 = 层叠（权重、书写顺序、!important、层、上下文）——第四、十二、十六章； 生效成什么样 = 盒模型 + 布局算法（普通流、Flex、Grid、定位）——第六、九~十二章； 能不能被所有人用 = 排版与可访问性 + 渐进增强（rem、焦点、降级、@supports）——第七、十三、二十章。 剩下的一切——颜色、渐变、阴影、动画——都是这三条之上的表现层。把这三句话记住，遇到「为什么不是我想的样子」时，先问它属于哪一句，答案通常就在对应那一章里。 html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .s4JwU, html code.shiki .s4JwU{--shiki-default:#85E89D}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .s6RL2, html code.shiki .s6RL2{--shiki-default:#FDAEB7;--shiki-default-font-style:italic}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}",1793263562598]