在折腾完双仓分离架构后,我本以为博客的建设大业已经完成,直到我点开文章列表的「网格模式(Grid)」。
满屏的卡片高低错落、无图卡片矮一截、长标题直接把卡片撑爆……这对于强迫症来说简直是灾难。
这篇文章记录了我对 Shirone 主题 PostCard.astro 和 PostMeta.astro 组件的深度调教,一步步实现“三列等高完美网格”和“列表模式高级虚化”的全过程。
🧱 第一阶段:为什么我的网格只有两列?
Shirone 的网格布局是基于 CSS Grid 和容器查询(@container)实现的。默认情况下,如果你用的是 regular 档位,容器宽度必须达到 49rem(约 784px) 才会激活两列。如果你用的是 compact 档位,也需要达到 41rem(约 656px)。
如果你的主内容区因为侧边栏挤压,宽度只有 742px,就会刚好卡在 regular 的阈值下方,导致永远只能显示单列。
解决方案:
如果你想强行上三列,可以修改主题源码 src/config/postListConfig.ts 中的最小宽度常量:
export const POST_CARD_MIN_WIDTH = { compact: "14rem", // 默认是 20rem,改为 14rem 即可在 742px 下容纳三列 regular: "24rem", relaxed: "28rem"};同时在内容仓的 post-list.yaml 中开启 compact 模式。
📐 第二阶段:强迫症福音 —— 卡片绝对等高
激活多列后,最丑的问题来了:有封面的卡片很高,无封面的卡片很矮;标题长的文章很高,标题短的很矮。
要解决这个问题,我们需要进行三步手术。
1. 无图卡片插入“透明占位块”
在 PostCard.astro 的 HTML 中,不要用 {hasCover && ...} 来控制整个图片容器的渲染。我们应该始终渲染容器,内部用三元表达式判断:
<div class="m3-blog-postcard__cover"> {hasCover ? ( <picture> {/* 你的图片代码 */} </picture> ) : ( <div class="m3-blog-postcard__cover-placeholder"></div> )}</div>然后在 CSS 中,让它在列表模式下隐藏,网格模式下显示(利用 aspect-ratio: 16/9 撑开高度):
&__cover &-placeholder background: var(--card-bg) // 或者纯透明 width: 100% height: 100%
@media (min-width: bp-md) &:not(.m3-blog-postcard--cover) &__cover display: none // 列表模式隐藏占位块
grid-card-layout(shell-selector) :global({shell-selector} .m3e-post-list--grid) &:not(.m3-blog-postcard--cover) &__cover display: block // 网格模式强制显示2. 强制文本截断( -webkit-line-clamp )
为了防止长标题和长标签把卡片撑爆,必须在 PostCard.astro 中限制它们的行数。
- 标签行:
display: -webkit-box; -webkit-line-clamp: 2; overflow: hidden; - 简介行:
display: -webkit-box; -webkit-line-clamp: 2; overflow: hidden; - 标题:因为标题是用
<a>包裹的flex布局(为了让右侧箭头对齐),直接加截断会失效。所以我们在标题文字外面套一层<span class="m3-blog-postcard__title-text">,只对文字进行截断。
3. 锁死卡片物理高度
最后,在 grid-card-layout 宏里,给最外层的卡片加上固定高度(比如 365px),并切断溢出:
grid-card-layout(shell-selector) :global({shell-selector} .m3e-post-list--grid) & flex-direction: column-reverse height: 365px // 绝对高度 overflow: hidden // 超出部分物理切断⚓ 第三阶段:底部信息的“推底”设计
默认的日期、字数、阅读时间混在元数据里。为了实现强迫症对齐,我在 PostCard.astro 的 HTML 里把手写了底部信息行:
<div class="m3-blog-postcard__footer"> <span class="m3-blog-postcard__footer-item"> <Icon name="material-symbols:calendar-today-outline-rounded" /> {published} </span> <span class="m3-blog-postcard__footer-divider">|</span> <span class="m3-blog-postcard__footer-item"> <Icon name="material-symbols:article-outline-rounded" /> {wordCount} </span></div>配合 __body 的 flex 布局,让它永远贴着底边:
&__body display: flex flex-direction: column
&__footer margin-top: auto // 核心:吃掉中间所有多余的高度 padding-top: var(--m3e-space-2) font-size: 0.85rem🪄 第四阶段:列表模式的图片“高级感”
网格模式解决后,列表模式(List)的右侧封面也有讲究。我想实现:平时左侧虚化融合,悬停时放大且边缘变清晰。
注意:绝对不要加 pointer-events: none,否则 :hover 无法触发。
&__cover > picture > img transition: transform 0.4s cubic-bezier(0.2, 0, 0, 1)
// 悬停放大 .m3-blog-postcard:hover & > picture > img transform: scale(1.05)
@media (min-width: bp-md) position: absolute top: 0 right: 0 bottom: 0 width: 32%
// 默认渐变虚化 mask-image: linear-gradient(to right, transparent 0%, black 30%) -webkit-mask-image: linear-gradient(to right, transparent 0%, black 30%) transition: mask-image 0.4s ease
// 悬停时清晰 .m3-blog-postcard:hover & mask-image: linear-gradient(to right, transparent 0%, black 5%) -webkit-mask-image: linear-gradient(to right, transparent 0%, black 5%)同时,在网格模式下,必须使用 mask-image: none !important 强制取消虚化,保证网格图片边缘干净利落。
总结
经过这一番改造,PostCard.astro 不再是一个简单的展示组件,而是一个精密的布局机器。虽然代码量增加了不少,但最终呈现的视觉效果——整齐划一的等高网格和丝滑的虚化悬停,绝对对得起这几天的折腾。
如果你也受够了排版错乱,不妨对着上面的代码试试看!
分享文章
生成精美分享图或复制链接,与更多人分享本文。
继续阅读
换条路线
从其他文章中稳定抽取
最后更新于 ,距今已过 6 天
部分内容可能已过时