[{"content":" 背景：给 PaperMod 博客做「左侧悬浮目录」时，从 fixed 迁移到 sticky，系统梳理了 position 的完整体系。\n一、一句话总纲 position 决定了一个元素\u0026quot;相对于谁、用什么规则来定位\u0026quot;。\nCSS 里有 5 个值（其中 4 个常用）。它们最大的区别，就在两个问题：\n参照物是谁 —— 相对自己？相对祖先？相对屏幕？ 会不会脱离文档流 —— 原来的位置还占不占？ 二、先理解前提：什么是「文档流」 网页元素默认从上到下、从左到右自然排列，像写字一样一行行排下来。 这个「自然的排列规则」就叫文档流（normal flow）。 默认情况（position: static），所有元素都待在文档流里，一个接一个。 position 的很多值，本质就是\u0026quot;让元素脱离这个自然流，然后相对某个参照物重新定位\u0026quot;。\n三、五个值逐个拆解 1. static（默认值） .element { position: static; } 所有元素的默认状态，不写 position 就是它。 元素乖乖待在文档流里，按顺序排列。 top / left / right / bottom 这些偏移属性对它无效。 一句话：就正常排着，别动我。\n2. relative（相对定位） .element { position: relative; top: 10px; left: 20px; } 相对它自己原来的位置偏移。 关键点 1：仍然占着原来的位置（不脱离文档流，坑还在）。 关键点 2：top: 10px = 从原位置往下挪 10px；left: 20px = 往右挪 20px。 一句话：我人挪了，但原来的座位还给我留着。\n隐藏但极重要的用途：relative 可以当「定位锚点」——一个 relative 元素，会成为它内部 absolute 元素的参照物。这是它最常见的使用方式。\n3. absolute（绝对定位） .element { position: absolute; top: 0; right: 0; } 完全脱离文档流，原来的位置被后面的元素顶上（不留坑）。 参照物：最近的、带 position 的祖先元素（通常是 relative 的父容器）。 如果没有任何带 position 的祖先，就相对整个页面（body）定位。 一句话：我飘起来了，谁也别占我的座；我贴着最近那个被标记的祖先来定位。\n4. fixed（固定定位） .element { position: fixed; top: 0; left: 0; } 完全脱离文档流。 参照物：浏览器窗口（屏幕），永远相对屏幕定位。 页面怎么滚动，它都固定在屏幕上不动。 一句话：我钉在屏幕上了，不管页面怎么滚，我都在这里。\n5. sticky（粘性定位） .element { position: sticky; top: 80px; } relative 和 fixed 的混合体。 平时表现像 relative（待在文档流里，占位置）。 当滚动到某个临界点（如 top: 80px）时，临时表现像 fixed，粘在屏幕上不动。 关键约束：只在父容器范围内粘住，滚出父容器就不粘了。 一句话：平时老实待着，滚到临界点就粘住，但只在爸妈（父容器）怀里粘。\n四、一张表牢牢记住 position 参照物（相对谁定位） 脱离文档流吗 一句话 static 无（就正常排） 否 默认状态，别动我 relative 自己原来的位置 否（占坑） 挪了人，坑还留着 absolute 最近的 position 祖先 是 飘起来，贴祖先 fixed 浏览器窗口（屏幕） 是 钉在屏幕上 sticky 父容器（滚动时） 否（占坑，临界时粘住） relative + fixed 混合 五、两个最重要的「关系」 关系 1：relative 是 absolute 的「锚点」 一个 absolute 元素，会去找「最近的、带 position 的祖先」当参照物。而人们通常给那个祖先设 position: relative（因为它相对自己不动，正好当个稳定锚点）。\n经典组合：\n父容器 { position: relative; } /* 当锚点 */ 子元素 { position: absolute; } /* 相对父容器定位 */ 关系 2：sticky = relative + fixed 的「混血儿」 平时像 relative：待在文档流里，占着位置。 滚到临界点时像 fixed：粘在屏幕上。 但只能在父容器范围内粘，滚出父容器就恢复成普通流。 这就是为什么 sticky 目录能「跟随滚动」，但不会像 fixed 那样跑出正文范围。\n六、回到我们的博客场景 为什么之前用 fixed 会出问题、现在要转向 sticky：\nfixed 目录 = 相对屏幕固定 → 和居中的正文「脱节」，窄屏时压字。 sticky 目录 = 相对正文容器粘住 → 跟着正文走，天然不脱节。 七、速记关键词 文档流：元素默认的上下排列规则。 参照物：position 最核心的区别，就是「相对谁定位」。 relative：相对自己，占坑，可当锚点。 absolute：相对最近 position 祖先，脱离流。 fixed：相对屏幕，脱离流，钉死不动。 sticky：relative + fixed 混合，父容器内粘住。 经典组合：父 relative + 子 absolute。 ","permalink":"https://ankopala.github.io/posts/css-position-guide/","summary":"\u003cblockquote\u003e\n\u003cp\u003e背景：给 PaperMod 博客做「左侧悬浮目录」时，从 \u003ccode\u003efixed\u003c/code\u003e 迁移到 \u003ccode\u003esticky\u003c/code\u003e，系统梳理了 \u003ccode\u003eposition\u003c/code\u003e 的完整体系。\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003chr\u003e\n\u003ch2 id=\"一一句话总纲\"\u003e一、一句话总纲\u003c/h2\u003e\n\u003cblockquote\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eposition\u003c/code\u003e 决定了一个元素\u0026quot;相对于谁、用什么规则来定位\u0026quot;。\u003c/strong\u003e\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eCSS 里有 5 个值（其中 4 个常用）。它们最大的区别，就在两个问题：\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003e参照物是谁\u003c/strong\u003e —— 相对自己？相对祖先？相对屏幕？\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e会不会脱离文档流\u003c/strong\u003e —— 原来的位置还占不占？\u003c/li\u003e\n\u003c/ol\u003e\n\u003chr\u003e\n\u003ch2 id=\"二先理解前提什么是文档流\"\u003e二、先理解前提：什么是「文档流」\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e网页元素默认\u003cstrong\u003e从上到下、从左到右\u003c/strong\u003e自然排列，像写字一样一行行排下来。\u003c/li\u003e\n\u003cli\u003e这个「自然的排列规则」就叫\u003cstrong\u003e文档流（normal flow）\u003c/strong\u003e。\u003c/li\u003e\n\u003cli\u003e默认情况（\u003ccode\u003eposition: static\u003c/code\u003e），所有元素都待在文档流里，一个接一个。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eposition 的很多值，本质就是\u0026quot;让元素脱离这个自然流，然后相对某个参照物重新定位\u0026quot;。\u003c/strong\u003e\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"三五个值逐个拆解\"\u003e三、五个值逐个拆解\u003c/h2\u003e\n\u003ch3 id=\"1-static默认值\"\u003e1. \u003ccode\u003estatic\u003c/code\u003e（默认值）\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-css\" data-lang=\"css\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e.\u003cspan style=\"color:#a6e22e\"\u003eelement\u003c/span\u003e { \u003cspan style=\"color:#66d9ef\"\u003eposition\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e; }\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003e所有元素的\u003cstrong\u003e默认状态\u003c/strong\u003e，不写 \u003ccode\u003eposition\u003c/code\u003e 就是它。\u003c/li\u003e\n\u003cli\u003e元素乖乖待在文档流里，按顺序排列。\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003etop\u003c/code\u003e / \u003ccode\u003eleft\u003c/code\u003e / \u003ccode\u003eright\u003c/code\u003e / \u003ccode\u003ebottom\u003c/code\u003e 这些偏移属性\u003cstrong\u003e对它无效\u003c/strong\u003e。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003e一句话\u003c/strong\u003e：就正常排着，别动我。\u003c/p\u003e\n\u003chr\u003e\n\u003ch3 id=\"2-relative相对定位\"\u003e2. \u003ccode\u003erelative\u003c/code\u003e（相对定位）\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-css\" data-lang=\"css\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e.\u003cspan style=\"color:#a6e22e\"\u003eelement\u003c/span\u003e { \u003cspan style=\"color:#66d9ef\"\u003eposition\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003erelative\u003c/span\u003e; \u003cspan style=\"color:#66d9ef\"\u003etop\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003epx\u003c/span\u003e; \u003cspan style=\"color:#66d9ef\"\u003eleft\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e20\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003epx\u003c/span\u003e; }\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003e相对它自己原来的位置\u003c/strong\u003e偏移。\u003c/li\u003e\n\u003cli\u003e关键点 1：\u003cstrong\u003e仍然占着原来的位置\u003c/strong\u003e（不脱离文档流，坑还在）。\u003c/li\u003e\n\u003cli\u003e关键点 2：\u003ccode\u003etop: 10px\u003c/code\u003e = 从原位置往下挪 10px；\u003ccode\u003eleft: 20px\u003c/code\u003e = 往右挪 20px。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003e一句话\u003c/strong\u003e：我人挪了，但原来的座位还给我留着。\u003c/p\u003e","title":"CSS `position` 定位属性详解"},{"content":" 背景：做博客「左侧目录」的窄屏适配时，用到了 @media 让目录在窄屏下隐藏/缩小。这里系统记录媒体查询是什么、怎么用。\n一、媒体查询是什么 一句话：媒体查询（Media Query）是 CSS 里的一种\u0026quot;条件判断\u0026quot;，让某些样式只在\u0026quot;满足特定条件\u0026quot;时生效。\n最常用的条件是\u0026quot;屏幕宽度\u0026quot;，但也可以是设备类型、屏幕方向（横屏/竖屏）、是否支持某功能等。\n它和编程里的 if 语句是同一个思想：\n/* 如果屏幕宽度 ≤ 1200px，就应用里面这些样式 */ @media (max-width: 1200px) { .toc-sidebar { display: none; } } 这等价于（用伪代码表达）：\n如果 (屏幕宽度 \u0026lt;= 1200px) { 隐藏 .toc-sidebar } 二、@media 的基本语法 结构是固定的，记住这个骨架：\n@media 条件 { 选择器 { 属性: 值; } } @media 是关键字 括号里写\u0026quot;条件\u0026quot; 花括号里写\u0026quot;满足条件时要应用的样式\u0026quot; 里面的写法和普通 CSS 完全一样 三、最常用的宽度条件 1. max-width（小于等于某个宽度时生效） @media (max-width: 768px) { /* 屏幕 ≤ 768px（手机）时生效 */ } 记忆：max-width = \u0026ldquo;最多就这么宽\u0026rdquo;，所以是**\u0026ldquo;小屏时生效\u0026rdquo;**。\n2. min-width（大于等于某个宽度时生效） @media (min-width: 1200px) { /* 屏幕 ≥ 1200px（大屏）时生效 */ } 记忆：min-width = \u0026ldquo;至少这么宽\u0026rdquo;，所以是**\u0026ldquo;大屏时生效\u0026rdquo;**。\n3. 组合区间（一个范围） @media (min-width: 768px) and (max-width: 1200px) { /* 屏幕在 768px ~ 1200px 之间时生效 */ } 用 and 把两个条件连起来，表达\u0026quot;在某个范围内\u0026quot;。\n四、其他常用条件（了解即可） 条件 作用 例子 orientation: portrait 竖屏 @media (orientation: portrait) orientation: landscape 横屏 @media (orientation: landscape) prefers-color-scheme: dark 用户偏好深色模式 @media (prefers-color-scheme: dark) hover: none 设备不支持悬停（触屏） @media (hover: none) 其中最实用的是 prefers-color-scheme（深色模式适配），以后做\u0026quot;跟随系统深色\u0026quot;会用到。\n五、移动端优先 vs 桌面端优先 媒体查询有两种书写思路，理解这个能少走弯路：\n桌面端优先（Desktop-first） 先写\u0026quot;大屏\u0026quot;样式（默认），再用 max-width 往下\u0026quot;缩\u0026quot;：\n/* 默认：大屏样式 */ .toc-sidebar { width: 260px; } /* 屏幕变窄时，一步步调整 */ @media (max-width: 1300px) { .toc-sidebar { width: 200px; } } @media (max-width: 1100px) { .toc-sidebar { display: none; } } 特点：从大到小，用 max-width。适合\u0026quot;先做桌面版，再适配手机\u0026quot;的场景——你现在的博客就是这种。\n移动端优先（Mobile-first） 先写\u0026quot;小屏\u0026quot;样式（默认），再用 min-width 往上\u0026quot;加\u0026quot;：\n/* 默认：小屏（手机）样式 */ .toc-sidebar { display: none; } /* 屏幕变宽时，逐步增强 */ @media (min-width: 1100px) { .toc-sidebar { display: block; } } 特点：从小到大，用 min-width。是当前主流推荐的做法。\n六、媒体查询的两个\u0026quot;坑\u0026quot; 坑 1：断点（breakpoint）是\u0026quot;猜\u0026quot;出来的 媒体查询里的宽度值（1200px、768px 等）叫断点。问题是——屏幕尺寸无穷多，断点写不完。\n比如你设了 1200px 隐藏目录，但用户的屏幕是 1199px 还是 1210px，效果差别可能很大，你没法为每个像素都写一条。\n这是媒体查询的固有局限，也是为什么\u0026quot;复杂的响应式布局\u0026quot;最终要配合其他技术（比如 position: sticky、flex、grid）一起用，而不是全靠媒体查询硬撑。\n坑 2：断点要和\u0026quot;内容\u0026quot;匹配，不是抄别人的 网上常有人说\u0026quot;768px 是平板、1024px 是桌面\u0026quot;——这些是参考值，不是金科玉律。\n正确的做法是：根据你自己的内容\u0026quot;什么时候会挤\u0026quot;来定断点。比如你正文 900px + 目录 260px，那大概 1200px 以下就会挤，所以断点设 1200px。换个内容，断点就该换。\n七、媒体查询 vs position: sticky 回顾一下两者的定位（呼应 why-position-sticky.md）：\n媒体查询 position: sticky 思路 \u0026ldquo;补丁式\u0026rdquo;：到了某宽度就改样式 \u0026ldquo;结构性\u0026rdquo;：从根上让布局自适应 解决的问题 临时补救重叠 从根本上避免重叠 局限 断点写不完，要猜 需配合 HTML 结构 结论：媒体查询是好用的工具，但不是万能的。它擅长\u0026quot;简单的开关式调整\u0026quot;（比如窄屏隐藏目录、切换字号），但面对\u0026quot;复杂布局的重叠\u0026quot;问题，更该用 sticky/flex/grid 这类结构性方案。\n八、速记关键词 媒体查询（media query）：CSS 的条件判断，满足条件才生效。 max-width：小于等于某宽度时生效（小屏适配）。 min-width：大于等于某宽度时生效（大屏增强）。 断点（breakpoint）：媒体查询里的宽度分界值。 桌面端优先：默认大屏，用 max-width 往下缩。 移动端优先：默认小屏，用 min-width 往上加。 媒体查询的局限：断点是\u0026quot;猜\u0026quot;的，复杂布局要配合结构性方案。 ","permalink":"https://ankopala.github.io/posts/media-query-intro/","summary":"\u003cblockquote\u003e\n\u003cp\u003e背景：做博客「左侧目录」的窄屏适配时，用到了 \u003ccode\u003e@media\u003c/code\u003e 让目录在窄屏下隐藏/缩小。这里系统记录媒体查询是什么、怎么用。\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003chr\u003e\n\u003ch2 id=\"一媒体查询是什么\"\u003e一、媒体查询是什么\u003c/h2\u003e\n\u003cp\u003e一句话：\u003cstrong\u003e媒体查询（Media Query）是 CSS 里的一种\u0026quot;条件判断\u0026quot;，让某些样式只在\u0026quot;满足特定条件\u0026quot;时生效。\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e最常用的条件是\u0026quot;屏幕宽度\u0026quot;，但也可以是设备类型、屏幕方向（横屏/竖屏）、是否支持某功能等。\u003c/p\u003e\n\u003cp\u003e它和编程里的 \u003ccode\u003eif\u003c/code\u003e 语句是同一个思想：\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-css\" data-lang=\"css\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e/* 如果屏幕宽度 ≤ 1200px，就应用里面这些样式 */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e@\u003cspan style=\"color:#66d9ef\"\u003emedia\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003emax-width\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e1200px\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    .\u003cspan style=\"color:#a6e22e\"\u003etoc-sidebar\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003edisplay\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003enone\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e这等价于（用伪代码表达）：\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e如果 (屏幕宽度 \u0026lt;= 1200px) {\n    隐藏 .toc-sidebar\n}\n\u003c/code\u003e\u003c/pre\u003e\u003chr\u003e\n\u003ch2 id=\"二media-的基本语法\"\u003e二、@media 的基本语法\u003c/h2\u003e\n\u003cp\u003e结构是固定的，记住这个骨架：\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-css\" data-lang=\"css\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e@\u003cspan style=\"color:#66d9ef\"\u003emedia\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e条件\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e选择器\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e属性:\u003c/span\u003e \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e值\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003e\u003ccode\u003e@media\u003c/code\u003e 是关键字\u003c/li\u003e\n\u003cli\u003e括号里写\u0026quot;条件\u0026quot;\u003c/li\u003e\n\u003cli\u003e花括号里写\u0026quot;满足条件时要应用的样式\u0026quot;\u003c/li\u003e\n\u003cli\u003e里面的写法和普通 CSS 完全一样\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"三最常用的宽度条件\"\u003e三、最常用的宽度条件\u003c/h2\u003e\n\u003ch3 id=\"1-max-width小于等于某个宽度时生效\"\u003e1. \u003ccode\u003emax-width\u003c/code\u003e（小于等于某个宽度时生效）\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-css\" data-lang=\"css\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e@\u003cspan style=\"color:#66d9ef\"\u003emedia\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003emax-width\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e768px\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e/* 屏幕 ≤ 768px（手机）时生效 */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003e记忆\u003c/strong\u003e：\u003ccode\u003emax-width\u003c/code\u003e = \u0026ldquo;最多就这么宽\u0026rdquo;，所以是**\u0026ldquo;小屏时生效\u0026rdquo;**。\u003c/p\u003e\n\u003ch3 id=\"2-min-width大于等于某个宽度时生效\"\u003e2. \u003ccode\u003emin-width\u003c/code\u003e（大于等于某个宽度时生效）\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-css\" data-lang=\"css\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e@\u003cspan style=\"color:#66d9ef\"\u003emedia\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003emin-width\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e1200px\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e/* 屏幕 ≥ 1200px（大屏）时生效 */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003e记忆\u003c/strong\u003e：\u003ccode\u003emin-width\u003c/code\u003e = \u0026ldquo;至少这么宽\u0026rdquo;，所以是**\u0026ldquo;大屏时生效\u0026rdquo;**。\u003c/p\u003e","title":"媒体查询（Media Query）与 @media 用法"},{"content":" 背景：给 PaperMod 博客做「左侧悬浮目录」，在做窄屏适配时，发现 position: fixed 方案越补越复杂，进而推导出 position: sticky 才是正解。\n一、问题的本质：两个\u0026quot;参照系\u0026quot;打架 当前目录用的是 position: fixed，正文是居中布局。这导致了根本矛盾：\n元素 定位方式 参照系 目录 .toc-sidebar position: fixed 整个浏览器窗口（屏幕） 正文 .post-content 居中 + max-width 屏幕正中央的固定宽度容器 两个元素各自用不同的参照系定位，所以：\n屏幕很宽时，两者刚好不重叠（纯属运气） 屏幕变窄时，正文的\u0026quot;左右留白\u0026quot;缩小，目录（相对屏幕固定）就会压到正文 结论：用 fixed 就注定要\u0026quot;打补丁\u0026quot;——写一堆媒体查询去\u0026quot;猜\u0026quot;什么宽度下会重叠。这是治标不治本。\n二、为什么\u0026quot;缩小距离/缩小宽度/隐藏\u0026quot;是补丁，不是解法 一开始设想的\u0026quot;三步判断\u0026quot;逻辑：\n屏幕够宽 → 目录浮在正文旁 二者贴在一起 → 缩小目录宽度 还不行 → 隐藏目录 这个逻辑方向是对的，但用媒体查询实现时，本质是在**\u0026ldquo;手动模拟\u0026quot;本应由浏览器自动完成的事**：\n你得猜\u0026ldquo;多少像素下会重叠\u0026rdquo;（是 1200？1300？1400？） 每猜一次，就要加一个 @media 断点 屏幕尺寸无穷多，断点也写不完 换个设备、换个分辨率，又得重调 这就是\u0026quot;补丁式\u0026quot;响应式的通病：永远在追赶，永远有漏网之鱼。\n三、position: sticky 为什么是正解 sticky 解决的是**\u0026ldquo;参照系统一\u0026rdquo;**这个根本问题。\nfixed 和 sticky 的本质区别 属性 定位参照系 表现 position: fixed 相对屏幕 永远钉在屏幕某个位置，与页面内容无关 position: sticky 相对父容器 在父容器范围内\u0026quot;跟随滚动\u0026rdquo;，超出范围就正常流动 sticky 如何从根上避免\u0026quot;重合\u0026quot; 如果目录用 sticky，并且放在正文容器的左侧（作为正文布局的一部分），那么：\n目录的位置是相对于正文容器计算的，不再是\u0026quot;相对屏幕\u0026quot; 正文容器居中、目录贴着它左侧 → 目录天然永远贴着正文，永远不会重叠 屏幕变窄时，整个\u0026quot;正文+目录\u0026quot;一起居中缩小，目录自动跟着正文走 这就是\u0026quot;从结构上避免重叠\u0026quot;，而不是\u0026quot;靠一堆断点去补救重叠\u0026quot;。\n四、一个直观的类比 position: fixed：像在墙上钉了个钉子，挂了个相框。墙（屏幕）多大，钉子就钉在离墙边固定的位置，跟家具（正文）没关系。家具挪了，相框还在原地，可能挡住家具。\nposition: sticky：像把相框贴在某个柜子侧面。柜子（正文容器）挪到哪，相框跟着到哪，永远不会和柜子里的东西打架。\n五、sticky 的代价（诚实说明） sticky 不是零成本，它有个前提：\n需要调整 HTML 结构：目录必须是\u0026quot;正文容器\u0026quot;的子元素（或与正文在同一个相对定位的容器里），才能以正文为参照。当前的 single.html 结构是\u0026quot;目录和正文平级\u0026quot;，需要先改造。 需要理解 flex + sticky 的配合：通常用\u0026quot;左栏 sticky + 右栏正文\u0026quot;的两栏结构实现。 所以它的学习成本略高，但换来的是\u0026quot;一次做对、以后不用打补丁\u0026quot;。\n六、结论 方案 优点 缺点 适用 fixed + 媒体查询补丁 改动小、好理解 治标不治本，断点写不完 临时过渡、快速见效 sticky 锚定正文 从根上避免重叠，一劳永逸 要调 HTML 结构，稍复杂 最终方案、长期维护 最终结论：position: fixed 适合\u0026quot;先快速上线看效果\u0026quot;，position: sticky 才是\u0026quot;窄屏适配 + 跟随滚动\u0026quot;的正解。目标是从 fixed 迁移到 sticky。\n七、速记关键词 参照系（positioning context）：fixed 相对屏幕，sticky 相对父容器。 补丁式响应式：靠一堆 @media 断点\u0026quot;猜\u0026quot;重叠点，永远追不完。 结构性解法：让目录成为正文布局的一部分，从根上避免重叠。 sticky 的前提：目录要放在正文容器的左侧，作为子元素或同一相对定位容器内。 ","permalink":"https://ankopala.github.io/posts/why-position-sticky/","summary":"\u003cblockquote\u003e\n\u003cp\u003e背景：给 PaperMod 博客做「左侧悬浮目录」，在做窄屏适配时，发现 \u003ccode\u003eposition: fixed\u003c/code\u003e 方案越补越复杂，进而推导出 \u003ccode\u003eposition: sticky\u003c/code\u003e 才是正解。\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003chr\u003e\n\u003ch2 id=\"一问题的本质两个参照系打架\"\u003e一、问题的本质：两个\u0026quot;参照系\u0026quot;打架\u003c/h2\u003e\n\u003cp\u003e当前目录用的是 \u003ccode\u003eposition: fixed\u003c/code\u003e，正文是居中布局。这导致了根本矛盾：\u003c/p\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth\u003e元素\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003e定位方式\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003e参照系\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e目录 \u003ccode\u003e.toc-sidebar\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ccode\u003eposition: fixed\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e整个浏览器窗口（屏幕）\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e正文 \u003ccode\u003e.post-content\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e居中 + \u003ccode\u003emax-width\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e屏幕正中央的固定宽度容器\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003e\u003cstrong\u003e两个元素各自用不同的参照系定位\u003c/strong\u003e，所以：\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e屏幕很宽时，两者刚好不重叠（纯属运气）\u003c/li\u003e\n\u003cli\u003e屏幕变窄时，正文的\u0026quot;左右留白\u0026quot;缩小，目录（相对屏幕固定）就会压到正文\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003e结论\u003c/strong\u003e：用 \u003ccode\u003efixed\u003c/code\u003e 就注定要\u0026quot;打补丁\u0026quot;——写一堆媒体查询去\u0026quot;猜\u0026quot;什么宽度下会重叠。这是治标不治本。\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"二为什么缩小距离缩小宽度隐藏是补丁不是解法\"\u003e二、为什么\u0026quot;缩小距离/缩小宽度/隐藏\u0026quot;是补丁，不是解法\u003c/h2\u003e\n\u003cp\u003e一开始设想的\u0026quot;三步判断\u0026quot;逻辑：\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e屏幕够宽 → 目录浮在正文旁\u003c/li\u003e\n\u003cli\u003e二者贴在一起 → 缩小目录宽度\u003c/li\u003e\n\u003cli\u003e还不行 → 隐藏目录\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e这个逻辑\u003cstrong\u003e方向是对的\u003c/strong\u003e，但用媒体查询实现时，本质是在**\u0026ldquo;手动模拟\u0026quot;本应由浏览器自动完成的事**：\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e你得\u003cstrong\u003e猜\u003c/strong\u003e\u0026ldquo;多少像素下会重叠\u0026rdquo;（是 1200？1300？1400？）\u003c/li\u003e\n\u003cli\u003e每猜一次，就要加一个 \u003ccode\u003e@media\u003c/code\u003e 断点\u003c/li\u003e\n\u003cli\u003e屏幕尺寸无穷多，断点也写不完\u003c/li\u003e\n\u003cli\u003e换个设备、换个分辨率，又得重调\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003e这就是\u0026quot;补丁式\u0026quot;响应式的通病：永远在追赶，永远有漏网之鱼。\u003c/strong\u003e\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"三position-sticky-为什么是正解\"\u003e三、position: sticky 为什么是正解\u003c/h2\u003e\n\u003cp\u003e\u003ccode\u003esticky\u003c/code\u003e 解决的是**\u0026ldquo;参照系统一\u0026rdquo;**这个根本问题。\u003c/p\u003e\n\u003ch3 id=\"fixed-和-sticky-的本质区别\"\u003efixed 和 sticky 的本质区别\u003c/h3\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth\u003e属性\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003e定位参照系\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003e表现\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ccode\u003eposition: fixed\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e相对\u003cstrong\u003e屏幕\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e永远钉在屏幕某个位置，与页面内容无关\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ccode\u003eposition: sticky\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e相对\u003cstrong\u003e父容器\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e在父容器范围内\u0026quot;跟随滚动\u0026rdquo;，超出范围就正常流动\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch3 id=\"sticky-如何从根上避免重合\"\u003esticky 如何从根上避免\u0026quot;重合\u0026quot;\u003c/h3\u003e\n\u003cp\u003e如果目录用 \u003ccode\u003esticky\u003c/code\u003e，并且\u003cstrong\u003e放在正文容器的左侧\u003c/strong\u003e（作为正文布局的一部分），那么：\u003c/p\u003e","title":"窄屏适配与 `position: stikiy` "},{"content":" 背景：学习 Hugo 搭建博客时，在文章 front matter 和站点配置 hugo.toml 中遇到了 YAML 和 TOML 两种格式。\n一、它们到底是什么 YAML 和 TOML 都是**「数据序列化格式」（serialization format）**——用来把「数据」用有规则、人和机器都能读懂的文本写下来，方便程序读取、也方便人修改。\n它们和 Markdown 是同类东西：Markdown 是给「文章」定格式，YAML/TOML 是给「配置数据」定格式。\n常见数据格式一览 格式 一眼认出 典型用途 JSON {\u0026quot;key\u0026quot;: \u0026quot;value\u0026quot;} API 接口、前后端传数据 YAML key: value + 缩进 配置文件（Docker、K8s、GitHub Actions、Hugo 文章） TOML key = \u0026quot;value\u0026quot; 配置文件（Rust/Python 项目、Hugo 站点配置） XML \u0026lt;tag\u0026gt;value\u0026lt;/tag\u0026gt; 老牌格式，现在少用 INI key=value Windows 老式配置 二、YAML 详解 核心语法（三件事） 1. 键值对用冒号\nname: anko age: 25 2. 层级用缩进（空格，不能用 Tab）\nperson: name: anko address: city: 上海 street: 某路 3. 列表用短横线 -\ntags: - Hugo - Blog - 编程 特点与坑 优点：最像「给人看」的格式，符号噪音少，可读性极强。 致命坑：对缩进极其敏感。多一个/少一个空格都可能导致解析错误，且报错往往不明显。新手最易翻车点。 常见使用场景 Docker Compose（docker-compose.yml） Kubernetes 部署文件 GitHub Actions 工作流（.github/workflows/*.yml） Hugo 文章 front matter、CI 配置 三、TOML 详解 核心语法 1. 键值对用等号\ntitle = \u0026#34;My Blog\u0026#34; baseURL = \u0026#34;https://example.org\u0026#34; 2. 用 [表头] 表示分组/层级\n[params] subtitle = \u0026#34;学习笔记\u0026#34; author = \u0026#34;anko\u0026#34; 3. 列表用方括号\ntags = [\u0026#34;Hugo\u0026#34;, \u0026#34;Blog\u0026#34;] 特点与坑 优点：规则明确、不依赖缩进（靠 = 和 [] 表达结构），对齐乱了也不影响，不易因空格出错。 优点：类型要求严格清晰（字符串加引号、数字不加），适合精确配置。 缺点：略啰嗦，符号比 YAML 多。 常见使用场景 Rust 的 Cargo.toml、Python 的 pyproject.toml Hugo 站点配置（hugo.toml） 四、YAML vs TOML 对比速查 对比项 YAML TOML 赋值方式 冒号 key: value 等号 key = \u0026quot;value\u0026quot; 表达层级 靠缩进 靠 [表头] 列表写法 - item [\u0026quot;item\u0026quot;] 可读性 最强，像自然语言 较严谨，像编程 最大风险 缩进错乱导致解析失败 类型不匹配报错 一句话印象 给「人」读的清单 给「机器」填的表 五、怎么选 看你要配的工具/框架默认用什么 —— 跟着它的惯例走。 没有惯例时：追求可读性选 YAML，追求严谨少出错选 TOML。 你的博客：文章 front matter 用 YAML，站点配置用 TOML（社区惯例）。 记住：它们只是「写配置的文字格式」，学会一种，另一种一看就懂。\n六、另外三种格式：JSON、XML、INI JSON —— 现在最主流的数据交换格式 { \u0026#34;title\u0026#34;: \u0026#34;My Blog\u0026#34;, \u0026#34;author\u0026#34;: \u0026#34;anko\u0026#34;, \u0026#34;tags\u0026#34;: [\u0026#34;Hugo\u0026#34;, \u0026#34;Blog\u0026#34;], \u0026#34;isPublic\u0026#34;: true, \u0026#34;views\u0026#34;: 1024 } 用花括号 {} 表示对象，方括号 [] 表示数组 键名必须用双引号，值也是（数字、布尔值除外） 非常严格：不允许注释、不允许尾随逗号 常见场景：API 接口传数据（前后端通信几乎都是 JSON）、package.json、tsconfig.json、VS Code 设置、日志。\n一句话印象：机器和程序之间交换数据的\u0026quot;世界通用语言\u0026quot;，严谨、无废话，但人读起来累。\nINI —— 最古老的\u0026quot;朴实无华\u0026quot;格式 [blog] title = My Blog author = anko [server] port = 1313 debug = true 用 [区块名] 分组，下面跟 键 = 值 极简：只有\u0026quot;区块\u0026quot;和\u0026quot;键值\u0026quot;两层，无嵌套 值都是字符串，没有类型概念 常见场景：Windows 的 .ini 配置文件、Linux 程序简单配置、游戏存档。\n一句话印象：爷爷辈的格式，胜在\u0026quot;傻白甜\u0026quot;——一眼就会，但表达不了复杂结构。TOML 可理解为 INI 的\u0026quot;现代化增强版\u0026quot;（TOML 就是受 INI 启发设计的）。\nXML —— 曾经的王者，现在退居幕后 \u0026lt;blog\u0026gt; \u0026lt;title\u0026gt;My Blog\u0026lt;/title\u0026gt; \u0026lt;author\u0026gt;anko\u0026lt;/author\u0026gt; \u0026lt;tags\u0026gt; \u0026lt;tag\u0026gt;Hugo\u0026lt;/tag\u0026gt; \u0026lt;tag\u0026gt;Blog\u0026lt;/tag\u0026gt; \u0026lt;/tags\u0026gt; \u0026lt;/blog\u0026gt; 用成对的标签 \u0026lt;xxx\u0026gt;...\u0026lt;/xxx\u0026gt; 包裹内容，很像 HTML 极其啰嗦：一个简单值也要写\u0026quot;开标签 + 内容 + 闭标签\u0026quot; 功能强大：支持属性、注释、命名空间、校验规则（DTD/XSD） 常见场景：老系统/企业级系统（银行、政务、传统行业接口）、Android 布局文件、需要严格校验的场合。\n一句话印象：曾经是\u0026quot;标准答案\u0026quot;，因太啰嗦很多场景被 JSON 取代，但需要严谨、带属性、可校验的场景仍不可替代。\n七、五种格式全家福 格式 语法特征 最大特点 典型用途 记忆口诀 JSON {\u0026quot;key\u0026quot;: \u0026quot;value\u0026quot;} 最主流、严格、无注释 API 传数据、package.json 机器语 YAML key: value 冒号+缩进 可读性最强、怕缩进错 Docker、GitHub Actions 给人看的清单 TOML key = \u0026quot;value\u0026quot; 等号+表头 严谨、不靠缩进 Cargo.toml、hugo.toml 给机器填的表 XML \u0026lt;tag\u0026gt;值\u0026lt;/tag\u0026gt; 成对标签 啰嗦但可校验、带属性 企业接口、Android 布局 严谨的老贵族 INI [区块] + key=value 最古老、最简单、无类型 Windows 老式配置 傻白甜老祖宗 历史演进视角 五种格式的出现顺序，讲了一个故事：\nINI（最老）—— 需求简单，够用就行 XML —— 需求变复杂，要层级、要校验，于是发明了啰嗦但强大的标签语言 JSON —— XML 太啰嗦，Web 时代需要轻量格式，JSON 上位 YAML —— JSON 对\u0026quot;人\u0026quot;不友好，于是有了更易读的 YAML TOML —— YAML 缩进易出错，于是有了更严谨的 TOML 核心规律：没有谁\u0026quot;绝对更好\u0026quot;，每个格式都为解决\u0026quot;上一个格式的痛点\u0026quot;而生，然后在特定场景沉淀下来。\n新手实用建议 现在最需要熟：JSON 和 YAML（搭博客、碰现代工具绕不开） TOML：已会（hugo.toml） XML：遇到能认出来即可，新项目很少主动用 INI：知道是\u0026quot;最简单的老古董\u0026quot;即可，几乎不用主动学 ","permalink":"https://ankopala.github.io/posts/yaml-vs-toml/","summary":"\u003cblockquote\u003e\n\u003cp\u003e背景：学习 Hugo 搭建博客时，在文章 front matter 和站点配置 \u003ccode\u003ehugo.toml\u003c/code\u003e 中遇到了 YAML 和 TOML 两种格式。\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003chr\u003e\n\u003ch2 id=\"一它们到底是什么\"\u003e一、它们到底是什么\u003c/h2\u003e\n\u003cp\u003eYAML 和 TOML 都是**「数据序列化格式」（serialization format）**——用来把「数据」用有规则、人和机器都能读懂的文本写下来，方便程序读取、也方便人修改。\u003c/p\u003e\n\u003cp\u003e它们和 Markdown 是同类东西：Markdown 是给「文章」定格式，YAML/TOML 是给「配置数据」定格式。\u003c/p\u003e\n\u003ch3 id=\"常见数据格式一览\"\u003e常见数据格式一览\u003c/h3\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth\u003e格式\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003e一眼认出\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003e典型用途\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eJSON\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ccode\u003e{\u0026quot;key\u0026quot;: \u0026quot;value\u0026quot;}\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eAPI 接口、前后端传数据\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eYAML\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ccode\u003ekey: value\u003c/code\u003e + 缩进\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e配置文件（Docker、K8s、GitHub Actions、Hugo 文章）\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eTOML\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ccode\u003ekey = \u0026quot;value\u0026quot;\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e配置文件（Rust/Python 项目、Hugo 站点配置）\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eXML\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ccode\u003e\u0026lt;tag\u0026gt;value\u0026lt;/tag\u0026gt;\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e老牌格式，现在少用\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eINI\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ccode\u003ekey=value\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eWindows 老式配置\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003chr\u003e\n\u003ch2 id=\"二yaml-详解\"\u003e二、YAML 详解\u003c/h2\u003e\n\u003ch3 id=\"核心语法三件事\"\u003e核心语法（三件事）\u003c/h3\u003e\n\u003cp\u003e\u003cstrong\u003e1. 键值对用冒号\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eanko\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eage\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e25\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003e2. 层级用缩进（空格，不能用 Tab）\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eperson\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eanko\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003eaddress\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003ecity\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e上海\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003estreet\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e某路\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003e3. 列表用短横线 \u003ccode\u003e-\u003c/code\u003e\u003c/strong\u003e\u003c/p\u003e","title":"YAML 与 TOML 详解"},{"content":" 背景：学习 Hugo + GitHub Pages 搭建博客，在「安装 PaperMod 主题」这一步遇到了 git submodule 命令。\n⚠️ 注意：文中的 PaperMod 主题仓库地址务必以官方为准，使用前请先核对最新地址：\n官方仓库：https://github.com/adityatelange/hugo-PaperMod SSH 地址：git@github.com:adityatelange/hugo-PaperMod.git 曾误写过 adnanhob/PaperMod（该仓库不存在），已更正。仓库地址可能随时间迁移，动手前建议到 GitHub 搜索 hugo-PaperMod 确认。 一、命令逐词拆解 git submodule add --depth=1 git@github.com:adityatelange/hugo-PaperMod.git themes/PaperMod 片段 含义 git submodule add git 的核心命令：添加一个子模块 --depth=1 只拉取最近 1 次提交（浅克隆） git@github.com:adityatelange/hugo-PaperMod.git 主题的远程仓库地址（SSH 形式） themes/PaperMod 主题下载到本地的位置 二、核心概念：什么是「子模块」（submodule） 要解决的场景冲突 你的博客站点本身是个 git 仓库（my-blog），而 PaperMod 主题也是一个独立的 git 仓库。现在你想把主题代码放进博客的 themes/ 目录里。\n如果直接 git clone 主题进去，就会形成「仓库套仓库」的混乱局面——博客的 git 会看到 themes/PaperMod 里还有个 .git，管理起来一团糟。\n子模块的机制 子模块就是 git 专门用来解决「仓库里套仓库」的机制。做法很聪明：\n你的博客仓库不保存主题的实际代码，只保存一句话：「themes/PaperMod 这个位置，指向 adityatelange/hugo-PaperMod 仓库的某个特定版本」 主题的代码仍然留在它自己的仓库里，独立更新、独立管理 原理图 ┌─────────────────────────────┐ ┌─────────────────────────────┐ │ 你的博客仓库 my-blog │ │ PaperMod 主题仓库 │ │ │ │ │ │ content/ 文章 │ │ （独立存在，独立更新） │ │ hugo.toml 配置 │ │ │ │ themes/PaperMod │ 引用 │ 真正存代码的地方 │ │ ↳ 只存一个「引用指针」 │ ──────▶ │ │ │ .gitmodules 记录指向 │ │ │ └─────────────────────────────┘ └─────────────────────────────┘ 好处：主题升级 = 单独 pull，互不干扰 三、--depth=1 是什么：浅克隆（shallow clone） 正常情况下，git clone 会把仓库的全部历史记录（每一次提交）都下载下来。但 PaperMod 发展了几年、有上千次提交，全部下载既慢又占空间——而我们其实只需要当前最新的代码。\n--depth=1 的意思就是：只下载最新的一次提交，不要历史。\n速度快、体积小 适合「要用主题」而非「研究主题历史」的场景 --depth=1 是传给子模块内部那个 git clone 的参数（git 允许这样把参数「穿透」进去） 四、执行这个命令后会发生什么 git 会输出类似：\nCloning into \u0026#39;themes/PaperMod\u0026#39;... Submodule path \u0026#39;themes/PaperMod\u0026#39;: checked out \u0026#39;xxxxxxx\u0026#39; 博客目录里会多出两个东西：\nthemes/PaperMod/ —— 主题代码被下载到这里 .gitmodules —— 新文件，记录「themes/PaperMod 指向哪个仓库」，相当于子模块的「登记表」 以后任何人（包括未来的自己）拿到这个博客仓库，只要执行一条命令就能把主题代码重新拉下来（因为主题代码本身没存进仓库，只存了引用指针）：\ngit submodule update --init 五、submodule vs Hugo module（两种装主题方式） 参考博客 blog.xiaohuangyu.space 的作者用的是 Hugo module 方式，和我们学的 submodule 不同。\n先纠正一个误解 作者说\u0026quot;submodule 是把主题代码塞进你的仓库\u0026quot;。这句话技术上不完全准确：\nsubmodule 其实也没有把主题代码\u0026quot;塞\u0026quot;进仓库——它同样只存一个引用指针（.gitmodules 里那行记录），主题代码仍留在主题自己的仓库里。 两者的真正区别在于：\u0026ldquo;引用\u0026quot;发生在哪个环节、由谁来拉取主题代码。 核心区别对比 对比项 submodule（我们学的） Hugo module（他用的） 引用记录 .gitmodules go.mod / module.toml 主题代码 下载到 themes/ 目录 不进仓库 拉取方式 手动 git submodule update Hugo 构建时自动拉 前提 只需 git 需要额外装 Go 难度 简单直观，新手友好 稍复杂，偏进阶 优点 直观、依赖少、出错好排查 仓库更干净、升级省心 作者的判断放在他的语境里 作者说\u0026quot;submodule 改起来重\u0026rdquo;，对他成立，原因有两点：\n他用了多个主题、长期折腾，submodule 每次换/升级主题都要手动操作，是负担。 他本身有 Go 环境，装 Go 零成本，module 几乎无门槛。 这两个前提，新手目前都不具备。\nHugo module 的真实优劣 优势：\n仓库更干净：主题代码完全不进仓库，仓库里只有自己的文章和配置。 升级省心：hugo mod get -u 一条命令升级，不用碰 git submodule 命令。 代价：\n必须额外装 Go（新工具、新环境）。 构建时依赖网络拉取主题（离线/网络不好时，本地可能构建不了）。 出问题时排查链路更长（涉及 Go 模块缓存、版本解析）。 结论 现在用 submodule，先别切。 理由：\n已经 git init 了，submodule 是自然顺下来的下一步，零额外依赖。 正在学 git，submodule 能看得见主题代码在 themes/PaperMod/ 里，对理解\u0026quot;Hugo 怎么找到主题\u0026quot;帮助更大。 单一主题、稳定使用，\u0026ldquo;升级麻烦\u0026quot;这个缺点短期内根本遇不到。 等遇到以下场景再切 module 不迟：想同时用多个主题 / 频繁换主题、嫌弃仓库里多出的主题目录、已装 Go 想统一用 Hugo 生态。\n一句话：作者的 module 方案是\u0026quot;进阶后的选择\u0026rdquo;，不是\u0026quot;新手的起点\u0026quot;。\n六、相关知识点速记 子模块（submodule）：git 处理「仓库里套仓库」的机制，父仓库只存引用指针，不存子仓库代码。 浅克隆（--depth=1）：只拉最新一次提交，不拉历史，省时省空间。 .gitmodules：子模块的登记表，记录子模块路径和对应仓库地址。 git submodule update --init：克隆仓库后，重新拉取所有子模块代码。 ","permalink":"https://ankopala.github.io/posts/git-submodule-explained/","summary":"\u003cblockquote\u003e\n\u003cp\u003e背景：学习 Hugo + GitHub Pages 搭建博客，在「安装 PaperMod 主题」这一步遇到了 \u003ccode\u003egit submodule\u003c/code\u003e 命令。\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cblockquote\u003e\n\u003cp\u003e⚠️ \u003cstrong\u003e注意\u003c/strong\u003e：文中的 PaperMod 主题仓库地址务必以官方为准，使用前请先核对最新地址：\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e官方仓库：https://github.com/adityatelange/hugo-PaperMod\u003c/li\u003e\n\u003cli\u003eSSH 地址：\u003ccode\u003egit@github.com:adityatelange/hugo-PaperMod.git\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e曾误写过 \u003ccode\u003eadnanhob/PaperMod\u003c/code\u003e（该仓库不存在），已更正。仓库地址可能随时间迁移，动手前建议到 GitHub 搜索 \u003ccode\u003ehugo-PaperMod\u003c/code\u003e 确认。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/blockquote\u003e\n\u003chr\u003e\n\u003ch2 id=\"一命令逐词拆解\"\u003e一、命令逐词拆解\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit submodule add --depth\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e git@github.com:adityatelange/hugo-PaperMod.git themes/PaperMod\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth\u003e片段\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003e含义\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ccode\u003egit submodule add\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003egit 的核心命令：添加一个\u003cstrong\u003e子模块\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ccode\u003e--depth=1\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e只拉取最近 1 次提交（浅克隆）\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ccode\u003egit@github.com:adityatelange/hugo-PaperMod.git\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e主题的远程仓库地址（SSH 形式）\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ccode\u003ethemes/PaperMod\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e主题下载到本地的\u003cstrong\u003e位置\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003chr\u003e\n\u003ch2 id=\"二核心概念什么是子模块submodule\"\u003e二、核心概念：什么是「子模块」（submodule）\u003c/h2\u003e\n\u003ch3 id=\"要解决的场景冲突\"\u003e要解决的场景冲突\u003c/h3\u003e\n\u003cblockquote\u003e\n\u003cp\u003e你的博客站点本身是个 git 仓库（\u003ccode\u003emy-blog\u003c/code\u003e），而 PaperMod 主题\u003cstrong\u003e也是一个独立的 git 仓库\u003c/strong\u003e。现在你想把主题代码放进博客的 \u003ccode\u003ethemes/\u003c/code\u003e 目录里。\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e如果直接 \u003ccode\u003egit clone\u003c/code\u003e 主题进去，就会形成「仓库套仓库」的混乱局面——博客的 git 会看到 \u003ccode\u003ethemes/PaperMod\u003c/code\u003e 里还有个 \u003ccode\u003e.git\u003c/code\u003e，管理起来一团糟。\u003c/p\u003e\n\u003ch3 id=\"子模块的机制\"\u003e子模块的机制\u003c/h3\u003e\n\u003cp\u003e子模块就是 git 专门用来解决「仓库里套仓库」的机制。做法很聪明：\u003c/p\u003e","title":"git 子模块与 submodule 命令详解"},{"content":"我要怎样才能留住你？\n我给你贫瘠的街道，绝望的落日，荒郊的月亮。\n我给你一个长久凝望孤月之人的悲哀。\n我给你我的祖先，我死去的人，那些活着的人\n用铜像纪念的魂灵：\n我的父亲的父亲死于布宜诺斯艾利斯的前线，\n两颗子弹洞穿他的胸膛，\n留着胡子，死去，被他的部下用牛皮包裹；\n我母亲的祖父\n——才刚刚24岁，在秘鲁率领三百人冲锋——\n现如今都是骑着马消失的亡灵。\n我给你我书中包含的所有洞察力，\n我生命中的所有男子气概和幽默。\n我给你我仅存的核心，\n——不可由语言言说，不可和梦想交换，不可被时间、\n欢乐与困厄触碰的核心。\n我给你在你出生之前、日落时见到的一朵黄玫瑰的记忆。\n我给你关于你的诠释，你的理论以及关于你\n真实而奇异的信息。\n我给你我的孤独，我的黑暗，我饥饿的心；\n我想要用无常、用危险、用失败贿赂你。\n—— 豪尔赫·路易斯·博尔赫斯（1934） ","permalink":"https://ankopala.github.io/about/","summary":"\u003cp\u003e我要怎样才能留住你？\u003cbr\u003e\n我给你贫瘠的街道，绝望的落日，荒郊的月亮。\u003cbr\u003e\n我给你一个长久凝望孤月之人的悲哀。\u003c/p\u003e\n\u003cp\u003e我给你我的祖先，我死去的人，那些活着的人\u003cbr\u003e\n用铜像纪念的魂灵：\u003cbr\u003e\n我的父亲的父亲死于布宜诺斯艾利斯的前线，\u003cbr\u003e\n两颗子弹洞穿他的胸膛，\u003cbr\u003e\n留着胡子，死去，被他的部下用牛皮包裹；\u003cbr\u003e\n我母亲的祖父\u003cbr\u003e\n——才刚刚24岁，在秘鲁率领三百人冲锋——\u003cbr\u003e\n现如今都是骑着马消失的亡灵。\u003c/p\u003e\n\u003cp\u003e我给你我书中包含的所有洞察力，\u003cbr\u003e\n我生命中的所有男子气概和幽默。\u003cbr\u003e\n我给你我仅存的核心，\u003cbr\u003e\n——不可由语言言说，不可和梦想交换，不可被时间、\u003cbr\u003e\n欢乐与困厄触碰的核心。\u003c/p\u003e\n\u003cp\u003e我给你在你出生之前、日落时见到的一朵黄玫瑰的记忆。\u003cbr\u003e\n我给你关于你的诠释，你的理论以及关于你\u003cbr\u003e\n真实而奇异的信息。\u003cbr\u003e\n我给你我的孤独，我的黑暗，我饥饿的心；\u003cbr\u003e\n我想要用无常、用危险、用失败贿赂你。\u003c/p\u003e\n\u003cdiv style=\"text-align: center;\"\u003e\n—— 豪尔赫·路易斯·博尔赫斯（1934）\n\u003c/div\u003e","title":"关于"},{"content":"这里放友情链接。\n","permalink":"https://ankopala.github.io/links/","summary":"\u003cp\u003e这里放友情链接。\u003c/p\u003e","title":"链接"}]