[{"data":1,"prerenderedAt":274},["ShallowReactive",2],{"article-css-grid-cards":3,"related-articles":173},{"id":4,"title":5,"body":6,"categoryLabel":158,"categorySlug":159,"description":160,"extension":161,"featured":162,"meta":163,"navigation":162,"path":164,"publishedAt":165,"readingMinutes":115,"seo":166,"stem":167,"tags":168,"__hash__":172},"blog\u002Fblog\u002Fcss-grid-cards.md","用 CSS Grid 排列自适应卡片",{"type":7,"value":8,"toc":153},"minimark",[9,13,18,133,136,139,142,146,149],[10,11,12],"p",{},"文章列表和项目卡片经常需要多列布局。CSS Grid 可以根据容器宽度自动调整列数，减少手写多个断点的工作。",[14,15,17],"h2",{"id":16},"使用-minmax-设置列宽范围","使用 minmax 设置列宽范围",[19,20,25],"pre",{"className":21,"code":22,"language":23,"meta":24,"style":24},"language-css shiki shiki-themes github-light-high-contrast",".card-grid {\n  display: grid;\n  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));\n  gap: 1rem;\n}\n","css","",[26,27,28,41,56,113,127],"code",{"__ignoreMap":24},[29,30,33,37],"span",{"class":31,"line":32},"line",1,[29,34,36],{"class":35},"sacAq",".card-grid",[29,38,40],{"class":39},"sigWx"," {\n",[29,42,44,47,50,53],{"class":31,"line":43},2,[29,45,46],{"class":35},"  display",[29,48,49],{"class":39},": ",[29,51,52],{"class":35},"grid",[29,54,55],{"class":39},";\n",[29,57,59,62,64,67,70,73,76,79,81,84,86,89,93,95,98,101,104,107,110],{"class":31,"line":58},3,[29,60,61],{"class":35},"  grid-template-columns",[29,63,49],{"class":39},[29,65,66],{"class":35},"repeat",[29,68,69],{"class":39},"(",[29,71,72],{"class":35},"auto-fit",[29,74,75],{"class":39},", ",[29,77,78],{"class":35},"minmax",[29,80,69],{"class":39},[29,82,83],{"class":35},"min",[29,85,69],{"class":39},[29,87,88],{"class":35},"100",[29,90,92],{"class":91},"sTJeM","%",[29,94,75],{"class":39},[29,96,97],{"class":35},"15",[29,99,100],{"class":91},"rem",[29,102,103],{"class":39},"), ",[29,105,106],{"class":35},"1",[29,108,109],{"class":91},"fr",[29,111,112],{"class":39},"));\n",[29,114,116,119,121,123,125],{"class":31,"line":115},4,[29,117,118],{"class":35},"  gap",[29,120,49],{"class":39},[29,122,106],{"class":35},[29,124,100],{"class":91},[29,126,55],{"class":39},[29,128,130],{"class":31,"line":129},5,[29,131,132],{"class":39},"}\n",[10,134,135],{},"每列至少需要约 15rem 的宽度，空间充足时平分剩余区域；容器变窄时，列数会自动减少。",[14,137,138],{"id":138},"检查内容变化",[10,140,141],{},"布局测试时不要只看相同长度的标题。把较长标题、空描述和较窄视口也放进页面，确认卡片高度与阅读顺序仍然清楚。",[14,143,145],{"id":144},"什么时候用-flexbox","什么时候用 Flexbox",[10,147,148],{},"单行导航、按钮组等一维排列常用 Flexbox；需要同时控制行和列时，Grid 通常更直接。两者可以按布局关系组合使用。",[150,151,152],"style",{},"html pre.shiki code .sacAq, html code.shiki .sacAq{--shiki-default:#023B95}html pre.shiki code .sigWx, html code.shiki .sigWx{--shiki-default:#0E1116}html pre.shiki code .sTJeM, html code.shiki .sTJeM{--shiki-default:#A0111F}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":24,"searchDepth":43,"depth":43,"links":154},[155,156,157],{"id":16,"depth":43,"text":17},{"id":138,"depth":43,"text":138},{"id":144,"depth":43,"text":145},"页面与样式","styles","使用 repeat、minmax 和 auto-fit，让卡片列数随容器宽度自然变化。","md",true,{},"\u002Fblog\u002Fcss-grid-cards","2026-09-10",{"title":5,"description":160},"blog\u002Fcss-grid-cards",[169,170,171],"CSS","Grid","页面布局","_NYe3e0KKuvyN2ONpU2-fC2aYtnZsfUZI8sgm9Z8Nlo",[174,176,186,198,206,214,222,230,238,248,256,264],{"id":4,"path":164,"title":5,"description":160,"categorySlug":159,"categoryLabel":158,"publishedAt":165,"readingMinutes":115,"featured":162,"tags":175},[169,170,171],{"id":177,"path":178,"title":179,"description":180,"categorySlug":159,"categoryLabel":158,"publishedAt":181,"readingMinutes":129,"featured":182,"tags":183},"blog\u002Fblog\u002Fmobile-layout-checklist.md","\u002Fblog\u002Fmobile-layout-checklist","做移动端页面适配时的检查笔记","从内容宽度、触控区域、文字换行和键盘焦点几个方面检查窄屏体验。","2026-08-20",false,[169,184,185],"响应式","可访问性",{"id":187,"path":188,"title":189,"description":190,"categorySlug":191,"categoryLabel":192,"publishedAt":193,"readingMinutes":194,"featured":162,"tags":195},"blog\u002Fblog\u002Freact-controlled-form.md","\u002Fblog\u002Freact-controlled-form","React 受控表单：从一个输入框开始","用一个简单的姓名输入框，理解 value、onChange 与 React state 之间的关系。","react","React","2026-09-18",6,[192,196,197],"表单","学习笔记",{"id":199,"path":200,"title":201,"description":202,"categorySlug":191,"categoryLabel":192,"publishedAt":203,"readingMinutes":115,"featured":182,"tags":204},"blog\u002Fblog\u002Freact-list-keys.md","\u002Fblog\u002Freact-list-keys","React 列表渲染里的 key 有什么用","通过稳定的 key 帮助 React 识别列表项目，避免用数组下标造成的状态错位。","2026-08-12",[192,205,197],"列表",{"id":207,"path":208,"title":209,"description":210,"categorySlug":191,"categoryLabel":192,"publishedAt":211,"readingMinutes":129,"featured":182,"tags":212},"blog\u002Fblog\u002Freact-props-and-state.md","\u002Fblog\u002Freact-props-and-state","React 组件里的 Props 和 State","用一个简单的信息卡片区分外部传入的数据和组件内部会变化的数据。","2026-08-28",[192,213,197],"组件",{"id":215,"path":216,"title":217,"description":218,"categorySlug":191,"categoryLabel":192,"publishedAt":219,"readingMinutes":129,"featured":182,"tags":220},"blog\u002Fblog\u002Freact-small-components.md","\u002Fblog\u002Freact-small-components","把重复的界面拆成小组件","从重复的按钮和卡片开始，认识组件拆分的几个简单信号。","2026-07-16",[192,213,221],"练习记录",{"id":223,"path":224,"title":225,"description":226,"categorySlug":191,"categoryLabel":192,"publishedAt":227,"readingMinutes":194,"featured":182,"tags":228},"blog\u002Fblog\u002Freact-use-effect-notes.md","\u002Fblog\u002Freact-use-effect-notes","React useEffect 的依赖和清理","整理 useEffect 何时运行，以及订阅和定时器为什么需要清理。","2026-06-30",[192,229,197],"useEffect",{"id":231,"path":232,"title":233,"description":234,"categorySlug":191,"categoryLabel":192,"publishedAt":235,"readingMinutes":115,"featured":182,"tags":236},"blog\u002Fblog\u002Freact-use-state-practice.md","\u002Fblog\u002Freact-use-state-practice","用 useState 管理一个简单的计数交互","从加一和重置两个操作，熟悉 React state 的声明与更新方式。","2026-07-30",[192,237,221],"useState",{"id":239,"path":240,"title":241,"description":242,"categorySlug":243,"categoryLabel":244,"publishedAt":245,"readingMinutes":129,"featured":162,"tags":246},"blog\u002Fblog\u002Ftypescript-component-props.md","\u002Fblog\u002Ftypescript-component-props","给 React 组件的 Props 添加 TypeScript 类型","用必填属性和可选属性描述组件接口，让使用方式在编辑器里更清晰。","typescript","TypeScript","2026-09-02",[244,192,247],"类型",{"id":249,"path":250,"title":251,"description":252,"categorySlug":243,"categoryLabel":244,"publishedAt":253,"readingMinutes":129,"featured":162,"tags":254},"blog\u002Fblog\u002Ftypescript-narrowing.md","\u002Fblog\u002Ftypescript-narrowing","TypeScript 类型收窄入门","使用 typeof 和条件判断缩小联合类型的范围，让后续代码更安全。","2026-09-25",[244,255,197],"类型收窄",{"id":257,"path":258,"title":259,"description":260,"categorySlug":243,"categoryLabel":244,"publishedAt":261,"readingMinutes":115,"featured":182,"tags":262},"blog\u002Fblog\u002Ftypescript-union-status.md","\u002Fblog\u002Ftypescript-union-status","用联合类型描述请求状态","把加载、成功和失败等状态限制在明确的集合里，减少拼写错误和遗漏分支。","2026-08-04",[244,263,197],"联合类型",{"id":265,"path":266,"title":267,"description":268,"categorySlug":269,"categoryLabel":270,"publishedAt":271,"readingMinutes":115,"featured":182,"tags":272},"blog\u002Fblog\u002Fvite-react-project.md","\u002Fblog\u002Fvite-react-project","用 Vite 创建一个 React + TypeScript 小项目","记录从初始化模板到启动开发服务器的基础步骤，以及几个值得先检查的文件。","tools","开发工具","2026-06-12",[273,192,244],"Vite",1792674168119]