<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>LAN MIN Blog</title>
  
  
  <link href="https://blog.lanmin.design/atom.xml" rel="self"/>
  
  <link href="https://blog.lanmin.design/"/>
  <updated>2026-05-22T03:35:54.177Z</updated>
  <id>https://blog.lanmin.design/</id>
  
  <author>
    <name>LAN MIN</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>Markdown 样式全量测试页</title>
    <link href="https://blog.lanmin.design/posts/markdown-style-showcase/"/>
    <id>https://blog.lanmin.design/posts/markdown-style-showcase/</id>
    <published>2026-05-20T16:00:00.000Z</published>
    <updated>2026-05-22T03:35:54.177Z</updated>
    
    <content type="html"><![CDATA[<h2 id="使用说明"><a href="#使用说明" class="headerlink" title="使用说明"></a>使用说明</h2><p>这是一篇用于<strong>样式回归测试</strong>的文章。你可以在每次改动渲染器或样式表后，对照本页检查展示是否一致。</p><hr><h2 id="段落与强调"><a href="#段落与强调" class="headerlink" title="段落与强调"></a>段落与强调</h2><p>普通段落：Markdown 的核心是可读性优先，因此你应该在不看渲染结果时也能理解文本结构。</p><p>这段包含 <em>斜体</em>、<strong>加粗</strong>、<em><strong>粗斜体</strong></em>、<del>删除线</del>、<code>行内代码</code>，以及一个普通“高亮文本”占位示例。</p><p>这行包含转义字符：*不是斜体*，`不是代码`，[不是链接]。</p><hr><h2 id="标题层级"><a href="#标题层级" class="headerlink" title="标题层级"></a>标题层级</h2><h3 id="三级标题"><a href="#三级标题" class="headerlink" title="三级标题"></a>三级标题</h3><h4 id="四级标题"><a href="#四级标题" class="headerlink" title="四级标题"></a>四级标题</h4><h5 id="五级标题"><a href="#五级标题" class="headerlink" title="五级标题"></a>五级标题</h5><h6 id="六级标题"><a href="#六级标题" class="headerlink" title="六级标题"></a>六级标题</h6><hr><h2 id="链接"><a href="#链接" class="headerlink" title="链接"></a>链接</h2><ul><li>行内链接：<a href="https://astro.build/">Astro 官网</a></li><li>带 title 的链接：<a href="https://openai.com/" title="OpenAI Website">OpenAI</a></li><li>自动链接：<a href="https://example.com/path?q=markdown">https://example.com/path?q=markdown</a></li><li>邮件链接：<a href="mailto:&#x68;&#101;&#108;&#x6c;&#111;&#x40;&#x6c;&#x61;&#110;&#x6d;&#105;&#x6e;&#x2e;&#100;&#101;&#x73;&#x69;&#103;&#110;">hello@lanmin.design</a></li></ul><hr><h2 id="引用"><a href="#引用" class="headerlink" title="引用"></a>引用</h2><blockquote><p>这是一级引用。引用里可以继续写第二段文字，用来测试多段引用的间距。这里原本可以测试嵌套引用，但为了兼容 TinaCMS rich-text，保持为同一级引用。</p></blockquote><hr><h2 id="列表"><a href="#列表" class="headerlink" title="列表"></a>列表</h2><p>无序列表：</p><ul><li>第一项</li><li>第二项<ul><li>第二项的子项 A</li><li>第二项的子项 B</li></ul></li><li>第三项</li></ul><p>有序列表：</p><ol><li>第一步</li><li>第二步</li><li>第三步</li></ol><p>任务列表（GFM）：</p><ul><li>已完成：接入标准渲染器</li><li>已完成：补充基础样式</li><li>待处理：为更多边缘语法补充视觉规范</li></ul><hr><h2 id="代码块"><a href="#代码块" class="headerlink" title="代码块"></a>代码块</h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">greet</span>(<span class="params">name</span>) &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="string">`Hello, <span class="subst">$&#123;name&#125;</span>!`</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="title function_">greet</span>(<span class="string">&quot;Markdown&quot;</span>));</span><br></pre></td></tr></table></figure><figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">interface</span> <span class="title class_">Post</span> &#123;</span><br><span class="line">  <span class="attr">title</span>: <span class="built_in">string</span>;</span><br><span class="line">  <span class="attr">slug</span>: <span class="built_in">string</span>;</span><br><span class="line">  <span class="attr">tags</span>: <span class="built_in">string</span>[];</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="attr">post</span>: <span class="title class_">Post</span> = &#123;</span><br><span class="line">  <span class="attr">title</span>: <span class="string">&quot;Markdown 样式全量测试页&quot;</span>,</span><br><span class="line">  <span class="attr">slug</span>: <span class="string">&quot;markdown-style-showcase&quot;</span>,</span><br><span class="line">  <span class="attr">tags</span>: [<span class="string">&quot;markdown&quot;</span>, <span class="string">&quot;gfm&quot;</span>],</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">npm run dev</span><br><span class="line">npm <span class="built_in">test</span></span><br><span class="line">npx astro build</span><br></pre></td></tr></table></figure><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;markdown-style-showcase&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;purpose&quot;</span><span class="punctuation">:</span> <span class="string">&quot;visual-regression&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;enabled&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><hr><h2 id="表格（GFM）"><a href="#表格（GFM）" class="headerlink" title="表格（GFM）"></a>表格（GFM）</h2><table><thead><tr><th align="left">语法项</th><th align="center">示例</th><th align="right">状态</th></tr></thead><tbody><tr><td align="left">强调</td><td align="center"><code>**bold**</code></td><td align="right">通过</td></tr><tr><td align="left">任务列表</td><td align="center"><code>- [x] done</code></td><td align="right">通过</td></tr><tr><td align="left">表格</td><td align="center"><code>| a | b |</code></td><td align="right">通过</td></tr><tr><td align="left">代码块</td><td align="center">三反引号围栏代码块（例如 js）</td><td align="right">通过</td></tr></tbody></table><hr><h2 id="图片"><a href="#图片" class="headerlink" title="图片"></a>图片</h2><p>下面使用项目现有资源，便于直接验证尺寸、圆角、响应式与加载：</p><p><img src="/assets/logo-mark.svg" alt="Logo Mark"></p><hr><h2 id="补充语法说明"><a href="#补充语法说明" class="headerlink" title="补充语法说明"></a>补充语法说明</h2><p>这份测试页为了兼容 TinaCMS 的 <code>rich-text</code> 解析，避免使用复杂原生 HTML 片段。<br>快捷键示例改为纯文本写法：<code>Ctrl</code> + <code>K</code>。</p><hr><h2 id="混合内容"><a href="#混合内容" class="headerlink" title="混合内容"></a>混合内容</h2><ol><li>第一项包含链接 <a href="https://docs.astro.build/">Docs</a> 与 <code>inline code</code>。</li><li>第二项包含子列表：<ul><li>子项里有 <strong>强调</strong></li><li>子项里有 &gt; 引用（语义上可读，但不建议过度嵌套）</li></ul></li><li>第三项包含短代码：</li></ol><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.markdown-body</span> <span class="selector-tag">table</span> &#123;</span><br><span class="line">  <span class="attribute">border-collapse</span>: collapse;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><hr><h2 id="结尾检查项"><a href="#结尾检查项" class="headerlink" title="结尾检查项"></a>结尾检查项</h2><ul><li>标题层级间距是否合理</li><li>表格在窄屏是否可横向滚动</li><li>代码块复制按钮是否可用</li><li>链接 hover&#x2F;focus 是否可见</li><li>引用和列表是否有清晰层级</li></ul><p>如果以上都正常，这个内容页的 Markdown 渲染就基本可用于日常发布。</p>]]></content>
    
    
    <summary type="html">用于测试内容页 Markdown/GFM 渲染是否完整、稳定的示例文章，覆盖几乎所有常见语法。</summary>
    
    
    
    <category term="code" scheme="https://blog.lanmin.design/category/code/"/>
    
    
    <category term="markdown" scheme="https://blog.lanmin.design/tags/markdown/"/>
    
    <category term="gfm" scheme="https://blog.lanmin.design/tags/gfm/"/>
    
    <category term="testing" scheme="https://blog.lanmin.design/tags/testing/"/>
    
  </entry>
  
  <entry>
    <title>从提示词到原型</title>
    <link href="https://blog.lanmin.design/posts/prompt-to-prototype/"/>
    <id>https://blog.lanmin.design/posts/prompt-to-prototype/</id>
    <published>2026-05-08T16:00:00.000Z</published>
    <updated>2026-05-22T03:35:54.325Z</updated>
    
    <content type="html"><![CDATA[<p>AI 生成原型最怕的不是做不出来，而是做出来的东西看着热闹、方向却是歪的。</p><h2 id="模糊需求会放大模糊结果"><a href="#模糊需求会放大模糊结果" class="headerlink" title="模糊需求会放大模糊结果"></a>模糊需求会放大模糊结果</h2><p>你越清楚目标、约束和气质，AI 给出的第一版就越接近可用。 </p>]]></content>
    
    
    <summary type="html">AAAAAAAAI 可以帮你把想法快速落成第一版原型，但前提是你已经知道自己在找什么。</summary>
    
    
    
    <category term="design" scheme="https://blog.lanmin.design/category/design/"/>
    
    
    <category term="原型" scheme="https://blog.lanmin.design/tags/%E5%8E%9F%E5%9E%8B/"/>
    
    <category term="提示词" scheme="https://blog.lanmin.design/tags/%E6%8F%90%E7%A4%BA%E8%AF%8D/"/>
    
  </entry>
  
  <entry>
    <title>创造空间</title>
    <link href="https://blog.lanmin.design/posts/creating-space/"/>
    <id>https://blog.lanmin.design/posts/creating-space/</id>
    <published>2026-04-11T16:00:00.000Z</published>
    <updated>2026-05-22T03:35:54.473Z</updated>
    
    <content type="html"><![CDATA[<p>当我重新看待博客首页时，我越来越不把它当作一张“文章索引页”，而把它当作一个<strong>立场声明</strong>。<br>它需要告诉读者：你关注什么，你相信什么样的信息组织方式，以及你想让阅读发生在什么样的气氛里。</p><h2 id="左栏不是导航，而是定调"><a href="#左栏不是导航，而是定调" class="headerlink" title="左栏不是导航，而是定调"></a>左栏不是导航，而是定调</h2><p>这次调整里，我把左栏视为整页的语气来源。作者头像、名称、身份标签、分类切换和文章列表都堆叠在这里，它们不是并列模块，而是同一条叙事链。</p><ul><li>头像负责建立熟悉感</li><li>身份标签负责交代观察视角</li><li>分类负责缩小阅读范围</li><li>列表负责把注意力送往下一篇内容</li></ul><p>如果左栏失去节奏，右侧再漂亮，也只会像一个摆在旁边的装饰面板。</p><h2 id="留白是信息密度的调音器"><a href="#留白是信息密度的调音器" class="headerlink" title="留白是信息密度的调音器"></a>留白是信息密度的调音器</h2><p>很多页面的问题，不是信息太多，而是没有地方让读者呼吸。<br>真正有用的留白，并不抽象，它常常就是几个非常具体的决定：</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-pseudo">:root</span> &#123;</span><br><span class="line">  <span class="attr">--page-padding</span>: <span class="number">48px</span>;</span><br><span class="line">  <span class="attr">--column-gap</span>: <span class="number">24px</span>;</span><br><span class="line">  <span class="attr">--stack-gap</span>: <span class="number">16px</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这些数字在屏幕上形成的不是“空”，而是速度感。<br>当列表的节奏被放慢，读者就更愿意停留。</p><h2 id="右栏应该是回声，不是抢答器"><a href="#右栏应该是回声，不是抢答器" class="headerlink" title="右栏应该是回声，不是抢答器"></a>右栏应该是回声，不是抢答器</h2><p>首页右侧的存在，不该只是填满空间。它更像左栏内容的回声：<br>你在左边做出选择，右边帮你放大那个选择的情绪与重点。</p><p>所以我更喜欢让右栏展示文章预览、封面、标签和一段更具方向感的描述，而不是把整篇正文塞进去。完整阅读应该发生在独立详情页里，这样体验和 SEO 才都站得住。</p>]]></content>
    
    
    <summary type="html">从网格、留白与节奏出发，重新设计一个个人博客首页该如何把内容与气质一起交代清楚。</summary>
    
    
    
    <category term="design" scheme="https://blog.lanmin.design/category/design/"/>
    
    
    <category term="留白" scheme="https://blog.lanmin.design/tags/%E7%95%99%E7%99%BD/"/>
    
    <category term="视觉设计" scheme="https://blog.lanmin.design/tags/%E8%A7%86%E8%A7%89%E8%AE%BE%E8%AE%A1/"/>
    
    <category term="网格" scheme="https://blog.lanmin.design/tags/%E7%BD%91%E6%A0%BC/"/>
    
  </entry>
  
  <entry>
    <title>CSS 变量布局</title>
    <link href="https://blog.lanmin.design/posts/css-variable-layout/"/>
    <id>https://blog.lanmin.design/posts/css-variable-layout/</id>
    <published>2026-04-10T16:00:00.000Z</published>
    <updated>2026-05-22T03:35:54.649Z</updated>
    
    <content type="html"><![CDATA[<p>当一个页面越来越精细时，最先失控的往往不是组件，而是各种间距数字。<br>这时候把布局参数提升为 CSS 变量，几乎总是值得的。</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-pseudo">:root</span> &#123;</span><br><span class="line">  <span class="attr">--page-padding</span>: <span class="built_in">clamp</span>(<span class="number">20px</span>, <span class="number">3vw</span>, <span class="number">48px</span>);</span><br><span class="line">  <span class="attr">--sidebar-width</span>: <span class="built_in">minmax</span>(<span class="number">280px</span>, <span class="number">420px</span>);</span><br><span class="line">  <span class="attr">--panel-gap</span>: <span class="built_in">clamp</span>(<span class="number">20px</span>, <span class="number">2vw</span>, <span class="number">28px</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这样做的好处，是布局会从“一个个局部修补”变成“有中心的整体调音”。</p><h2 id="变量不是为了抽象，而是为了调整效率"><a href="#变量不是为了抽象，而是为了调整效率" class="headerlink" title="变量不是为了抽象，而是为了调整效率"></a>变量不是为了抽象，而是为了调整效率</h2><p>如果一个值未来根本不会被复用，它不一定值得抽成变量。<br>但只要某个值与版式气质直接相关，比如页边距、栏间距、标题节奏，它就应该被提升为系统级参数。</p><h2 id="对响应式最友好的不是断点数量，而是断点态度"><a href="#对响应式最友好的不是断点数量，而是断点态度" class="headerlink" title="对响应式最友好的不是断点数量，而是断点态度"></a>对响应式最友好的不是断点数量，而是断点态度</h2><p>我更倾向于先用 <code>clamp()</code> 让页面自然伸缩，再只在必要时补明确断点。<br>这样页面在宽屏和平板之间不会突然“翻脸”。</p>]]></content>
    
    
    <summary type="html">用 CSS 变量统一管理页边距、列宽和断点，让视觉迭代不再依赖散落的魔法数字。</summary>
    
    
    
    <category term="code" scheme="https://blog.lanmin.design/category/code/"/>
    
    
    <category term="设计系统" scheme="https://blog.lanmin.design/tags/%E8%AE%BE%E8%AE%A1%E7%B3%BB%E7%BB%9F/"/>
    
    <category term="响应式" scheme="https://blog.lanmin.design/tags/%E5%93%8D%E5%BA%94%E5%BC%8F/"/>
    
    <category term="CSS" scheme="https://blog.lanmin.design/tags/CSS/"/>
    
  </entry>
  
  <entry>
    <title>界面留白笔记</title>
    <link href="https://blog.lanmin.design/posts/interface-whitespace-notes/"/>
    <id>https://blog.lanmin.design/posts/interface-whitespace-notes/</id>
    <published>2026-04-09T16:00:00.000Z</published>
    <updated>2026-05-22T03:35:54.781Z</updated>
    
    <content type="html"><![CDATA[<p>留白从来不只是“空一点”。它是阅读速度、层级分隔和界面气质共同形成的结果。</p><h2 id="留白最怕平均主义"><a href="#留白最怕平均主义" class="headerlink" title="留白最怕平均主义"></a>留白最怕平均主义</h2><p>如果所有间距都一样，页面会看起来整齐，但没有节奏。真正舒服的界面，通常会让标题、段落、模块和边界各自拥有不同的呼吸尺度。</p><h2 id="先控制边界，再控制内容"><a href="#先控制边界，再控制内容" class="headerlink" title="先控制边界，再控制内容"></a>先控制边界，再控制内容</h2><p>我更习惯先把页面边缘和主栏宽度定下来，再处理组件之间的微观间距。这样整体气质会稳定得多。</p>]]></content>
    
    
    <summary type="html">把留白拆成边距、间隙与呼吸感之后，信息密度反而更容易被精确控制。</summary>
    
    
    
    <category term="design" scheme="https://blog.lanmin.design/category/design/"/>
    
    
    <category term="留白" scheme="https://blog.lanmin.design/tags/%E7%95%99%E7%99%BD/"/>
    
    <category term="界面设计" scheme="https://blog.lanmin.design/tags/%E7%95%8C%E9%9D%A2%E8%AE%BE%E8%AE%A1/"/>
    
  </entry>
  
  <entry>
    <title>深色界面的灰阶</title>
    <link href="https://blog.lanmin.design/posts/dark-ui-grayscale/"/>
    <id>https://blog.lanmin.design/posts/dark-ui-grayscale/</id>
    <published>2026-04-08T16:00:00.000Z</published>
    <updated>2026-05-22T03:35:54.921Z</updated>
    
    <content type="html"><![CDATA[<p>深色界面不是把背景改黑就结束了。真正决定观感的，是正文、次要信息、边线和装饰元素之间的灰阶关系。</p><h2 id="亮度差要够，但不要刺"><a href="#亮度差要够，但不要刺" class="headerlink" title="亮度差要够，但不要刺"></a>亮度差要够，但不要刺</h2><p>如果正文和背景对比太高，页面会像在发光；如果太低，又会糊成一片。舒适度来自一个很窄的平衡区间。</p><h2 id="分割线要像空气，不要像刀"><a href="#分割线要像空气，不要像刀" class="headerlink" title="分割线要像空气，不要像刀"></a>分割线要像空气，不要像刀</h2><p>在深色界面里，线条更多是在提示边界，而不是强行切开内容。</p>]]></content>
    
    
    <summary type="html">深色界面里真正决定舒适度的，往往不是黑，而是不同层级灰色之间的秩序。</summary>
    
    
    
    <category term="design" scheme="https://blog.lanmin.design/category/design/"/>
    
    
    <category term="深色模式" scheme="https://blog.lanmin.design/tags/%E6%B7%B1%E8%89%B2%E6%A8%A1%E5%BC%8F/"/>
    
    <category term="灰阶" scheme="https://blog.lanmin.design/tags/%E7%81%B0%E9%98%B6/"/>
    
  </entry>
  
  <entry>
    <title>组件化博客首页</title>
    <link href="https://blog.lanmin.design/posts/componentized-homepage/"/>
    <id>https://blog.lanmin.design/posts/componentized-homepage/</id>
    <published>2026-04-07T16:00:00.000Z</published>
    <updated>2026-05-22T03:35:55.089Z</updated>
    
    <content type="html"><![CDATA[<p>一个视觉感很强的首页，往往很容易在实现时滑向“全部写在一个文件里”。<br>最开始这样当然快，但一旦要接 CMS、接 SEO、接真实文章路由，它就会迅速失控。</p><h2 id="拆分的关键不是技术层，而是责任边界"><a href="#拆分的关键不是技术层，而是责任边界" class="headerlink" title="拆分的关键不是技术层，而是责任边界"></a>拆分的关键不是技术层，而是责任边界</h2><p>我更喜欢按用户看到的内容块去拆：</p><ol><li>左侧站点信息与分类</li><li>文章列表</li><li>右侧预览区</li><li>详情页正文区</li></ol><p>这种拆法有个好处：当你调整视觉层级时，不必一路穿透到数据拼接逻辑里。</p><h2 id="内容不应该再藏在脚本里"><a href="#内容不应该再藏在脚本里" class="headerlink" title="内容不应该再藏在脚本里"></a>内容不应该再藏在脚本里</h2><p>原始模板里，文章标题、日期、摘要甚至正文都直接内联在脚本字符串中。<br>这在 demo 阶段没问题，但一旦进入真实博客系统，内容就应该迁到 Markdown。</p><figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> posts = (<span class="keyword">await</span> <span class="title function_">getCollection</span>(<span class="string">&quot;posts&quot;</span>))</span><br><span class="line">  .<span class="title function_">filter</span>(<span class="function">(<span class="params">&#123; data &#125;</span>) =&gt;</span> !data.<span class="property">draft</span>)</span><br><span class="line">  .<span class="title function_">sort</span>(<span class="function">(<span class="params">a, b</span>) =&gt;</span> b.<span class="property">data</span>.<span class="property">date</span>.<span class="title function_">valueOf</span>() - a.<span class="property">data</span>.<span class="property">date</span>.<span class="title function_">valueOf</span>());</span><br></pre></td></tr></table></figure><p>这一步非常重要，因为它不仅提升可维护性，也直接决定搜索引擎能不能正确理解你的页面。</p><figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> articlePreviewState = <span class="title function_">createPreviewState</span>(&#123;</span><br><span class="line">  <span class="attr">activeCategoryId</span>: <span class="string">&quot;all&quot;</span>,</span><br><span class="line">  <span class="attr">currentPage</span>: <span class="number">1</span>,</span><br><span class="line">  <span class="attr">postsPerPage</span>: <span class="number">5</span>,</span><br><span class="line">  <span class="attr">selectedSlug</span>: <span class="string">&quot;componentized-homepage&quot;</span>,</span><br><span class="line">  <span class="attr">posts</span>: collection</span><br><span class="line">    .<span class="title function_">filter</span>(<span class="function">(<span class="params">&#123; data &#125;</span>) =&gt;</span> !data.<span class="property">draft</span>)</span><br><span class="line">    .<span class="title function_">sort</span>(<span class="function">(<span class="params">left, right</span>) =&gt;</span> right.<span class="property">data</span>.<span class="property">date</span>.<span class="title function_">valueOf</span>() - left.<span class="property">data</span>.<span class="property">date</span>.<span class="title function_">valueOf</span>())</span><br><span class="line">    .<span class="title function_">map</span>(<span class="function">(<span class="params">entry</span>) =&gt;</span> (&#123;</span><br><span class="line">      <span class="attr">slug</span>: entry.<span class="property">data</span>.<span class="property">slug</span>,</span><br><span class="line">      <span class="attr">title</span>: entry.<span class="property">data</span>.<span class="property">title</span>,</span><br><span class="line">      <span class="attr">description</span>: entry.<span class="property">data</span>.<span class="property">description</span>,</span><br><span class="line">      <span class="attr">category</span>: entry.<span class="property">data</span>.<span class="property">category</span>,</span><br><span class="line">      <span class="attr">tags</span>: entry.<span class="property">data</span>.<span class="property">tags</span>,</span><br><span class="line">      <span class="attr">cover</span>: entry.<span class="property">data</span>.<span class="property">cover</span>,</span><br><span class="line">      <span class="attr">seoTitle</span>: entry.<span class="property">data</span>.<span class="property">seoTitle</span> ?? entry.<span class="property">data</span>.<span class="property">title</span>,</span><br><span class="line">      <span class="attr">seoDescription</span>: entry.<span class="property">data</span>.<span class="property">seoDescription</span> ?? entry.<span class="property">data</span>.<span class="property">description</span>,</span><br><span class="line">      <span class="attr">permalink</span>: <span class="string">`/posts/<span class="subst">$&#123;entry.data.slug&#125;</span>/?from=home-preview&amp;category=<span class="subst">$&#123;entry.data.category&#125;</span>&amp;page=<span class="subst">$&#123;<span class="built_in">String</span>(currentPage).padStart(<span class="number">2</span>, <span class="string">&quot;0&quot;</span>)&#125;</span>&amp;source=template-migration-validation-case`</span>,</span><br><span class="line">    &#125;)),</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><h2 id="组件边界会反过来塑造设计"><a href="#组件边界会反过来塑造设计" class="headerlink" title="组件边界会反过来塑造设计"></a>组件边界会反过来塑造设计</h2><p>当你真的把首页拆成了几个独立单元，很多视觉问题会自己暴露出来：</p><ul><li>某个区域是不是承担了太多信息</li><li>某个标题是不是只有在大卡片里才成立</li><li>某个动效是不是离开上下文就显得多余</li></ul><p>实现方式从来不只是“技术细节”，它会不断逼着设计变得更诚实。</p>]]></content>
    
    
    <summary type="html">把头像、分类、列表与预览区拆成清晰边界，让作品化首页也能长期维护。</summary>
    
    
    
    <category term="code" scheme="https://blog.lanmin.design/category/code/"/>
    
    
    <category term="Astro" scheme="https://blog.lanmin.design/tags/Astro/"/>
    
    <category term="组件化" scheme="https://blog.lanmin.design/tags/%E7%BB%84%E4%BB%B6%E5%8C%96/"/>
    
    <category term="工程化" scheme="https://blog.lanmin.design/tags/%E5%B7%A5%E7%A8%8B%E5%8C%96/"/>
    
  </entry>
  
  <entry>
    <title>标签组件的状态</title>
    <link href="https://blog.lanmin.design/posts/tag-state-design/"/>
    <id>https://blog.lanmin.design/posts/tag-state-design/</id>
    <published>2026-04-05T16:00:00.000Z</published>
    <updated>2026-05-22T03:35:55.241Z</updated>
    
    <content type="html"><![CDATA[<p>分类标签是个很小的组件，但它承担着页面导航和状态提示两种角色。</p><h2 id="激活态必须一眼能认出来"><a href="#激活态必须一眼能认出来" class="headerlink" title="激活态必须一眼能认出来"></a>激活态必须一眼能认出来</h2><p>用户不应该靠回忆来确认自己现在在哪个分类里。激活态应该在颜色、边界和对比度上都和普通态拉开差距。</p><h2 id="悬停态更像预告"><a href="#悬停态更像预告" class="headerlink" title="悬停态更像预告"></a>悬停态更像预告</h2><p>好的 hover 不应该只是“变个色”，而应该告诉用户：点击之后这里会成为新的焦点。</p>]]></content>
    
    
    <summary type="html">一个分类标签是否好用，往往取决于默认、悬停和激活三个状态是否足够明确。</summary>
    
    
    
    <category term="design" scheme="https://blog.lanmin.design/category/design/"/>
    
    
    <category term="标签" scheme="https://blog.lanmin.design/tags/%E6%A0%87%E7%AD%BE/"/>
    
    <category term="交互" scheme="https://blog.lanmin.design/tags/%E4%BA%A4%E4%BA%92/"/>
    
  </entry>
  
  <entry>
    <title>AI 辅助工作流</title>
    <link href="https://blog.lanmin.design/posts/ai-assisted-workflow/"/>
    <id>https://blog.lanmin.design/posts/ai-assisted-workflow/</id>
    <published>2026-04-04T16:00:00.000Z</published>
    <updated>2026-05-22T03:35:55.397Z</updated>
    
    <content type="html"><![CDATA[<p>我对 AI 最感兴趣的地方，不是“它能不能一键完成”，而是它能否成为一个可靠的中间层。</p><p><img src="/uploads/xnip2026-05-20_20-06-33.png"></p><p><strong>不知道</strong><br><strong>它最好能帮我加速判断、展开方案、补足验证，而不是把所有决定都替我做掉。</strong></p><h2 id="真正有价值的三个环节"><a href="#真正有价值的三个环节" class="headerlink" title="真正有价值的三个环节"></a>真正有价值的三个环节</h2><h3 id="1-需求收束"><a href="#1-需求收束" class="headerlink" title="1. 需求收束"></a>1. 需求收束</h3><p>在需求还模糊的时候，AI 很适合帮我把目标、约束、边界和成功标准先整理出来。<br>这能显著减少后续返工。</p><h3 id="2-视觉与实现之间的翻译"><a href="#2-视觉与实现之间的翻译" class="headerlink" title="2. 视觉与实现之间的翻译"></a>2. 视觉与实现之间的翻译</h3><p>当页面气质已经明确，但还没有变成结构化组件时，AI 很适合帮忙生成第一版骨架。<br>不过这一步的前提，是你自己先知道页面想成为什么样。</p><h3 id="3-回归检查"><a href="#3-回归检查" class="headerlink" title="3. 回归检查"></a>3. 回归检查</h3><p>在功能完成之后，AI 也很适合作为第二双眼睛，帮忙检查：</p><ul><li>SEO 是否补齐</li><li>组件命名是否混乱</li><li>交互是否存在前后不一致</li></ul><h2 id="热闹感最强，也最容易浪费时间的地方"><a href="#热闹感最强，也最容易浪费时间的地方" class="headerlink" title="热闹感最强，也最容易浪费时间的地方"></a>热闹感最强，也最容易浪费时间的地方</h2><p>最容易让人兴奋的，通常是“看起来什么都能生成”。<br>但真正落到项目里，成本最高的常常是：</p><ul><li>内容结构不稳定</li><li>命名没有规则</li><li>生成结果和现有设计系统不一致</li></ul><p>所以我越来越相信，AI 最适合做的是<strong>增强判断</strong>，而不是取代判断。</p>]]></content>
    
    
    <summary type="html">把 AI 放进设计与前端工作流里之后，哪些环节真正提效，哪些只是在制造热闹。</summary>
    
    
    
    <category term="ai" scheme="https://blog.lanmin.design/category/ai/"/>
    
    
    <category term="AI" scheme="https://blog.lanmin.design/tags/AI/"/>
    
    <category term="设计系统" scheme="https://blog.lanmin.design/tags/%E8%AE%BE%E8%AE%A1%E7%B3%BB%E7%BB%9F/"/>
    
    <category term="工作流" scheme="https://blog.lanmin.design/tags/%E5%B7%A5%E4%BD%9C%E6%B5%81/"/>
    
  </entry>
  
  <entry>
    <title>原生 Tab 组件</title>
    <link href="https://blog.lanmin.design/posts/native-tab-component/"/>
    <id>https://blog.lanmin.design/posts/native-tab-component/</id>
    <published>2026-04-03T16:00:00.000Z</published>
    <updated>2026-05-22T03:35:55.541Z</updated>
    
    <content type="html"><![CDATA[<p>很多时候，一个简单的分类切换并不需要引入复杂框架。原生按钮、状态类名和键盘支持就够了。</p><h2 id="先定义状态，再写事件"><a href="#先定义状态，再写事件" class="headerlink" title="先定义状态，再写事件"></a>先定义状态，再写事件</h2><p>组件最重要的是明确状态模型：当前激活项是谁，切换后哪些区域需要刷新。</p><h2 id="语义比动画更先做"><a href="#语义比动画更先做" class="headerlink" title="语义比动画更先做"></a>语义比动画更先做</h2><p>用户首先要能点、能看懂、能切换，之后才是让它动起来。</p>]]></content>
    
    
    <summary type="html">不依赖框架也能做出清晰、可访问、状态明确的分类切换体验。</summary>
    
    
    
    <category term="code" scheme="https://blog.lanmin.design/category/code/"/>
    
    
    <category term="JavaScript" scheme="https://blog.lanmin.design/tags/JavaScript/"/>
    
    <category term="可访问性" scheme="https://blog.lanmin.design/tags/%E5%8F%AF%E8%AE%BF%E9%97%AE%E6%80%A7/"/>
    
  </entry>
  
  <entry>
    <title>字体与系统平台</title>
    <link href="https://blog.lanmin.design/posts/font-platform-selection/"/>
    <id>https://blog.lanmin.design/posts/font-platform-selection/</id>
    <published>2026-04-01T16:00:00.000Z</published>
    <updated>2026-05-22T03:35:55.689Z</updated>
    
    <content type="html"><![CDATA[<p>同一套页面在 macOS 和 Windows 上经常像两个项目。字体栈就是其中最容易被忽略的原因之一。</p><h2 id="默认系统字体并不土"><a href="#默认系统字体并不土" class="headerlink" title="默认系统字体并不土"></a>默认系统字体并不土</h2><p>很多时候，最自然的阅读体验恰恰来自用户已经熟悉的系统字形。</p>]]></content>
    
    
    <summary type="html">中文字体栈看起来像小事，但它会显著影响博客在不同系统里的亲和度和稳定性。</summary>
    
    
    
    <category term="ai" scheme="https://blog.lanmin.design/category/ai/"/>
    
    
    <category term="字体" scheme="https://blog.lanmin.design/tags/%E5%AD%97%E4%BD%93/"/>
    
    <category term="平台体验" scheme="https://blog.lanmin.design/tags/%E5%B9%B3%E5%8F%B0%E4%BD%93%E9%AA%8C/"/>
    
  </entry>
  
  <entry>
    <title>列表渲染模板</title>
    <link href="https://blog.lanmin.design/posts/list-rendering-template/"/>
    <id>https://blog.lanmin.design/posts/list-rendering-template/</id>
    <published>2026-03-31T16:00:00.000Z</published>
    <updated>2026-05-22T03:35:55.817Z</updated>
    
    <content type="html"><![CDATA[<p>一旦文章列表变多，手写重复 DOM 很快就会失控。</p><h2 id="小模板也要有数据约束"><a href="#小模板也要有数据约束" class="headerlink" title="小模板也要有数据约束"></a>小模板也要有数据约束</h2><p>日期、标题、摘要和 slug 如果能先统一格式，后续切换内容源会非常轻松。</p><h2 id="版式输出应该晚一点发生"><a href="#版式输出应该晚一点发生" class="headerlink" title="版式输出应该晚一点发生"></a>版式输出应该晚一点发生</h2><p>先得到干净数据，再决定如何把它渲染成列表、卡片或预览区。</p>]]></content>
    
    
    <summary type="html">通过统一的数据结构渲染文章列表，可以把“内容”和“版式输出”彻底拆开。</summary>
    
    
    
    <category term="code" scheme="https://blog.lanmin.design/category/code/"/>
    
    
    <category term="模板" scheme="https://blog.lanmin.design/tags/%E6%A8%A1%E6%9D%BF/"/>
    
    <category term="渲染" scheme="https://blog.lanmin.design/tags/%E6%B8%B2%E6%9F%93/"/>
    
  </entry>
  
  <entry>
    <title>列表的信息层级</title>
    <link href="https://blog.lanmin.design/posts/list-hierarchy-rhythm/"/>
    <id>https://blog.lanmin.design/posts/list-hierarchy-rhythm/</id>
    <published>2026-03-29T16:00:00.000Z</published>
    <updated>2026-05-22T03:35:55.957Z</updated>
    
    <content type="html"><![CDATA[<p>文章列表看起来简单，但它其实是最吃层级控制的区域之一。</p><h2 id="标题是抓手，摘要是延展"><a href="#标题是抓手，摘要是延展" class="headerlink" title="标题是抓手，摘要是延展"></a>标题是抓手，摘要是延展</h2><p>标题负责让用户停下来，摘要负责让用户决定要不要继续。</p><h2 id="日期不能抢戏"><a href="#日期不能抢戏" class="headerlink" title="日期不能抢戏"></a>日期不能抢戏</h2><p>日期很重要，但它的任务是帮助排序和定位，不该和标题争主次。</p>]]></content>
    
    
    <summary type="html">日期、标题、摘要和箭头如果没有被清晰分层，长列表很快就会失去扫描效率。</summary>
    
    
    
    <category term="design" scheme="https://blog.lanmin.design/category/design/"/>
    
    
    <category term="信息层级" scheme="https://blog.lanmin.design/tags/%E4%BF%A1%E6%81%AF%E5%B1%82%E7%BA%A7/"/>
    
    <category term="列表" scheme="https://blog.lanmin.design/tags/%E5%88%97%E8%A1%A8/"/>
    
  </entry>
  
  <entry>
    <title>Figma 到 HTML</title>
    <link href="https://blog.lanmin.design/posts/figma-to-html-translation/"/>
    <id>https://blog.lanmin.design/posts/figma-to-html-translation/</id>
    <published>2026-03-23T16:00:00.000Z</published>
    <updated>2026-05-22T03:35:56.093Z</updated>
    
    <content type="html"><![CDATA[<p>把 Figma 变成网页，不该只是复制尺寸。更有价值的是把布局逻辑、间距规律和可复用结构翻译出来。</p><h2 id="视觉稿说的是结果，代码需要的是规则"><a href="#视觉稿说的是结果，代码需要的是规则" class="headerlink" title="视觉稿说的是结果，代码需要的是规则"></a>视觉稿说的是结果，代码需要的是规则</h2><p>当你能把一个页面说成“两个主栏、一个浮动工具条、一个滚动内容区”，实现就已经成功一半了。</p>]]></content>
    
    
    <summary type="html">从视觉稿到真实页面，最重要的不是还原像素，而是找到结构、层级与约束关系。</summary>
    
    
    
    <category term="ai" scheme="https://blog.lanmin.design/category/ai/"/>
    
    
    <category term="Figma" scheme="https://blog.lanmin.design/tags/Figma/"/>
    
    <category term="HTML" scheme="https://blog.lanmin.design/tags/HTML/"/>
    
  </entry>
  
  <entry>
    <title>响应式断点判断</title>
    <link href="https://blog.lanmin.design/posts/responsive-breakpoint-judgment/"/>
    <id>https://blog.lanmin.design/posts/responsive-breakpoint-judgment/</id>
    <published>2026-03-18T16:00:00.000Z</published>
    <updated>2026-05-22T03:35:56.237Z</updated>
    
    <content type="html"><![CDATA[<p>我不太喜欢“手机就是 768，平板就是 1024”这种固定思路。断点更应该来自版式本身。</p><h2 id="版式先失衡，断点才出现"><a href="#版式先失衡，断点才出现" class="headerlink" title="版式先失衡，断点才出现"></a>版式先失衡，断点才出现</h2><p>当右侧视觉锚点已经挤压了正文，或者左栏无法再完整容纳信息，才说明页面真的需要切换布局。</p>]]></content>
    
    
    <summary type="html">页面何时从双栏切到单栏，应该由版式是否还能成立来决定，而不是设备名称。</summary>
    
    
    
    <category term="code" scheme="https://blog.lanmin.design/category/code/"/>
    
    
    <category term="响应式" scheme="https://blog.lanmin.design/tags/%E5%93%8D%E5%BA%94%E5%BC%8F/"/>
    
    <category term="断点" scheme="https://blog.lanmin.design/tags/%E6%96%AD%E7%82%B9/"/>
    
  </entry>
  
  <entry>
    <title>博客内容模型</title>
    <link href="https://blog.lanmin.design/posts/blog-content-model/"/>
    <id>https://blog.lanmin.design/posts/blog-content-model/</id>
    <published>2026-03-14T16:00:00.000Z</published>
    <updated>2026-05-22T03:35:56.385Z</updated>
    
    <content type="html"><![CDATA[<p>内容模型越晚补，代价越高。哪怕是个人博客，也值得尽早定义哪些字段是必须的。</p><h2 id="摘要不是正文第一段"><a href="#摘要不是正文第一段" class="headerlink" title="摘要不是正文第一段"></a>摘要不是正文第一段</h2><p>摘要是面向列表页、分享卡片和搜索结果的，它应该为“点击决策”服务。</p>]]></content>
    
    
    <summary type="html">文章标题、摘要、分类、标签和 SEO 字段最好从一开始就有清晰边界。</summary>
    
    
    
    <category term="code" scheme="https://blog.lanmin.design/category/code/"/>
    
    
    <category term="内容模型" scheme="https://blog.lanmin.design/tags/%E5%86%85%E5%AE%B9%E6%A8%A1%E5%9E%8B/"/>
    
    <category term="CMS" scheme="https://blog.lanmin.design/tags/CMS/"/>
    
  </entry>
  
  <entry>
    <title>设计系统的边界</title>
    <link href="https://blog.lanmin.design/posts/design-system-boundaries/"/>
    <id>https://blog.lanmin.design/posts/design-system-boundaries/</id>
    <published>2026-03-10T16:00:00.000Z</published>
    <updated>2026-05-22T03:35:56.533Z</updated>
    
    <content type="html"><![CDATA[<p>设计系统的价值不在于“把一切都收编”，而在于帮团队更快地做出一致决定。</p><h2 id="有重复，才值得收束"><a href="#有重复，才值得收束" class="headerlink" title="有重复，才值得收束"></a>有重复，才值得收束</h2><p>只有当颜色、字号、间距或组件模式已经反复出现，它们才值得被抽成规则。</p>]]></content>
    
    
    <summary type="html">不是所有视觉细节都值得系统化，真正应该沉淀的是会反复影响决策的那部分。</summary>
    
    
    
    <category term="ai" scheme="https://blog.lanmin.design/category/ai/"/>
    
    
    <category term="设计系统" scheme="https://blog.lanmin.design/tags/%E8%AE%BE%E8%AE%A1%E7%B3%BB%E7%BB%9F/"/>
    
    <category term="方法论" scheme="https://blog.lanmin.design/tags/%E6%96%B9%E6%B3%95%E8%AE%BA/"/>
    
  </entry>
  
  <entry>
    <title>视觉重心右移</title>
    <link href="https://blog.lanmin.design/posts/visual-center-shift/"/>
    <id>https://blog.lanmin.design/posts/visual-center-shift/</id>
    <published>2025-12-02T16:00:00.000Z</published>
    <updated>2026-05-22T03:35:56.669Z</updated>
    
    <content type="html"><![CDATA[<p>双栏页面常见的问题，是左边太满、右边太空，最后整页看起来像一半在工作、一半在发呆。</p><h2 id="右侧不是补白区"><a href="#右侧不是补白区" class="headerlink" title="右侧不是补白区"></a>右侧不是补白区</h2><p>如果右侧只是为了“平衡一下”，那它很容易显得虚。更好的方式，是让它承担情绪、预览或视觉锚点的角色。</p>]]></content>
    
    
    <summary type="html">当左侧承载信息、右侧承载气氛时，页面的视觉重心往往会自然向右偏移。</summary>
    
    
    
    <category term="design" scheme="https://blog.lanmin.design/category/design/"/>
    
    
    <category term="版式" scheme="https://blog.lanmin.design/tags/%E7%89%88%E5%BC%8F/"/>
    
    <category term="视觉重心" scheme="https://blog.lanmin.design/tags/%E8%A7%86%E8%A7%89%E9%87%8D%E5%BF%83/"/>
    
  </entry>
  
  <entry>
    <title>代码复制体验</title>
    <link href="https://blog.lanmin.design/posts/code-copy-experience/"/>
    <id>https://blog.lanmin.design/posts/code-copy-experience/</id>
    <published>2025-09-17T16:00:00.000Z</published>
    <updated>2026-05-22T03:35:56.801Z</updated>
    
    <content type="html"><![CDATA[<p>复制按钮这种小交互，如果处理得好，用户几乎感觉不到它的存在；如果处理得差，就会在最需要的时候碍事。</p><h2 id="成功反馈要短"><a href="#成功反馈要短" class="headerlink" title="成功反馈要短"></a>成功反馈要短</h2><p>最好的反馈不是弹窗，而是按钮本身短暂切换成“已复制”。</p>]]></content>
    
    
    <summary type="html">给代码块增加复制按钮并不复杂，但文案反馈、按钮位置和状态节奏会决定它是否顺手。</summary>
    
    
    
    <category term="code" scheme="https://blog.lanmin.design/category/code/"/>
    
    
    <category term="代码块" scheme="https://blog.lanmin.design/tags/%E4%BB%A3%E7%A0%81%E5%9D%97/"/>
    
    <category term="细节体验" scheme="https://blog.lanmin.design/tags/%E7%BB%86%E8%8A%82%E4%BD%93%E9%AA%8C/"/>
    
  </entry>
  
  <entry>
    <title>AI 评审回路</title>
    <link href="https://blog.lanmin.design/posts/ai-review-loop/"/>
    <id>https://blog.lanmin.design/posts/ai-review-loop/</id>
    <published>2025-06-11T16:00:00.000Z</published>
    <updated>2026-05-22T03:35:56.933Z</updated>
    
    <content type="html"><![CDATA[<p>在设计和前端交付之前，我越来越习惯让 AI 先走一遍检查清单。</p><h2 id="它适合抓遗漏，不适合拍板"><a href="#它适合抓遗漏，不适合拍板" class="headerlink" title="它适合抓遗漏，不适合拍板"></a>它适合抓遗漏，不适合拍板</h2><p>像 SEO、命名、状态遗漏这类问题，AI 很容易提醒你；但最后是否成立，还是得人来判断。</p>]]></content>
    
    
    <summary type="html">AI 最适合放进交付前的复查环节，帮你补足第二视角，而不是替你做最终判断。</summary>
    
    
    
    <category term="ai" scheme="https://blog.lanmin.design/category/ai/"/>
    
    
    <category term="AI" scheme="https://blog.lanmin.design/tags/AI/"/>
    
    <category term="Review" scheme="https://blog.lanmin.design/tags/Review/"/>
    
  </entry>
  
</feed>
