Grid 布局¶
本教程涵盖 LatticeSVG 中 CSS Grid 布局的各种技巧,从基础到高级。
固定轨道¶
最简单的网格——指定固定像素宽度:
from latticesvg import GridContainer, TextNode, Renderer
grid = GridContainer(style={
"width": "500px",
"padding": "16px",
"grid-template-columns": ["200px", "280px"],
"gap": "12px",
"background-color": "#f5f5f5",
})
grid.add(TextNode("200px 宽", style={"background-color": "#e3f2fd", "padding": "12px"}))
grid.add(TextNode("280px 宽", style={"background-color": "#fce4ec", "padding": "12px"}))
Renderer().render(grid, "fixed_grid.svg")
弹性单位 fr¶
fr 单位按比例分配剩余空间:
grid = GridContainer(style={
"width": "600px",
"padding": "16px",
"grid-template-columns": ["1fr", "2fr", "1fr"], # 1:2:1 比例
"gap": "12px",
})
混合轨道¶
固定宽度与弹性单位混用:
grid = GridContainer(style={
"width": "800px",
"padding": "16px",
"grid-template-columns": ["240px", "1fr"], # 固定侧边栏 + 弹性主区域
"gap": "24px",
})
经典侧边栏布局
["240px", "1fr"] 是最常见的侧边栏布局模式,也可以使用内置模板
templates.SIDEBAR_LAYOUT。
自动放置¶
不指定 row/col 时,子节点按照 grid-auto-flow 自动放置:
grid = GridContainer(style={
"width": "600px",
"grid-template-columns": ["1fr", "1fr", "1fr"],
"gap": "8px",
"padding": "16px",
})
# 自动按行填充:第 1 行 3 个,第 2 行 2 个
for i in range(5):
grid.add(TextNode(f"项目 {i+1}", style={
"padding": "12px",
"background-color": "#e8eaf6",
"text-align": "center",
}))
跨行跨列¶
使用 row_span 和 col_span 让元素跨越多个轨道:
grid = GridContainer(style={
"width": "500px",
"grid-template-columns": ["1fr", "1fr", "1fr"],
"grid-template-rows": ["auto", "auto", "auto"],
"gap": "8px",
"padding": "16px",
})
# 跨 2 列
grid.add(TextNode("跨 2 列", style={
"background-color": "#bbdefb",
"padding": "16px",
"text-align": "center",
}), row=1, col=1, col_span=2)
# 跨 2 行
grid.add(TextNode("跨 2 行", style={
"background-color": "#c8e6c9",
"padding": "16px",
"text-align": "center",
}), row=1, col=3, row_span=2)
grid.add(TextNode("普通", style={
"background-color": "#fff9c4",
"padding": "16px",
}), row=2, col=1)
grid.add(TextNode("普通", style={
"background-color": "#ffccbc",
"padding": "16px",
}), row=2, col=2)
命名区域¶
使用 grid-template-areas 定义命名区域,用 area 参数放置子节点:
grid = GridContainer(style={
"width": "600px",
"padding": "16px",
"grid-template-columns": ["200px", "1fr"],
"grid-template-rows": ["auto", "1fr", "auto"],
"grid-template-areas": '"header header" "sidebar main" "footer footer"',
"gap": "8px",
})
grid.add(TextNode("页眉", style={
"background-color": "#2c3e50",
"color": "#fff",
"padding": "16px",
}), area="header")
grid.add(TextNode("侧边栏", style={
"background-color": "#ecf0f1",
"padding": "16px",
}), area="sidebar")
grid.add(TextNode("主内容", style={
"background-color": "#ffffff",
"padding": "16px",
}), area="main")
grid.add(TextNode("页脚", style={
"background-color": "#34495e",
"color": "#ecf0f1",
"padding": "12px",
"text-align": "center",
}), area="footer")
对齐控制¶
容器级对齐¶
justify-items— 水平对齐所有子项(start|center|end|stretch)align-items— 垂直对齐所有子项
子项级对齐¶
justify-self— 覆盖单个子项的水平对齐align-self— 覆盖单个子项的垂直对齐
grid = GridContainer(style={
"width": "400px",
"grid-template-columns": ["1fr", "1fr"],
"gap": "12px",
"padding": "16px",
"justify-items": "center", # 所有子项水平居中
"align-items": "center", # 所有子项垂直居中
})
repeat() 和 minmax()¶
使用 repeat() 简化重复轨道定义,minmax() 设置轨道尺寸范围:
grid = GridContainer(style={
"width": "800px",
"padding": "16px",
# repeat(3, minmax(150px, 1fr)) → 3 列,每列最少 150px
"grid-template-columns": "repeat(3, minmax(150px, 1fr))",
"gap": "12px",
})
自动轨道¶
当子节点超出显式定义的轨道时,grid-auto-rows 和 grid-auto-columns 控制隐式轨道的大小:
grid = GridContainer(style={
"width": "400px",
"grid-template-columns": ["1fr", "1fr"],
# 只定义了列,行由自动轨道控制
"grid-auto-rows": "80px", # 每行固定 80px
"gap": "8px",
"padding": "16px",
})
# 添加 6 个元素 → 自动创建 3 行 × 2 列
for i in range(6):
grid.add(TextNode(f"单元格 {i+1}", style={
"background-color": "#e0f7fa",
"padding": "8px",
"text-align": "center",
}))
嵌套网格¶
GridContainer 可以作为另一个 GridContainer 的子节点:
outer = GridContainer(style={
"width": "800px",
"padding": "24px",
"grid-template-columns": ["1fr", "1fr"],
"gap": "16px",
})
# 左侧卡片(也是一个 Grid)
left_card = GridContainer(style={
"padding": "16px",
"background-color": "#ffffff",
"border": "1px solid #e0e0e0",
"grid-template-columns": ["1fr"],
"gap": "8px",
})
left_card.add(TextNode("卡片标题", style={"font-weight": "bold"}))
left_card.add(TextNode("卡片内容"))
outer.add(left_card)
justify-content 间距¶
利用 column-gap 和 row-gap 独立控制行列间距:
grid = GridContainer(style={
"width": "600px",
"grid-template-columns": ["1fr", "1fr", "1fr"],
"column-gap": "24px", # 列间距
"row-gap": "8px", # 行间距
"padding": "16px",
})
简写属性
gap 是 row-gap 和 column-gap 的简写。"gap": "8px 24px" 等同于
"row-gap": "8px" + "column-gap": "24px"。