<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Sansui's blog</title>
        <link>https://sansui233.com</link>
        <description>记录学习和生活的个人博客</description>
        <lastBuildDate>Thu, 10 Sep 2026 06:15:14 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>zh-CN</language>
        <copyright>All rights reserved 2022, Sansui</copyright>
        <atom:link href="https://sansui233.com/rss" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[每日见闻 - 说说]]></title>
            <link>https://sansui233.com/memos</link>
            <guid isPermaLink="false">https://sansui233.com/memos?id=2026-09-10T06:11:47.000Z</guid>
            <pubDate>Thu, 10 Sep 2026 06:11:47 GMT</pubDate>
            <content:encoded><![CDATA[<h2>2026-09-10 14:02:33</h2>
<p>#分享 #工具 用了 <a href="https://sftpgo.com">SFTPGO</a>。windows 25h2 不知道抽什么风，smb  的服务器文件共享连不上了。</p>
<p>终于把老家 9 年前的路由器换掉了。以前想组 mesh 感想就是面板非常贵，现在的路由器都自带了，虽然各家不兼容就是了……用的是 TPLink 的 7DR3600  Wifi-7 路由器。就看中这个薄薄的一片，没想到还是差点塞不进弱电箱，天线不能弯折，口又是开在正后方的。Easy Mesh 也确实按起来够简单的，只不过当我测出来子路由的公网速度只有 150Mbps 时两眼一黑。但内网速度没问题于是百思不得其解。后面拔线重启了主路由又好了。</p>
<p>然后我换的路由器时候，所有人都说：你又买路由器了，旧的难道不能用了吗……我特意去京东看了一下订单，特么上一个路由器我是 2017 年买的啊！什么叫又！晚上姐夫来也是这么问的，然后把我那老 Wifi5 路由器捡走了，说我姐房间信号不太好……不是……这路由器回收价都只值两块钱。等下……他们有网线吗？应该是没有的……</p>
<hr/>
<h2>2026-09-09 11:18:56</h2>
<p>说来我领了一个领导派的工作，大概就是学别的地区的同事做 Excel数据分析。领导也没说要分析什么，我打电话问同事才知道。然后一个周了，我连数据源都没见到……有数据源真的很快，没数据源不行。</p>
<p>他们用的二十多年前的腾讯系聊天软件（这个软件早在2015年就停止服务了），不上线接不到消息，文件不会自动接收，不及时手动接就保存不了。一开班又被软件全屏了接不到提醒，上班又不能看手机。</p>
<p>很不一样的就是，Si 为主导的行业学的是流程而不是逻辑（人为规定很多都没法整理出逻辑）。领导说最好是她整理的时候我给打个视频看着一步步做，让我有种 20年前的电脑书籍全是截图，告诉你要点哪里这样。我有点哭笑不得，就一个 Excel 业务在那做加减乘除的，有难成这样吗……</p>
<p>打电话的同事说，处理后重复数据，我当时其实非常纳闷，网上下的数据，自己数据的，怎么会处理出重复数据？她说什么 SUMIF 都算了一遍，然后后面的重复项 CountIF 置 0，我也没懂，但没在现场也问不出个所以然。直到晚上我写 Excel 手册时，写到数据透视表才想起来，特么他们是不知道数据透视表这个东西，就在原表上 SUM……</p>
<p>我把数据透视表给父母试了一下，我演示什么，他们就只能做什么，变一下就完全不会了。我能理解，他们只是记住了我说要点哪里，并不知道这样点数据模型发生了什么变化。而我是完全记不住要点哪里，只知道什么按钮能让数据发生变化。但是我也真的很头疼，因为我似乎是第一次知道数据透视表时就明白了数据透视表的概念，所以我完全无法理解他们为什么是在记流程而不是试图去理解数据发生了什么。</p>
<hr/>
<h2>2026-09-04 02:37:33</h2>
<p>研究了一下 Obsidian 导出 PDF BOOK。不得不说目前的 HTML 已经很够用了，@media print 里设置分页，<code>Obsidian </code>.print` 类里设置字号，插件 Better Export PDF 可以预览和设置页脚。设置对于没有复杂图文版式的导出完全够用。</p>
<p>要说常见什么 Markdown 刚需不太行的地方，大概要算自动编号了…… 最后还是靠 AUTO-HEADING 插件。</p>
<p>然后就是 PDF Viewer 的100% size，至少我下的软件算出来都是错的……普遍比 Actual Size 里。对于高分屏，Summatra PDF 一定要自己设置 DPI。我也很纳闷就真的不能获取到屏幕的 DPI信息吗……</p>
<hr/>
<h2>2026-08-19 22:18:52</h2>
<p>Deepseek v4 pro。拿来处理文件资料编译 Wiki 还是不行。本来自然语言规章制度就够不是人读的了，加上情况非常多。 Deepseek 一是在我明确说明要改条款 A2 时，在 A2 里加入了相关的 A1 条款，然后需求 A2 的适用边界也与当前文档的前文 A1 冲突了，还出现了从没有见过的 A2 条款，实际上和 A2 毫无关系。</p>
<p>换回 GPT Sol 瞬间理解对了，适用边界非常清楚。</p>
<hr/>
<h2>2026-08-17 21:07:33</h2>
<p>#分享 书 <a href="https://en.algorithmica.org/hpc/">现代硬件算法（英文）</a></p>
<hr/>
<h2>2026-08-16 23:32:50</h2>
<p>除了父母满意，我对这个工作零点满意。</p>
<p>真的是熬夜网上冲浪了，完全没自己的时间。</p>
<p>好难忍受网不通自动化水平这么低与世隔绝 0 技术发展的行业……</p>
<p>但我自己也没有时间搞开发了。我能偶尔训练图生图模型已经是奢侈了。我是真的很不想在谈论这些时再这么痛苦了。博客有组件还没有写完我觉得我又是永远没有时间去写了。</p>
<p>我虽然知道想法其实更重要，但经验告诉我，想法的发展是会随着技术的学习提高的。想象力与能做的事是基于认知的。我不觉得我十几岁时能写出比现在好的东西。不学习哪里来的认知啊？！</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[用 Obsidian 导出笔记为一本书]]></title>
            <link>https://sansui233.com/posts/2026-09-07-Obsidian-PDF-Print-B5</link>
            <guid isPermaLink="false">https://sansui233.com/posts/2026-09-07-Obsidian-PDF-Print-B5</guid>
            <pubDate>Mon, 07 Sep 2026 12:57:58 GMT</pubDate>
            <description><![CDATA[排版还是太难了]]></description>
            <content:encoded><![CDATA[<p>之前在 Memo 里说想把笔记印出来，以方便无法带手机时看。在 Obsidian 里自己有非常仔细调整过排版自己印了，之后还是送去网上的印刷店打印，可以效果差距非常大。专业的还是太专业了，特此记录。</p>
<p>此次 PDF 成品可以 <strong><a href="https://img-cf.sansui233.com/books/Excel%20%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%20Cookbook.pdf">在此下载</a></strong>。</p>
<h2>一、Obsidian 导出配置</h2>
<h3>插件</h3>
<ul>
<li>Better Export PDF：可预览，可加目录书签</li>
<li>Code Block Customizer：伟大无需多言！代码块终于像样了，完全换掉了 Obsidian live mode 对于代码块的处理方式。</li>
<li>Auto Heading：标题自动编号。对于打印来说自动编号是很重要的。不过没有中文数字。</li>
<li>一个文本编辑器，编辑打印用的 CSS 配置</li>
</ul>
<h3>CSS 配置</h3>
<p>CSS 现在对于打印 (@media print) 的配置比我想得要多得多……</p>
<ul>
<li>自动页码，奇偶页码</li>
<li>页眉页脚</li>
<li>按大章节分页</li>
<li>首页占一整页做封面</li>
<li>防止标题被挤到页尾</li>
<li>防止图片跨页</li>
</ul>
<p>表格的跨页表头还是自动续表的，CSS 还有计数器功能。我惊呆了好吧，原来这么强的吗？已经是符合本次基本的书籍导出的要求了。新的 CSS 还在加印刷相关的内容。</p>
<p>Typst 更强也好用，但就一般笔记导出成书而言还是 markdown + css 快且广泛。
<img src="https://img-cf.sansui233.com/imgs/2026/09/202609072304512.webp" alt=""></p>
<p>上面具体配置我就不细说了，因为本人酷爱装修，样式都是长期累积的结果，印刷用的主题也是在原主题的基础上又叠了一层修修补补，直接放到 <a href="https://gist.github.com/Sansui233/aeb581779e7df8ba22a99f82584338fe#file-pdf-print-css">gist 链接</a>上了。</p>
<p><img src="https://img-cf.sansui233.com/imgs/2026/09/202609072227229.webp" alt=""></p>
<h3>软件</h3>
<p>一定要一个可以读取屏幕 dpi 查看实际大小的软件。Photoshop 是可以的， SummatraPDF 经过设置后也是可以的。其他的我没有试过。</p>
<p>以 SummatraPDF 为例，在「设置」→「高级选项」中，设置 <code>CustomScreenDPI = 189</code> 。其中 189 是我的屏幕 DPI 。你可以直接查阅屏幕型号，或到 <a href="https://www.shutterstock.com/zh/image-design-tools/dpi-ppi-calculator?dd_referrer=https%3A%2F%2Fwww.google.com%2F">这里</a> 计算。</p>
<p>然后重启 SummatraPDF， <code>Ctrl+1</code> 就是打印大小了。</p>
<h2>二、排版</h2>
<p>对于主题，初期我尝试了使用网页风格无衬线主题 ，效果算是非常非常不行，主要打印出来的字非常大一个，而且粗细对比过强，网页感太重了。</p>
<p>对于一般的纸张，书籍印刷确实非常不适合使用粗体字（Bold, weight 600)，除非你用铜版纸这类不吸墨的纸。500 的字重比较适合。</p>
<p>适合印刷的主题是需要重新写的，才有了上面的效果。</p>
<h3>纸张</h3>
<p>可以说 <strong>纸张</strong> 和 <strong>纸张大小</strong> 在印刷里的重要程度能占 60%。</p>
<ul>
<li>纸张种类：道林纸（双胶纸），本白色。</li>
<li>纸张大小：B5。</li>
</ul>
<p>首先是排除办公复印用的荧光剂 A4 纸。这个纸，即便你裁为 B5 的大小，认真胶装，加上铜版纸封面。但那种挺度、表面质感和刺眼的荧光白，仿佛小学复印店里复印出来的一样（实际上就是）。</p>
<p>道林纸（双胶纸）是一种比较常见的纸张。值得注意的是，除非你住印厂旁边，街边的复印店是不会准备本白色的双胶纸的，连大学毕业论文打印的地方都是荧光白A4纸。我走完了一条街的广告店，有个女店主很认真介绍了她存放的纸的种类，说对于特种纸要提前给工厂定制，存放也是有要求的。</p>
<p>如果不想寄印，只能自己买一打回去，带给打印店了。</p>
<p>至于为什么 B5 大小……真的会觉得 A4 纸像书吗？</p>
<h3>字号</h3>
<h6>配置</h6>
<ul>
<li>网页： 16px</li>
<li>Obsidian Better Export 导出缩放：80%</li>
<li>实际大小：9.6pt</li>
</ul>
<p>Chromium 的 PDF 导出以 96dpi 导出，于是 16px 的字体对应的是 12pt。之前买过 Rei 的《印刷排雷手册》，12pt 在正文印刷里已经算是老年人字号了。</p>
<p>因为我想制作册子，使用的是 B5 大小印刷。在初期，我只是问了 AI 缩放到 85% 是否可行（字体大小10.2pt），AI 说可以，我印出来也觉得凑合。但当我拿到专业印厂的印刷后，才发现 10.2 pt 和 9.6 pt 虽然看起来差不太多，但舒适度差距比想象得大…… 10 pt 还是更适合 A4 尺寸。</p>
<h3>边距</h3>
<h6>配置</h6>
<ul>
<li>css:</li>
</ul>
<pre><code class="language-css">@media print {
    @page {
        margin: 12mm 10mm 14mm; /* 正文 80% 缩放不知自带 6mm 边距*/
    }
}
</code></pre>
<ul>
<li>实际边距：左 16mm，上 18mm，右 16mm，下 20mm</li>
</ul>
<p>我没有搞懂为什么 margin 为 0 还是有自带了边距，有可能是我的原来的傻逼主题干的（并不）。</p>
<p>实际边距是 GPT 的推荐值，也是我从印厂拿到的胶印书籍里的测量值。</p>
<h3>行间距与段间距</h3>
<p>这部分反而是祖宗之法。</p>
<ul>
<li>行间距: 1.5倍。</li>
<li>段间距: 1倍 margin。</li>
</ul>
<p>1.5 倍行间距也是考虑到我的笔记有大量的 bullet，没有超过 3 行的长段落，大概比较像教材。小说类的行间距是更稀疏的。</p>
<h2>装订</h2>
<p>我对册子要求就是能平摊，能平摊，能平摊。我讨厌不工整的纸，谢谢。</p>
<p>最开始我使用了固体胶装，牢固是牢固的，但是好像，因为真的干不了所以到处黏纸……后面还是使用了经典的白乳胶放一晚上，非常牢固且照顾手残。</p>
<p>而印厂因为能打印 B3 的尺寸，小册直接用骑马钉了。</p>
<h2>印厂的调整</h2>
<p><img src="https://img-cf.sansui233.com/imgs/2026/09/202609072237670.webp" alt=""></p>
<p>我发给印厂的 PDF 存在着诸多问题。不标准的字体大小，下边距过窄。但是印厂把各个边距给我裁得相当之标准。骑马钉所在的内侧边距要微大于右侧边距。</p>
<p>我的上边距是标准的，所以印厂没有变上边距，只是整体缩小，给了下边距和左右边距正确的距离，可以说是非常细致地排版过了。</p>
<p>质量相差最大的最难的算是灰度网点，AM 胶印的细腻的网点，家用的激光打印机打不出来……真的打不出来。</p>
<p>整个印刷质量、均匀程度和办公用的激光打印机相比，实在差得太多了。</p>]]></content:encoded>
            <category domain="https://sansui233.com/categories/工具">工具</category>
        </item>
        <item>
            <title><![CDATA[个人阅读 RSS 的最佳实践]]></title>
            <link>https://sansui233.com/posts/2026-06-02-personal-rss-reading-best-practice</link>
            <guid isPermaLink="false">https://sansui233.com/posts/2026-06-02-personal-rss-reading-best-practice</guid>
            <pubDate>Tue, 02 Jun 2026 12:50:00 GMT</pubDate>
            <description><![CDATA[省流：新标签页小组件]]></description>
            <content:encoded><![CDATA[<p>我有订阅 RSS 的习惯。在十年前，我觉得做 RSS 阅读的思路就是自定义杂志，放到一个 App 里读很自然。但是时间长了后，逐渐意识到问题所在。 RSS 不存在什么成瘾性，忙的时候很难想起来，忙之后闲下来时也想不起来。只有“啊我想看看大家都在写什么”的时候，才想得起来还可以看看 RSS。</p>
<p>最近换了 Vivaldi 浏览器，有一段时间了，突然我发现我再也没有漏过 RSS。原因是浏览器的新标签页组件。</p>
<p><img src="https://img-cf.sansui233.com/imgs/2026/06/202606031844401.webp" alt="Vivaldi 新标签页"></p>
<p>在打开新网站时，我一直使用 <code>ctrl +T</code> 新建标签页。在这之前，我有尝试过 Chrome 的订阅类插件。最开始使用的掘金插件，当时掘金初创不久，内容还不错。但实际使用发现，在我新建标签页时，是要准备切换工作了，这时掘金的订阅铺满了一整屏，就不会想阅读这么多的信息。即便换到了其他的插件，也依然存在着信息过载的问题。</p>
<p>后来我开始使用订阅服务，几经转换后使用的是 Innoreader。Innoreader 有 Chrome 插件，红点显示未读数。但是，我依然不会点，如果有红点强迫症，来一篇就点一篇很烦。如果没有红点强迫症，就更不会点了。</p>
<p>Innoreader 还会发邮件提醒什么文章没有读。但是打开邮箱时，通常也需要处理事件（指接收验证码）。我不会摸鱼摸到邮箱里去。</p>
<p><img src="https://img-cf.sansui233.com/imgs/2026/06/202606022054681.webp" alt="innoreader 邮件"></p>
<p>Vivaldi 新标签页组件就很好地解决了这个问题。首先，组件面积不大，信息量保持在人可接收的最佳范围（4篇）。至于为什么是4，参考 <a href="https://www.bilibili.com/video/BV12hz2Y1E3B">【毕导】你有一种连你自己都没意识到的超能力</a>。</p>
<p>其次，组件内默认点击是进入的原始网页，给人感觉是我去别人家的装修的房子里做客，还能看看评论。这也是因为我本来就在使用浏览器，并不会在 App 之间跳来跳去。相比于 all in one 的方便，在个人阅读的场景下，浏览器原始网页能给人更强的满足感。</p>
<p>这样一来，我新建标签页时，如果很忙就直接进行原本的事情，RSS 不会打扰到我。如果不忙，我就会看一眼大家都发了什么，有没有什么有兴趣看的内容。</p>
<p>我认为个人维持阅读 RSS 习惯便应该这样，以少量精简的消息，嵌入到日常一定会使用的软件里，同时不会贴脸打扰到人工作，也不会使用角标进行烦人的提醒。</p>
<p>这样的软件其实不多了，大部分的工作软件打开后全程工作区，很少有浏览器新标签页这样每天都会用的非工作区场景。而社媒平台的推荐给你绑得死死的。我之前还用过即刻的 RSS 机器人，完全符合刷社媒时顺便刷到自己的订阅，非常好用，但很快因为监管问题下架了。要么就是推特了。但是写博客的人，又不一定会发推特。不如说，除了阮一峰，我没有再找到每篇博客都发推特的个人博主了。</p>]]></content:encoded>
            <category domain="https://sansui233.com/categories/Diary">Diary</category>
        </item>
        <item>
            <title><![CDATA[draw.io 与 Word 转 PDF 打印时的清晰度问题]]></title>
            <link>https://sansui233.com/posts/2026-05-25-draw-io-svg-to-word-pdf-print</link>
            <guid isPermaLink="false">https://sansui233.com/posts/2026-05-25-draw-io-svg-to-word-pdf-print</guid>
            <pubDate>Mon, 25 May 2026 09:36:00 GMT</pubDate>
            <description><![CDATA[Word 的图打出来超糊的说]]></description>
            <content:encoded><![CDATA[<p><strong>最近打印论文发现一个问题</strong>，我的超高清流程图 PNG，打印出来非常糊。</p>
<p>然后检查了一下 PDF，确实是导出时糊成一坨。</p>
<p><img src="https://img-cf.sansui233.com/imgs/2026/05/202605252012853.webp" alt="1_padded_padded"></p>
<p>我用后期画图用的都是 draw.io，之前也写过 <a href="/posts/2024-11-12-%E6%8A%8Adrawio%E8%A3%85%E4%BF%AE%E4%B8%BA%E7%AE%80%E5%8D%95%E7%BE%8E%E8%A7%82%E7%9A%84%E7%99%BD%E6%9D%BF%E5%BA%94%E7%94%A8">draw.io 相关设置的文章</a>，研究了一下，大概分为两种情况。</p>
<h2>使用像素图（PNG）</h2>
<p>如果使用 PNG 之类的像素图，首先要<strong>确保原图像素足够大</strong>，在 draw.io 中我会导出为 400% 大小。然后在 Word 选项 -> 高级中：</p>
<p><img src="https://img-cf.sansui233.com/imgs/2026/05/202605252012855.webp" alt="2_padded_padded"></p>
<p>可以选择以下两种任意其一</p>
<ul>
<li>不压缩文件中的图像</li>
<li>默认分辨率设置为「高保真」</li>
</ul>
<p>之后把糊图全部替换一遍，这样至少设置后图像不会被压缩。</p>
<p><strong>检查方式</strong>：放大 Word 界面到 250% 后看看图像的清晰度是否可接受。</p>
<p>但是导出 PDF 或者打印时，像素图始终是以图像像素打印的，带有抗锯齿，没有矢量文字那么清晰。而且<strong>流程图用矢量图无疑是更好的</strong>。</p>
<h2>使用矢量图（SVG）</h2>
<p>在使用 draw.io 的 SVG 导出矢量图后，在 Word 中显示不糊了，但是导出为 PDF 发现还是会糊的。</p>
<p><img src="https://img-cf.sansui233.com/imgs/2026/05/202605252012856.webp" alt="3_padded_padded"></p>
<p>PDF 中明显依然是把 SVG 转换为了像素图。并且，「dobj」 的上框线也被截断了一半，因为 bounding box 是从线条中间算的，导出时 SVG 必须加点边距来避免这个情况。</p>
<p>如果想要 Word 能完全按照矢量图处理 SVG，draw.io 导出时需要取消勾选「嵌入字体」和「嵌入图形」。</p>
<p><img src="https://img-cf.sansui233.com/imgs/2026/05/202605252012857.webp" alt="4_padded_padded"></p>
<p>但此时渲染更不对了。一是<strong>字体不对</strong>，其次是 <strong>SVG 内的文字默认不换行</strong>。</p>
<p><img src="https://img-cf.sansui233.com/imgs/2026/05/202605252012858.webp" alt="5_padded_padded"></p>
<p>这是因为 draw.io 的 SVG 默认面向 HTML 的，Word 对于很多 HTML SVG 的渲染特性是不支持的。如果需要 draw.io 的渲染和 Word 一致：</p>
<ol>
<li>在图形框上设置字体，而不是选中文字内部设置字体。</li>
<li>在导出前需要全选图形，然后在右侧栏的文字选项卡中勾选「转换标签为 SVG」。</li>
</ol>
<p><img src="https://img-cf.sansui233.com/imgs/2026/05/202605252012859.webp" alt="6_padded_padded"></p>
<p>但是就算是这样，你还是有可能会发现英文字体间距（kerning）有问题。</p>
<p><img src="https://img-cf.sansui233.com/imgs/2026/05/202605252012860.webp" alt="7_padded_padded"></p>
<p>我看了下<a href="https://www.drawio.com/doc/faq/SVG-export-text-problems">官网的说明</a>，这种情况应该要取消前两项。</p>
<p><img src="https://img-cf.sansui233.com/imgs/2026/05/202605252012861.webp" alt="8_padded_padded"></p>
<p>这样最终效果就完全一致，导出为 PDF 打印后，图表内的文字也和正文一样清晰，而且可以被选中。
<img src="https://img-cf.sansui233.com/imgs/2026/05/202605252012862.webp" alt="9_padded_padded"></p>
<h2>总结</h2>
<p>如果用像素图，记得图像够大，让图像不要压缩即可。</p>
<p>如果用矢量图，需要</p>
<ul>
<li>全选图像，「文本」中取消「自动换行」和「格式化文本」。手动换行</li>
<li>draw.io 导出 SVG 时取消「嵌入字体」和「嵌入图像」，并添加一点边距</li>
</ul>
<p>这样 Word 转 SVG 为 PDF 时，文字可以保持矢量状态，而且可以被选中。</p>]]></content:encoded>
            <category domain="https://sansui233.com/categories/工具">工具</category>
        </item>
        <item>
            <title><![CDATA[Windows 调整之中文字体]]></title>
            <link>https://sansui233.com/posts/2023-09-29-windows-system-chinese-fonts-adjustment</link>
            <guid isPermaLink="false">https://sansui233.com/posts/2023-09-29-windows-system-chinese-fonts-adjustment</guid>
            <pubDate>Wed, 25 Mar 2026 15:33:14 GMT</pubDate>
            <description><![CDATA[让 windows11 字体更好看的一些设置与字体浅谈]]></description>
            <content:encoded><![CDATA[<blockquote>
<p>以下仅适用于低于 4k 缩放 200% 的显示器</p>
</blockquote>
<p>微软雅黑作为随着 Windows7 出现的字体，加上遥遥领先（？）的 ClearType，在当时的 1080p 显示器上十分清晰易读。</p>
<p>但如今的显示器分辨率越来越高，旧版微软雅黑的设计存在着明显的缺陷。</p>
<p>一是其字形设计并不平衡，中宫过大，有的字形可以以难看来形容；二是微软雅黑字形只在 4K 屏 200% 缩放（以上的配置）上有着较好的显示效果。</p>
<p>微软曾经设计过“另一版的微软雅黑”，即 Noble Scarlet，但并没有在正式的系统中使用。这一版字体设计依然中宫偏大，但相对老版收敛了不少，平衡了一些。</p>
<p>另外，如果你不巧像我一样用着 2K 或 2.5K 屏，</p>
<ul>
<li>在 24寸时，100% 缩放字体比较合适，但与 16 寸 1080p 显示器差不多清晰度，不过屏幕可用空间更大。</li>
<li>在 21 寸时，100% 缩放字体会偏小，比较锻炼眼睛。150% 缩放字体大小比较合适，效果更细腻，但字型会比较怪，且屏幕可用空间与 1080p 相同。</li>
<li>在 16 寸时，150% 缩放字体稍微偏小，效果比较细腻，但非整数倍缩放+ClearType 的加持下，一些像素被吞掉，笔画的间距不平衡，有种“ windows 特有的字被虫噬的美”。</li>
</ul>
<p><img src="https://img-cf.sansui233.com/imgs/2024/08/202408190158527.webp" alt="字形"></p>
<p>可以看到，上图的 100% 200% 缩放没有字形变形问题，可以说微软雅黑小字优化是考虑的 100% 缩放。100% 缩放显得糊则是因为图片放大放大倍率过高，实际不会有糊，而是有锯齿感。</p>
<p>150% 缩放会由于 clearType 的“锐化”导致字形变化，不知道的还以为换了个字体。如果是125%、175%的缩放，字体变形更加糟糕。</p>
<p>造成缩放问题的原因大概可以用下图进行简要解释：</p>
<p><img src="https://img-cf.sansui233.com/imgs/2024/08/202408190318888.webp" alt="缩放"></p>
<p>Mac 上的 Retina 渲染相当于 4k 200% 缩放起步。而 windows 下， 2k-2.5k 的屏幕都在 200% 以下的缩放中挣扎。如果软件没有适配高分屏，没有 clearType，强制进行双线性缩放（常见于图片UI），就会显得非常糊。想体验这样的糊，可以下载旧版的原神启动器。</p>
<h2>需要准备</h2>
<ul>
<li><strong>Noble Scarlet</strong>  替换系统的微软雅黑。由于 Noble Scarlet 是一个未完成的字体，普遍使用的是社区修正版，以下是资源参考。
<ul>
<li><a href="https://bbs.pcbeta.com/viewthread-1960120-1-4.html">pcbeta</a></li>
<li><a href="https://www.bilibili.com/read/cv6059905/">bilibili</a></li>
</ul>
</li>
</ul>
<blockquote>
<p>以上苹方加粗版本不一致性问题太多、新版苹方的英文表现相当糟糕，因此不建议使用，其他版本直接替换的都还不错。</p>
</blockquote>
<ul>
<li>系统字体替换工具：搜索 “<a href="https://www.fishlee.net/soft/SysFontReplacer/">字体替换工具 by 随风飘扬</a>”。替换完后重启，否则可能有缩放错误。另外，github 上有一个非侵入式的系统字体替换工具 <a href="https://github.com/Tatsu-syo/noMeiryoUI">noMeiryoUI</a>，可惜换不全 windows 11，只是作为预览不同字体在系统上的效果倒是个很不错的工具。</li>
<li><a href="https://www.mactype.net/"><strong>MacType</strong></a> 改善 ClearType 的虫噬渲染方式带来的不均匀，使用后提升非常非常大。</li>
<li><strong><a href="https://source.typekit.com/source-han-serif/cn/">思源宋体</a></strong>：推荐将浏览器的 Serif 字体设置为此字体。默认的宋体真的，不论中文英文，都很丑……只适合打印。</li>
</ul>
<h2>字体替换说明</h2>
<p>位于 <code>C:\Windows\Fonts</code> 下有三个文件。这个三个文件可以使用上述的<strong>系统字体替换工具</strong>替换（推荐），或者安全模式下 <code>xcopy</code> 命令也可以替换。但是自己替换时要注意备份，这是真正意义上的替换了底层字体。网上也许会说用 PE 启动，但其实并不需要从 PE 启动这么麻烦。</p>
<ul>
<li><code>msyhbd.ttc</code></li>
<li><code>msyh.ttc</code></li>
<li><code>msyhl.ttc</code></li>
</ul>
<p>位于 <code>C:\Users\你的用户名\AppData\Local\Microsoft\Windows\Fonts</code> 也有三个文件，这三个文件可以不用管，直接安装对应新字体就可以让新字体生效，同时老字体也没有被删除，只是会生成 <code>msyhhv_0.ttc</code>，等于是修改了注册表中的字体文件Link。</p>
<ul>
<li><code>msyhhv.ttc</code></li>
<li><code>msyhsb.ttc</code></li>
<li><code>msyhsl</code>.ttc</li>
</ul>
<p>当然，其实你也可以生成注册表</p>
<h2>常用正文黑体简述</h2>
<p><img src="https://img-cf.sansui233.com/imgs/2024/07/202407260100518.webp" alt=""></p>
<h3>苹方</h3>
<p>苹方是一款设计上很优秀的字体，其间架结构、中宫非常平衡，既兼顾了传统的汉字笔画细节又有规整而现代的几何化，间距合理，阅读起来非常舒适。</p>
<p><del>但是……苹方的设计缺字重。</del> 苹方已经发布了可变字体，目前不再缺字重了，下段内容已过时。</p>
<blockquote>
<p>在设计上，苹方没有 Heavy 字重（<a href="https://support.apple.com/en-us/103203">参考</a>）。而在<a href="https://github.com/paraself/PingFang-Fonts">流行的 github 苹方字体仓库</a>中，则是将 Bold 字重映射到了 Heavy，而将原本的Medium 映射到了 bold。虽然这个问题不是苹果设计的导致的，而是一个再次分发时的错误，但致使目前网上能搜索到的第三方仓库的苹方字体整体字重均偏细。</p>
</blockquote>
<p><del>另外，苹方在 2.5K 屏上表现非常糊。</del> hinting 有了，不糊了，下段内容已过时。</p>
<blockquote>
<p>苹方问世时已经进入了 Retina 屏的时代，没考虑过在低 PPI 屏幕上的表现（不是4K屏缩放200%都别用）。</p>
</blockquote>
<p>第三，苹果设备的显示的西文字体是 <a href="https://zh.wikipedia.org/zh-hans/San_Francisco_(2014%E5%B9%B4%E7%9A%84%E5%AD%97%E4%BD%93)">San Francisco</a>，不是苹方。在 <a href="https://lrd.im/blog/2022-01-17">细数 Pingfang SC 的七宗罪</a> 中，也提到仅使用苹方导致不同设备字体 fallback 的不一致的问题。而作为系统字体里的其他问题，例如缺失本地化的字型，也是大部分字体所缺乏的，这已经不仅仅是一个字体问题，而是和字体相关的和 UI 技术标准化问题，难以仅通过字体解决。而无比例数字、冒号不垂直居中、没有垂直标点等细节，则都是因为苹果显示标点数字用的 SF 字体，苹方在此类字符上算是基本能用，但缺少多种场景下的细节。</p>
<blockquote>
<p>其他资源： <a href="https://www.figma.com/community/file/1089832205783108371">Pingfang for windows - Figma</a></p>
</blockquote>
<p>另外，苹方是有版权限制，以下字体除了思源黑体，和大厂的开源黑体，均不可免费商用。</p>
<h3>思源黑体系列</h3>
<p>思源黑体(Noto sans) 是 google 的开源可商用字体，用于 Android 系统，在开源可商用的的黑体其质量无可替代。</p>
<p>更纱黑体是思源黑体的衍生，修改了西文部分，相比思源黑体上更符合作为 无明显风格特征的系统字体，带 hinting 在 1080p 和 2.5k 下都能保证良好的清晰度。</p>
<p>但是，思源黑体系列设计相比于国产的商用字体并不能算好，有时间架结构比较怪异，字形的细节不太统一，比如“用”字明显矮了一截，整理风格上给人一种不稳定感。同时也不是一个大气的字体，比如口字旁处理对于黑体而言偏小，“用”字矮了一些，但是在宋体设计上，“用”字矮的这一截反而让字体看起来平衡。而一个系列的字体衬线、非衬线的统一感来源于其比例，个人理解为思源/更纱系列是优先考虑宋体的字形，和黑体的比例有一定的结合。整体而言还是宋体的设计更加优秀。</p>
<p>相对而言更纱黑体更适合作为系统字体，有着合理的 hinting。思源黑体是不太适合低 ppi 屏的，它的 Regular 字重看起来像 Bold。</p>
<h3>方正兰亭系列（微软雅黑）</h3>
<p>Noble Scarlet （社区版）常规体是新设计中宫收窄的微软雅黑，而粗体是方正兰亭黑 Pro，因此在加粗时，字体明显会变小一圈。</p>
<p>微软雅黑系列字体在标点处理上很差，最直观的就是全角引号，太像半角的处理方式，很难看出前引号与后引号的区别。其实我在写这一篇文的时候，换了 Typora 的字体，才发现前后引号全打反了……</p>
<p>方正兰亭黑 Pro 想对于两版微软雅黑都有着更小的中宫，字形设计中正。但也由于稍小了一些，在低 ppi 屏的小字上笔画更容易显得不太均匀，渲染效果不太好。另外使用此字体需要相比于其他所有字体更大的行距，因为其较小的中宫，字间距显得相对宽了。</p>
<h3>汉仪旗黑系列</h3>
<p>近年来的国产安卓厂商字体都是汉仪旗黑的衍生，代表阿里的普惠体、鸿蒙体、小米的字体、Oppo的字体。</p>
<p>这系列字体间架结构合理，但笔画上更加激进，减弱了起笔与收笔的的传统突出，以追求几何感与现代的科技感。在观感上，这样规矩的方形会使得字体相比方正系列更加圆润，多了现代感但少了汉字的人情味，用于阅读小说时尤其明显。</p>
<p>仅字形而言，作为 UI 是非常不错的。不过 Misans 渲染出来明显偏粗，我没有测试其他同系列字体是否也有这样的问题。</p>
<h2>改掉 Windows 的默认中文无衬线字体</h2>
<p>很多无法分别修改中英字体的 windows 原生应用，当只设置了英文字体时，显示的中文是新宋体（SimSun），比如 vs studio。原因在于系统里的 Microsoft Sans-serif 字体名，回落到的第一个字体就是新宋体……难以想象微软雅黑出了十多年了还有这样的问题。</p>
<p>解决办法：</p>
<ul>
<li>winkey + R, 输入 regdit，进入 windows注册表</li>
<li>进入 <code>HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontLink\SystemLink</code></li>
<li>把 Microsoft Sans Serif 的值中 SIMSUN.TTC 那一行去掉。这样默认的无衬线体就会往后 fallback 到系统的微软雅黑上。</li>
<li>把 <code>Segoe UI</code> 的 <code>TAHOMA.TTF,Tahoma</code> 挪到 <code>MSYH.TTC,Microsoft </code>后面</li>
</ul>
<hr>
<p>创建于 2023-09-29 02:25:44</p>
<ul>
<li>2026-03-25 更新：针对苹方字体资讯更新，增加字体替换说明。</li>
</ul>]]></content:encoded>
            <category domain="https://sansui233.com/categories/工具">工具</category>
        </item>
        <item>
            <title><![CDATA[Minecraft v1.20.1 常用设置]]></title>
            <link>https://sansui233.com/posts/2023-09-26-minecraft-settings-for-v1-20</link>
            <guid isPermaLink="false">https://sansui233.com/posts/2023-09-26-minecraft-settings-for-v1-20</guid>
            <pubDate>Mon, 12 Jan 2026 18:38:09 GMT</pubDate>
            <content:encoded><![CDATA[<blockquote>
<p>更新：<a href="/static/mc-1.20.1-mods/dependencies.html">1.20.1 版本 mod 列表</a>，有详细的 mod 分类与依赖关系。大部分为实用工具</p>
</blockquote>
<p>在 Minecraft 1.20 版本光照引擎被大幅改写，使得帧数提升，模组的数量似乎又多了起来。另外在 fabric 发展起来以后，mod的社区生态有了很大的变化，有很多老牌模组有了更新的替代。现在记录一下实现常用的基本功能需要的模组与修改设置。</p>
<p>我使用的 hmcl 启动器，在其中进行模组下载可显示模组间的依赖情况。以下内容在 1.20.1 中完全兼容，且项目均在维护中。</p>
<h2>1. Mods</h2>
<p>MC 是一款肝度明显过高的游戏。mod 的选用主要是为了：</p>
<ol>
<li>使画面养眼</li>
<li>降低肝度，同时少引入额外的快捷键</li>
<li>优化细节使用体验</li>
</ol>
<p>使用以 fabric-api 构建的模组。</p>
<h3>1.1 渲染类</h3>
<ul>
<li><a href="https://www.mcmod.cn/class/2785.html">Sodium</a>: 渲染优化之神，许多模组的前置</li>
<li>Sodium-extra: 渲染优化之神的扩展，相应 GUI 为reeses sodium options</li>
<li>Lithium: 原版机制的算法改进</li>
<li>Iris: Sodium 加光影</li>
<li><a href="https://www.mcmod.cn/class/9909.html">Custom Entity Models</a>: 自定义实体模型，增强对 optifine 材质包的支持（性能不好，能不用就不用）</li>
<li>Continuity: 无缝纹理，安装后需要启用相应的材质包。对第三方材质包支持一般，主要和 optifine 的格式还是不一样。</li>
<li>Indium: 许多模组的前置，提供 Fabric Rendering API的支持</li>
</ul>
<h3>1.2 功能类</h3>
<ul>
<li><a href="https://www.mcmod.cn/class/1675.html">modmenu</a>: 显示所有模组和相应的设置页面（如果有的话）设置为 <code>\</code> 开配置</li>
<li>carpet: 单人生存必备，可使用命令放置假人以常加载区块刷红石</li>
<li>tweakeroo: 一系列微调的小功能。主要使用 freecamera（灵魂出窍）<code>f5</code>以获得更好的摄影视角，zoom 开启类似 optifine 的按 <code>c</code> 视角放大，handrestock 可自动补货手里的工具、方块</li>
<li>xaero's minimap: 小地图，降肝度必备。需要设置一下显示的东西，默认会非常多，我只开启了玩家、时间、坐标。关闭了网格显示和生物显示。有世界地图和世界地图的 Plus 版本，联动领地声明功能（虽然单人用不太到）</li>
<li>Carry on：手里没有东西时，<code>shift+右键</code> 搬运箱子，降低装饰的肝度。</li>
<li>JEI + <a href="https://www.mcmod.cn/class/6630.html">EMI</a> + 通用拼音搜索: 物品搜索，查看合成配方、查看方块用途，EMI 增加了<strong>查看合成树</strong>，在 JEI 的 <code>r</code> 键可看。切换可合成物品。（没更新的话用 <a href="https://www.mcmod.cn/class/1674.html">REI</a>）</li>
<li><a href="https://www.mcmod.cn/class/4104.html">Invertory Profiles Next</a>: 高版本的 R 键背包整理（但被我改成 <code>z</code> 键整理，R 键通常是 JEI 查看合成表）。自动补充工具、连续合成、捡物品时默认扔到背包中，以及在打开箱子时使用滚轮移动物品。关掉快破损时替换工具。</li>
<li>imblock: 输入法冲突修复</li>
<li>Panda's falling tree：砍树时树会倒下，降低砍树的肝度。</li>
<li><a href="https://modrinth.com/mod/leawind-third-person">Leawind's Third Person</a>: 更好的第三视角。这算是第一个可以日常使用的第三视角模组，挖方块瞄准都很方便。日常的垂直平滑 0.5 以上，不然爬山能晕死。特点是不绑快捷键。(作者新出了 <a href="https://modrinth.com/mod/perspective-api/versions">Perspective API</a>)</li>
<li>better combat: 动作战斗优化，攻速和攻击范围都有反馈了。</li>
<li><a href="https://modrinth.com/mod/litematica">Litematica</a>：投影。辅助红石机械建造，也算是一种降生存建筑的肝度。使用相当简单，一根木棍，control+滚动切换模式，快捷键进菜单。最难的其实是收集足够多的预置模型。但这个模组，要抢 Map 的 M 键……键位需要大改。</li>
<li><a href="https://modrinth.com/mod/hey-wiki">Hey Wiki</a>: 在指向物品时按 h 键查询wiki。在物品越来越多的高版本具有一些引导作用。</li>
</ul>
<h3>1.3 新物品</h3>
<ul>
<li>Gliders：类似塞尔达的滑翔伞，防摔。在空中按空格展开滑翔。使用方式和大部分游戏一致。只是要占一个盔甲位。动画做得很不错。</li>
<li>Waystones：传送石碑，后期物品，降低交通的肝度。如果用地图作弊路径点传送就不需要这个东西了，但理想的玩法还是地图只是用来看的，让传送石碑在地图上显示（需要前期多刷小黑），只能传送石碑处，禁止任意传送。传送石不是个好设计，MC背包不能放下更多东西了。除非有单纯扩容用的背包模组。</li>
<li>travelersbackpack：背包模组，终于有了 fabric 版。虽然 mojang 一直很谨慎地加入新的方块，但似乎从未考虑过方块越来越多时的背包使用问题。再者模组整合包也因为方块种类数爆炸的问题增加背包模组。在 1.12 版本时，背包容量是刚好够的。个人并不是很喜欢背包的设计。</li>
</ul>
<h2>2. 设置</h2>
<ul>
<li>画面尺寸: 1920*1080@60fps，窗口化</li>
<li>视场角: 85</li>
<li>鼠标灵敏度: 75</li>
<li>模拟距离：8</li>
<li>渲染距离：12</li>
</ul>
<h3>2.1 快捷键修改</h3>
<p>总体的键位映射图如下。深绿色为原版的功能。橘色为Mod功能，蓝色为创造模式功能。键位分为直接按键、组合键、修饰键（长按）。MC 原版只能定义直接按键，组合键与修饰键在复杂的 mod 中用得多，并且会覆盖原版的直接按键。</p>
<p><img src="https://img-cf.sansui233.com/imgs/2026/01/202601132155912.webp" alt="KeyMaps"></p>
<h4>游戏主界面</h4>
<p>首先把 ctrl 改到 capslock 键位，方便疾跑。系统全局 powertoys 改的（吐槽一万句control的键位）</p>
<ul>
<li>长按 <code>tab</code>，滚轮切换物品栏。在tweakroo 的「工具」中开启 hotbarscroll，再在 tweakroo  的「快捷键」中把 hotbarscroll 的快捷键设置为 Tab。</li>
<li><code>v</code>: 切换第三人称视角(visual)，很常用的功能。原本是f5，实在太远了</li>
<li><code>f4</code>: Leawind's Third Person 第三人称视角相机调位置。同时关掉左右切换。点按左右，长按居中</li>
<li><code>f5</code>:  灵魂出窍，在 tweakroo 的 freecamera 中设定</li>
<li><code>c</code>: 望远镜，在 tweakroo 的 zoomactivate 中设定</li>
<li><code>b</code>：开背包（如果物品栏有的话）</li>
<li><code>t</code>: 路标点传送管理(transport)。聊天改 <code>enter</code> 键</li>
<li><code>x</code>: 锦致装饰-箭袋</li>
<li><code>m</code>:  显示大地图和设定。地图的其他快捷键全关掉。</li>
<li><code>n</code> Litematica 投影菜单</li>
<li><code>h</code> Hey Wiki 查询指向的物品 Wiki</li>
<li><code>shift+右键</code> 空手时搬运箱子，carry on 自带。</li>
<li><code>\</code> Mod Menu配置</li>
<li><code>n+c</code> Litematica 配置。n系列特别多键。</li>
<li><code>x+c</code> tweakroo 配置</li>
</ul>
<p>特定工具下的修饰键：</p>
<ul>
<li>木棍工具
<ul>
<li><code>~</code>  Litematica 木棍工具修饰键，改变区域大小</li>
<li><code>n+enter</code> Litematica 木棍工具模式5且创造模式下放置投影</li>
</ul>
</li>
</ul>
<p>预留键位：</p>
<ul>
<li><code>g</code> 圆盘菜单</li>
<li><code>~</code>  特定工具修饰键，比如连锁挖矿</li>
<li><code>b</code> 背包(backpack)</li>
<li><code>j</code> FTB任务书(journal)</li>
<li><code>左alt</code> 创造模式下，建筑模组 axiom 用 alt 切换专用物品栏。</li>
</ul>
<h4>合成台、箱子UI</h4>
<ul>
<li><code>r</code> : JEI 查看光标下物品的合成方式</li>
<li><code>u</code> : JEI 查看光标下物品的用途</li>
<li><code>ctrl + 左键点击</code> JEI的物品，移动物品到合成台</li>
<li><code>z</code> : 一键整理。在 IPN 的设置中修改。</li>
<li>使用滚轮以在背包和箱子间移动物品，按shift移动整组</li>
</ul>
<h2>3. 光影</h2>
<ul>
<li>BSL v8.2.04，默认配置High，把 Camera 中的 Bloom 关闭，把 Atmosphere 中的 fog 调到 0，开启 lighting 中的handDynamicLight。抗锯齿的TAA随便开不开，取决于风扇响不响</li>
<li>Complementary Reimagined，配置 medium，high 会开启材质的反射运算量明显变大。夜晚也比较亮，适合生存。</li>
<li>itt 3.0，更适合搭配了写实系材质的建筑，风格最写实的 shader 没有之一。不适合生存。</li>
</ul>
<h2>4. 材质</h2>
<ul>
<li>任意矿物发光材质。比如 <a href="https://www.curseforge.com/minecraft/texture-packs/new-glowing-ores">New Glowing Ores</a>。主要是因为 BSL 光影没有矿物发光，所以要加一个材质以确保有 fallback。</li>
<li><a href="https://afdian.net/a/Nan2uu">彩虹像素</a>，非常优秀的免费猛男材质包，原版风但更精致。有很多更可爱的附加包。</li>
</ul>
<h2>5. 创造模式附加</h2>
<h3>5.1 Mod</h3>
<p>Axiom 高版本环境必备，可以创建实体方块随意拉伸模型，相当好用。</p>
<p>effortLess structure 快速建造几何体。原 effortless buidling。</p>
<p>lotweaks 自定义材质轮盘</p>
<p>wordedit 经典创世神</p>
<h3>快捷键</h3>
<p><code>tab</code>: effortLess structure 轮盘。</p>
<p><code>r</code>: lotweaks 轮盘，和手中方块有关。会禁用丢东西（但创造模式本来就不用丢东西除了篝火灭火，何不用 Axiom 的调试棒？）</p>
<p><code>左 alt</code>： Axiom 的大菜单</p>]]></content:encoded>
            <category domain="https://sansui233.com/categories/游戏">游戏</category>
        </item>
        <item>
            <title><![CDATA[z-index 设计与海浪模型]]></title>
            <link>https://sansui233.com/posts/z-index-and-context-management-and-design-logic</link>
            <guid isPermaLink="false">https://sansui233.com/posts/z-index-and-context-management-and-design-logic</guid>
            <pubDate>Tue, 06 Jan 2026 18:20:00 GMT</pubDate>
            <description><![CDATA[z-index 只是个插件，层叠上下文才是真正的 z 轴]]></description>
            <content:encoded><![CDATA[<blockquote>
<p>本文针对前端中多个元素层叠时 z-index 管理混乱的问题，提出一个名为海浪模型的设计模型，以构建复杂 z-index 管理的最佳实践。</p>
</blockquote>
<h2>基础知识 - 代码的画布</h2>
<p>层叠上下文是代码逻辑上的画布。一旦一个元素产生了层叠上下文，它内部的所有子元素就被包裹在这个范围里。</p>
<p><strong>层叠上下文的产生</strong></p>
<ul>
<li>根元素：<code>&#x3C;html></code></li>
<li>定位 + 层级：<code>position</code> 为 <code>relative</code> / <code>absolute</code> 且 <code>z-index</code> 不是 <code>auto</code>。</li>
<li>固定定位：<code>position: fixed</code> 或 <code>sticky</code>。</li>
<li>CSS3 属性：
<ul>
<li>opacity 小于 1。</li>
<li>transform 不为 none（比如旋转、缩放）。</li>
<li>filter（滤镜）、flex/grid 子元素的 z-index 等。</li>
</ul>
</li>
</ul>
<blockquote>
<p>❗注意：层叠上下文的产生，和层内元素关系，是两套规则，两者之间<strong>没有关系，没有关系，没有关系</strong>。因为部分规则相似，很容易给记混了。</p>
</blockquote>
<p><strong>层叠内元素关系</strong></p>
<p>我使用 context-level 说明层内元素绝对的上下覆盖关系。</p>
<ul>
<li>CL-1: 背景和边框（最底层）</li>
<li>CL-2: 定位元素（如absolute）且负 z-index</li>
<li>CL-3: 块级元素（static 定位的普通 div 等）</li>
<li>CL-4: 浮动元素（float）</li>
<li>CL-5: 内联/行内块元素（文字、图片）</li>
<li>CL-6: 定位元素（如absolute）且 z-index 没有设定为负，还有 opacity，transform 等。</li>
<li>CL-7: 定位元素（如absolute）正 z-index（最顶层）</li>
</ul>
<p>z-index 在其中的作用相当于是一个算层内关系的插件。<strong>必须和定位配套使用，否则不生效。</strong></p>
<p>从功能上说，<strong>层叠上下文才是真正面向用户的Z轴</strong>，z-index属性只是这个 z轴的一个插件。</p>
<h2>视觉画布</h2>
<p>可以发现，被提升到 <strong>CL-6</strong> 的层，其规则和产生一个层叠上下文高度重合，<strong>就像产生了一个新的画布</strong>。这也是为什么说，容易把 CL-6 层等同于产生层叠上下文的层，但是不是的，<strong>CL-6 是描述自己作为子元素的层级</strong>，而“产生层叠上下文”描述的自己作为父元素的行为。</p>
<ul>
<li>opacity 且 z-index: 0。位于 CL-3，产生了层叠上下层文，但是其实层级很低，z-index 是无效的。</li>
<li>relative 且 z-index: auto。位于 CL-6，没产生层叠上下文，其子元素如果有更低的层级，可能会被盖掉。子元素有更高的层级，会盖掉别人。</li>
<li>relative 且 z-index: 0。位于 CL-6，产生了层叠上下层文，其子元素层级和当前元素严格一致。</li>
</ul>
<p>理解了这一点，可以记住。在做目录头时，并不是设置了 <code>relative</code> 就万事大吉了，如果你的后面的元素也是 relative，很容易被覆盖。</p>
<h2>z-index 划分</h2>
<p>考虑到我们不可能把所有画布内元素全挤在 CL-6，全靠 DOM 关系划分层级，因此需要设计 CL-7 的层级，也就是正 index 区域。</p>
<p>正 z-index 的画布内元素应处于同一个层叠上下文内。如果不在同一个，则按产生了新的层叠上下文设计。</p>
<h3>基础逻辑</h3>
<p>对于一个画布（层叠上下文）内，我设计新产生的画布设计上分100层。对应 z-index 0（CL-6）到 z-index 100。每 20 层为一个全屏大画布，比如 Modal。也就是</p>
<ul>
<li>0-20：画布内组件层级</li>
<li>20、40、60、80、100：新画布层级</li>
</ul>
<p>那 21-39 有什么用？<strong>没有用，不要用</strong>。只是为了提醒你，这个东西是个大画布。如果把画布内组件设定到了 20 以上，你可能就不知道什么东西溢出到了 Modal。</p>
<p>此外，如果真的想做一些在不同层级上换来换去的小组件，也可以根据模型的定义很快决定放到哪个层级，非常方便。</p>
<h3>海浪模型</h3>
<p>想象一个海星被 5 层海浪（大画布）冲到沙滩上，每一层海浪上有自己的生物群。</p>
<p>大部分生物都挤在海底（0层以下）层，形成了基石。到第 0-19 层有一堆小东西争先恐后地彰显存在感，但是你又觉得不那么重要。之后的20层、40层、60层通常而言清澈透明，但一旦染色后，就会将下面的生物变得不见天日。</p>
<p>此时你觉得这个海星，你应该看到它吗？应该放在哪一层？</p>
<p>通常而言，层级设计遵循以下基础逻辑。</p>
<ul>
<li>大尺寸元素的层级低小，小尺寸元素的层级高。</li>
<li>重要性高的层级高。</li>
</ul>
<p>第一条是一个视觉规律，第二条则是功能需要。</p>
<h3>0-19 层</h3>
<p>根据基础的逻辑，0-20 层我会如下划分。</p>
<ul>
<li>移动端菜单栏 -> 中偏小，重要，9</li>
<li>浮动按钮 -> 中偏小，但不重要，5</li>
<li>侧边栏 -> 大，但重要。你很难说和浮动按钮哪个在上面。这两个要权衡一下，给到 4。</li>
<li>Hover tips -> 小，重要，19<br>
如果 Hover tip 也可能本身是一个交互丰富的大画布，这时要看重要性。如果重要性与 Modal 相当，设到 20（新一层海浪）。如果只是随便看看，共享当前层的主要内容，只是覆盖一下正文，设到 0 或 1。大画布谨慎设置中间值，容易造成混乱。</li>
<li>目录头：暂时一下冒头，给到 0（注意是 z-index:0，不能是 z-index:auto）</li>
<li>拖拽：暂时冒一下头，给到0。</li>
</ul>
<p>在海浪模型里，<strong>带 9 的数字被表示为重要，而整十数表示为新的起点</strong>。</p>
<h3>20、40、60层</h3>
<p>几乎为 Modal 层。通常页面上只会出现一个Modal，20 层足够使用，或者你要设置为40，60，都可以。如果你有很多层 Modal 要排序（窗口管理）。要么从 z-index 入手，要么从 DOM 结构入手。显然，别去动 DOM 结构树，靠 z-index 足够完成窗口层级管理。</p>
<h3>最重要的海星</h3>
<p>这个海星如果你认为是稀世珍宝，任何时候都需要被看见，请直接设置到 999。但一旦，你认为它有可能会被覆盖，请思考它被覆盖时，是不是还是这么重要。</p>
<p>如果不确定，参考基础逻辑：<strong>面积越小通常越重要</strong>。这不是一个我定义的规则，而是客观的视觉逻辑。面积越小，通常代表了信息量越密集。一个很常见的对比是：</p>
<ul>
<li>Hover tips（小面积）：在一个层非常非常重要。但需要被新画布覆盖</li>
<li>消息通知（中小面积）：重要吗？超重要的，但是消息通知上是不是还是应该可以 Hover 一些提示？</li>
<li>Hover reference（大面积）：比如参考。重要吗？很重要。但是你觉得需要被消息通知、进度条覆盖吗？需要。</li>
</ul>
<h3>天空层（1000+）</h3>
<p>总有些东西，你希望他们不要在海浪里浮动，而浮动在天上，不被任何东西覆盖。比如全局进度条、全局 Hover、全局消息。</p>
<p>放在天空的这点问题本身不大。最大的问题是，你觉得这个海星，应该放在海浪还是天空？<strong>不要让本该在海里的海星升天</strong>。一旦你觉得这个海星会被新逻辑的 Modal 覆盖，请让海星立刻返回 0-19 层。</p>
<h2>为什么要思考海浪模型</h2>
<ul>
<li>易于复用：对于可复用的浮动组件，不管其父元素的 CL 层级，总能被安插到正确的位置。如果发现异常，那就是忘了使父元素产生层叠上下文来包裹他</li>
<li>避免混乱，减少设计的心智负担</li>
</ul>]]></content:encoded>
            <category domain="https://sansui233.com/categories/学习">学习</category>
        </item>
        <item>
            <title><![CDATA[Better Web Typography for a Better Web 中文版]]></title>
            <link>https://sansui233.com/posts/2025-12-30-Better-Web-Typography-for-a-Better-Web-Chinese-Version</link>
            <guid isPermaLink="false">https://sansui233.com/posts/2025-12-30-Better-Web-Typography-for-a-Better-Web-Chinese-Version</guid>
            <pubDate>Mon, 29 Dec 2025 22:10:00 GMT</pubDate>
            <description><![CDATA[我的排版启蒙书]]></description>
            <content:encoded><![CDATA[<p>这是一本讲网页排版的书籍，书中内容有在线示例与代码，是这么多年来对我极其有用的平面设计书籍之一，说是我的排版启蒙也不为过。此博客的采用的正文排版均构建于此书所介绍的基础上。</p>
<ul>
<li>书名：Better Web Typography for a Better Web</li>
<li>译名：更好的网页排版，造就更好的互联网</li>
</ul>
<blockquote>
<p>此书为 90% 的 AI 翻译，完全保留原书排版，由人工校对以确保大部分用词统一。</p>
</blockquote>
<h2>推荐语</h2>
<p>2018 年，我还在大学社团做海报，那时候对排版的理解更多是靠“直觉”。直到接触到了 Matej Latin 的网页排版公开课，也就是这本书的起源。课和中提出“排版的完美等边三角形”——即字号、行高与行宽之间的动态平衡，以及“模块化比例”的概念，彻底改变了我观察网页的视角。我至今铭记在心：“要获得完美的段落，需要三样东西：字体大小、行高和行宽。它们需要达到平衡。”</p>
<p>从那以后，这三要素就成了我做阅读文字时绕不开的底层直觉。每当我看到一个网页，总会下意识地去拆解它的文字比例是否协调。尽管此书以英文为基准，其中的排版规律对多种语言均适用。</p>
<p>虽然这本书写在八年前，在互联网平面设计风格迭代如此之快的今天，它讨论的核心规则却依然稳固。甚至可以说，如今主流的网页排版方向，就如书中的所言。如果你想摆脱“凭感觉”排版，真正理解排版的美学逻辑，倾情您阅读推荐这本书。</p>
<h2>简介</h2>
<p>Better Web Typography for a Better Web 是一本源自高分在线课程的著作，旨在向网页设计师和开发人员等网站构建者讲解排版。作者 Matej Latin 将垂直节奏（vertical rhythm）、模块化比例（modular scale）和页面构成（page composition）等复杂概念，以通俗易懂的方式进行了深入浅出的解析。本书配有实时代码示例，读者在阅读过程中将亲历设计并构建一个示例网站的完整流程。这是一本针对新媒介的排印新书：基本规则虽未改变，但除此之外的一切都已焕然一新。</p>
<h2>摘录</h2>
<ol>
<li>“……如果说我希望你们从这次演讲中记住一个关键要点，那就是以下内容——要获得完美的段落，需要三样东西：字体大小、行高和行宽。它们需要达到平衡。”</li>
<li>大多数网站都会犯的一个错误，就是将主体文本设置得过小。早在21世纪初，将主体文本大小设置在大约11像素是常见的做法。但当时的屏幕更小，分辨率也较低，这意味着11像素的字体在当时看起来比现在更大。</li>
<li>推荐文本行长度为45至75个字符。需考虑所用语言的平均词长。</li>
<li>我认为，我们开始创建网站时，首先应该审视网站的主要目的。不仅仅是我们正在设计的特定网站，而是其真正、根本的目的。我指的是——<strong>内容</strong>。试想，没有内容的网站是什么？它是一个空壳。内容糟糕但外观精美的网站是什么？它就像一个外表好看但缺乏个性的人。那么反过来说呢——内容出色但外观贫乏的网站？它就像是一个个性鲜明、趣味十足的人，却因为“外表不够标准”而无人关注。</li>
</ol>
<h2>资源链接</h2>
<p>CloudFlare - R2 直链下载：</p>
<ul>
<li><a href="https://img-cf.sansui233.com/books/%E6%9B%B4%E5%A5%BD%E7%9A%84%E7%BD%91%E9%A1%B5%E6%8E%92%E7%89%88%EF%BC%8C%E9%80%A0%E5%B0%B1%E6%9B%B4%E5%A5%BD%E7%9A%84%E4%BA%92%E8%81%94%E7%BD%91%20-%20Matej%20Latin.epub">更好的网页排版，造就更好的互联网 - Matej Latin</a></li>
</ul>
<p>标签： 排版，字体排印，平面设计，网页设计</p>]]></content:encoded>
            <category domain="https://sansui233.com/categories/书和剧">书和剧</category>
        </item>
        <item>
            <title><![CDATA[uv 管理 conda 项目依赖]]></title>
            <link>https://sansui233.com/posts/2025-07-24-embed-python-with-uv</link>
            <guid isPermaLink="false">https://sansui233.com/posts/2025-07-24-embed-python-with-uv</guid>
            <pubDate>Thu, 24 Jul 2025 12:12:32 GMT</pubDate>
            <description><![CDATA[沐神都解决不了的……]]></description>
            <content:encoded><![CDATA[<h2>conda 的问题</h2>
<p>Python 新项目使用 uv 管理容易，但是总是有一些老项目不用。 conda 包管理一直以来都是 AI 的标配。我用 python 99% 都是在扒别人代码运行。这就导致了我运行了多少个项目，就装了多少份 torch……硬盘再大也经不起十几次折腾。</p>
<p><img src="https://img-cf.sansui233.com/imgs/2025/07/202507242029977.webp" alt="沐神都解决不了的"></p>
<p>conda 的问题在于</p>
<ol>
<li>requirements.txt <strong>全手写</strong>！很多人可能忘更新配置，导致扒拉下来缺库运行不了，先解决一个小时的依赖问题再说。</li>
<li>依赖和安装顺序强相关。比如项目需要更新的 numpy，但你可能要装个别的项目的库，python 发了论文和仓库就跑的项目是很多的。安装一个旧项目导致之前安装 numpy 被卸载，然后整个项目就垮掉。这种情况相当之多，又解决两个小时的依赖问题。</li>
<li>（至少我不愿意看到）电脑里十几个相同版本的 torch 和 cuda。当时的硬盘还只有 256G，多装几个 torch 无法接受，嗯……</li>
</ol>
<p>直到现在都还是这样的，大家主打一个能跑完实验就行。包的更新是激进的，包管理是落后的。在几年前有人说用 PDM，后面有 poetry。这两是不用再手写 <code>requirements.txt</code> 了，依赖也会自动 resolve 不会覆盖来覆盖去的，但还是会装十几个 torch。直到 uv 开始用硬链接进行包管理。</p>
<h2>uv 之于 conda 项目</h2>
<p>uv 接管 python 界的依赖管理按理说已经没什么问题。但实际情况是，很多项目还是在用 conda。除非哪天 torch 和 HF 都把 uv 设置为首推，否则就得一直与  conda 存在的问题战斗。</p>
<h3>1. 不提供 venv 的项目</h3>
<p>用于研究的项目一般都是不提供的打包好的环境的，主要是太大了，每个人设备情况也不一样。所以下载后第一件事是</p>
<pre><code class="language-sh">uv venv
./.venv/Script/activate
</code></pre>
<p>如果这个项目不再更新了，或者是打算迁移到 uv，可以直接使用 uv 的方式管理依赖。uv 会自动维护 <code>pyproject.toml</code> 和 <code>uv.lock</code> 文件。</p>
<pre><code>uv add -r requirements.in -c requirements.txt
</code></pre>
<p>如果这个项目，他还在更新，你时不时就得去拉一下分支。这时候最好用 <code>uv pip</code> 。至于依赖混乱问题，听天由命吧。<del>跑得起来就得了</del></p>
<pre><code>uv pip install -r requirement.txt
</code></pre>
<h3>2. 提供 venv 的项目</h3>
<p>提供 venv 的项目通常是给人用的，b 站的整合包一大堆。这种已经配好环境的项目也意味着你最好只用 pip。通常还是非常原始地调用 pip</p>
<pre><code>./.venv/python -m pip install xxx
</code></pre>
<p>……等于说又开始了安装十几份 torch 的依赖管理模式。用 uv 是可以重复利用缓存的。这个时候 uv 的问题在于无法接管 python 环境，需要设置一下环境变量：</p>
<pre><code class="language-sh">export UV_PYTHON="./.venv/python"
uv pip list
</code></pre>
<p>然后就可以利用 uv 的缓存了。</p>
<p>当然，依赖混乱问题使用 <code>uv pip</code> 是无法避免的。这对于发行版也是一种麻烦。因为发行版的环境全给你配好了，但有的项目设计了插件系统，插件系统又需要装插件的 requirement.txt，安一个许久没更新的插件让主项目废掉的情况也不是不可能……</p>
<p>如果让插件作者指定的兼容版本？只靠规范做不到，必须像MC那样检查版本号，不更新版本号就不放行。这样就算不更新代码了，也得倒逼作者每个版本都进行一次（至少是与主项目的）依赖兼容性测试。</p>
<p>我觉得以当前 python 的运行方式，不 lock 子依赖的版本，这个问题是没法解决的。</p>
<h2>uv 管理 torch 下载源</h2>
<p>通常而言，在不指定 index 时 uv add torch 是去 pypi 或清华镜像源找 CPU 版本。如果打算每个项目都采用一样的 torch 版本 和 cuda ——</p>
<h3>uv 创建的新项目</h3>
<p>共用的 <code>uv.toml</code> 指定下载源。</p>
<p>Linux 在 <code>.config/uv/</code> 下，Windows 在 <code>%APPDATA%/uv/</code> 下。</p>
<pre><code class="language-toml">[[index]]
url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple/"
default = true
[[index]]
name = "pytorch-cu128"
url = "https://download.pytorch.org/whl/cu128"
explicit = true
[[index]]
name = "pytorch-cu126"
url = "https://download.pytorch.org/whl/cu126"
explicit = true
</code></pre>
<p>项目级别的 <code>pyproject.toml</code></p>
<pre><code class="language-toml">dependencies = [
  "torch==2.8.0",
  "torchvision==0.23.0",
  "torchaudio==2.8.0",
]

[tool.uv.sources]
torch = [
  { index = "pytorch-cu128"},
]
torchvision = [
  { index = "pytorch-cu128"},
]
torchaudio = [
  { index = "pytorch-cu128"},
]
</code></pre>
<p>然后执行 <code>uv sync</code> 安装。</p>
<h3>uv pip 管理老项目</h3>
<p>要复用必须满足四个相同：python 版本相同, index-url 相同, torch 版本号相同， torch 后端相同。</p>
<p>python 版本由 venv 创建时决定。我们需要指定缓存里的 <strong>torch 版本</strong>， <code>--index-url</code> 和 <code>--torch-backend</code>。少一个都不行。</p>
<pre><code class="language-shell">uv pip install torch==2.8.0 torchvision==0.23.0 torchaudio==2.8.0 --index-url https://download.pytorch.org/whl/cu128 --torch-backend=cu128
</code></pre>
<p>和用 pip 的方式差不多，区别是会硬链接到集中的缓存，不会重复占用十几份 torch。当然。该有的依赖冲突还是会有的。<del>关键是装好后就不要更新了</del></p>]]></content:encoded>
            <category domain="https://sansui233.com/categories/学习">学习</category>
        </item>
        <item>
            <title><![CDATA[踩了一圈 CSS 构建方案的坑]]></title>
            <link>https://sansui233.com/posts/2025-07-12-compare-css-solutions</link>
            <guid isPermaLink="false">https://sansui233.com/posts/2025-07-12-compare-css-solutions</guid>
            <pubDate>Sat, 12 Jul 2025 04:49:09 GMT</pubDate>
            <description><![CDATA[前端代码中质量最薄弱的一环]]></description>
            <content:encoded><![CDATA[<p>css 的写法一直算比较混乱的。层叠的样式表与 DOM 结构的分离看似清晰，但也因此容易产生屎山，组合太自由，哪些选择器用了哪些选择器没用，共用的嵌套的，分离的。今天小编就带你一探究竟（……）</p>
<h2>CSS类复用粒度</h2>
<p>我自己把 css 选择器（类）的复用粒度分三个层级。</p>
<h3>组件类</h3>
<p>粒度最大的层级，通常按组件级别语义化。选择器一般是下面这些名字</p>
<pre><code class="language-css">.wrapper
.container
.list-item
</code></pre>
<p>组件化的选择器下面通常有很多条的 css。</p>
<h3>功能类</h3>
<p>通常是共用的样式或状态，比如</p>
<pre><code class="language-css">.open
.close
.light
.dark
.glass-effect
</code></pre>
<p>这个看起来好像和组件类不冲突，但硬说的话组件类其实应该是这样</p>
<pre><code class="language-css">.container.open { 此处将 .open 的所有样式全覆盖 }
.container.close { 此处将 .close 的所有样式全覆盖 }
.container.light { 此处将 .light 的所有样式全覆盖 }
.container.dark { 此处将 .dark 的所有样式全覆盖 }
</code></pre>
<p>组件类的状态严格在组件的 scope 下。功能类则是可以不限 Scope 的复用。</p>
<p>这 CSS 容易混乱的根源。在工程维护角度，功能类是最不敢乱动的类，不知道动了后哪里样式就会出问题。但在设计角度，用功能类复用一些状态又确实很方便，统一设计也好用。比如增加统一的圆角、描边、阴影样式。</p>
<p>功能类的优缺点是一体两面——图像的只有主观的好看与否，没有客观的对错。</p>
<h3>原子类</h3>
<p>定义海量常用的基础样式类，在 class 上直接写类名就能获得对应效果。就是 tailwind css。</p>
<p>原子类相较于功能类粒度更小，也不会轻易改动 css 属性。</p>
<pre><code class="language-css">.flex
.col-1
.text-sm
</code></pre>
<h2>方案</h2>
<p>通常来说，一个库的样式会着重在一个某一个粒度上。</p>
<h3>原生 css</h3>
<p>用原生 css 时通常会以 <strong>组件化</strong> 的粒度为主，带极少的功能类。现在配合 css 变量使用。早期的网页简单，一个 CSS 文件就能搞定全站，设计上并没有考虑项目变得越来越复杂后的实践。</p>
<p><strong>优点</strong>：性能好，扁平的结构利好小项目。适合写研究新样式。</p>
<p><strong>缺点</strong>：过于扁平，大量工程化后易屎山，存在样式与 DOM 分离带来的维护混乱。</p>
<h3>SCSS</h3>
<p>古法预处理器，可能多层嵌套 css，可组合。是 <strong>组件化</strong> 的粒度。在 CSS.module 出来前，用 SCSS 分割 Scope 挺好用。</p>
<p><strong>优点</strong>：结构非常清晰</p>
<p><strong>缺点</strong>：</p>
<ol>
<li>编译后的选择器很长一串，从浏览器渲染角度，匹配DOM是耗性能的</li>
<li>难以应对复杂项目 DOM 结构的改变，需要考虑扁平化 + 命名，但这样做和原生 CSS 的维护体验也不相上下。</li>
</ol>
<h3>CSS Module</h3>
<p>CSS Module 是完全 <strong>组件化</strong> 的粒度。相比起 SCSS 的样式与 DOM 分离，CSS Module 为组件内部样式耦合，组件间样式分离。</p>
<p><strong>优点：</strong> 在组件粒度分割合理的情况下，清晰易维护。</p>
<p><strong>缺点</strong>：依赖预构建，写类名写起来太磨叽了。整体我用得不多没法评价。</p>
<pre><code class="language-jsx">const Button = () => {
  return (
    &#x3C;button className={styles.button}>
      Click me
    &#x3C;/button>
  );
};
</code></pre>
<h3>BootStrap</h3>
<p><strong>组件化</strong> 为主，少量原子化修饰的预制样式库，拿来即用是不错的。早期 CSS 框架大多是指预制样式，和预构建的库有本质区别。</p>
<h3>Tailwind css</h3>
<p>完全原子化的神奇之库，通过编译可以有功能类和组件类。它更像是重新定义了 css 语法。</p>
<p><strong>优点</strong></p>
<ol>
<li>灵活，快，好看</li>
<li>工具链齐全，可以裁剪掉不用的原子类。</li>
</ol>
<p><strong>缺点</strong></p>
<ol>
<li>稍微要写复杂一点的样式，DOM 就会被一大堆 class 埋没。</li>
<li>从浏览器渲染角度，匹配、合并大量 CSS 样式是需要更多性能开销的</li>
<li>要做到同种样式的复用，必须组合原子类，变成功能类或组件类，否则维护起来相当麻烦。这似乎违背了用 tailwind css 的初衷，熟悉了 css 的不如直接自己用 css 手撮功能类和组件类。</li>
<li>其实我是 tailwind 黑，嗯。但无法否认开发时确实很快很方便。</li>
</ol>
<pre><code class="language-jsx">function Card({ title, description, imageUrl, imageAlt }) {
  return (
    &#x3C;div className="max-w-sm rounded overflow-hidden shadow-lg">
      &#x3C;img className="w-full" src={imageUrl} alt={imageAlt} />
      &#x3C;div className="px-6 py-4">
        &#x3C;div className="font-bold text-xl mb-2">{title}&#x3C;/div>
        &#x3C;p className="text-gray-700 text-base">{description}&#x3C;/p>
      &#x3C;/div>
      &#x3C;div className="px-6 pt-4 pb-2">
        &#x3C;span className="inline-block bg-gray-200 rounded-full px-3 py-1 text-sm font-semibold text-gray-700 mr-2 mb-2">#photography&#x3C;/span>
        &#x3C;span className="inline-block bg-gray-200 rounded-full px-3 py-1 text-sm font-semibold text-gray-700 mr-2 mb-2">#travel&#x3C;/span>
        &#x3C;span className="inline-block bg-gray-200 rounded-full px-3 py-1 text-sm font-semibold text-gray-700 mr-2 mb-2">#adventure&#x3C;/span>
      &#x3C;/div>
    &#x3C;/div>
  );
}
</code></pre>
<h3>原生 css in js</h3>
<p>指 JS Object 转译为 CSS。由于写起来太不像 CSS，复杂的功能写起来过于不直观 ，我直接 PASS。</p>
<pre><code class="language-jsx">const InlineStyleExample = () => {
  const myStyle = {
    color: 'blue',
    backgroundColor: 'lightgray',
    padding: '10px',
    borderRadius: '5px'
  };

  return (
    &#x3C;div style={myStyle}>
      &#x3C;p style={{ fontSize: '18px', fontWeight: 'bold' }}>
        This text is styled with inline CSS.
      &#x3C;/p>
    &#x3C;/div>
  );
};
</code></pre>
<h3>Styled-components</h3>
<p><strong>组件化</strong>的 CSS in JS 方案，写起来像 CSS 实际是 JS。支持客户端动态修改 CSS 具体属性（其他方案做状态改变主要依靠 selector 的匹配）</p>
<p><strong>优点</strong>：</p>
<p>灵活好拓展，比如主题管理不仅仅是颜色，还可以是图片资源一类的。</p>
<p><strong>缺点</strong>：</p>
<ol>
<li>因为是 JS 转 CSS，服务器编译慢和客户端渲染慢得选一个</li>
<li>React 的 useContext 要被废弃了，而 styled-components 严重依赖此 hook，导致进入了维护状态。JS 框架发展太快了。</li>
</ol>
<pre><code class="language-jsx">import styled from 'styled-components';

// Create a styled button component
const StyledButton = styled.button`
  background-color: blue;
  font-size: 16px;
  padding: 10px 20px;
  border-radius: 5px;

  &#x26;:hover {
    background-color: darkblue;
  }
`;

function App() {
  return (
    &#x3C;div>
      &#x3C;StyledButton>Click Me&#x3C;/StyledButton>
    &#x3C;/div>
  );
}
</code></pre>
<h3>Linaria</h3>
<p>自定义 <strong>功能类</strong> 的 CSS in js 方案，同时也支持 <strong>组件化</strong> 写法。生成的是完全静态的 css，样式值的复用靠变量，片段的复用靠 <code>css</code> 生成的类。</p>
<p><strong>优点</strong>：</p>
<p>是预构建方案，在服务端渲染。和原始的 CSS 写法和思路差不多。</p>
<p><strong>缺点</strong>：</p>
<ol>
<li>
<p>值复用靠变量，但是由于是 <strong>静态 css</strong>，这个并不会变。所以变量插值<strong>其实是常量</strong>。比如下面的 font-size 并不会变化。</p>
<pre><code class="language-jsx">const fontSize = 16;
const Title = styled.h1`
  font-size: ${fontSize}px;
`
</code></pre>
<p>也就是说，你如果想在客户端随意改变字体，用 context/zustand 这种 runtime 的 fontSize，这样写报错。不过，Linaria 允许你借助 react 的 props 和 <code>styled</code> 组件来实现客户端的值变化。</p>
<pre><code class="language-jsx">const Title = styled.h1`
  font-size: ${props => props.size}px;
`
export default function MyComponent() {
  const fontSize = useAppStore(state => state.fontSize)
  return &#x3C;Title fontSize={fontSize}>Hello&#x3C;/Title>
}
</code></pre>
<p>相当于生成</p>
<pre><code class="language-jsx">&#x3C;h1
  className="_title_xyz"
  style={{ '--linaria-font-size': `${size}px` }}
>
</code></pre>
<p>那这和 styled-components 写起来已经差不多了。而且要做主题化的值都得用快要废弃的 <code>useContext</code> API。只不过 linaria 改的 style 属性，styled 是改的 css  API。改 style 属性其实已经不能算静态了。</p>
</li>
<li>
<p>组件间的<strong>样式复用方案</strong>只有原生的 CSS 方案，上述的奇妙客户端插值做不了这个需求。假设，你要做一个主题化的对话框的卡片阴影，只能使用原生 css 类中加原生 css 变量。上述动态改变样式的因为依赖 props，只能使用 <code>styled</code> 的写法，但这样就会把 html 标签了也继承了，不同的样式也无法随意组合。这也是为什么我说 Linaria 是原生 css 的替代，而不是 styled-components 的替代，构建方式就决定他们差得太了远。</p>
</li>
<li>
<p>基于2，导致你写组件又要检查 <code>styled</code> 又要确认 <code>css</code> 类又要检查 JSX classname 的顺序。如果用组件继承会被迫连 DOM 类型都继承。</p>
</li>
<li>
<p>使用功能类有点像原子化，又完全不如 tailwind 已经给你预设好一堆东西的效率。写类名和 cssmodule 一样，太磨叽了</p>
</li>
</ol>
<p>我博客本想迁移至此方案，但由于工作量实在巨大而放弃。linaria 主要还是解决了个命名空间冲突的问题，想用得更深入一点就会四不像。</p>
<pre><code class="language-jsx">import { css } from '@linaria/core';

const eleStyle = css`
  color: red;
  font-size: 3rem;
  &#x26;:hover {
    color: blue;
  }
`;

function App() {
  return &#x3C;h1 className={eleStyle}>Hello Linaria!&#x3C;/h1>;
}

export default App;
</code></pre>
<h2>构建组建库</h2>
<p>每一个 CSS 方案都有对应的构建组件库的实践。 <a href="https://github.com/shadcn-ui/ui">shadcn</a> 是基于 tailwind 构建组件库实践。</p>
<h2>CSS 框架选择要素</h2>
<ol>
<li>样式复用</li>
<li>样式组合</li>
<li>动态样式</li>
<li>主题切换</li>
<li>代码提示</li>
<li>自动裁剪</li>
<li>随意重构</li>
<li>渲染性能</li>
<li>实践的统一性</li>
</ol>
<p>最重要的还是自己的需求。</p>]]></content:encoded>
            <category domain="https://sansui233.com/categories/学习">学习</category>
        </item>
    </channel>
</rss>