样式#
全局的配色、字体、间距和圆角先看 Themes(英文)。下面这些修饰符是针对单个对象覆盖主题的。
内容命令和底层组件都返回构建器,每个修饰符也返回同一个构建器,所以可以一直链下去:
text("Important")
.size(pt(30))
.bold()
.color("#38bdf8")
.margin(12, 0);
全局排版#
想保留主题的配色和布局、但换一套字体默认值时,用 presentation() 的 font 选项:
presentation({
title: "My Slides",
theme: "minimal-academic",
font: {
family: '"Noto Sans SC", sans-serif',
size: 24,
weight: 400,
lineHeight: 1.5,
heading: {
family: '"Noto Serif SC", serif',
size: 40,
weight: 700,
},
code: {
family: '"JetBrains Mono", monospace',
size: 18,
},
},
});
size 处的数字是像素。也接受长度助手和 CSS 字符串,比如 pt(20)、"1.5rem"、"24px"。lineHeight 可以是无单位数字或 CSS 字符串。
优先级是:单个对象的修饰符或 .style() 值 > presentation.font > 所选主题。顶层的 family 同时作用于正文和标题;代码保持主题的等宽字族,除非设置了 code.family。
中文、日文、韩文默认可用:每套内置主题的字族链末尾都带 CJK 回退,详见 Themes(英文)。
长度与单位#
数字按像素解释:
text("Pixels").size(24);
需要显式单位时用助手函数:
px(20)
pt(20)
rem(2)
percent(50)
vw(40)
vh(30)
它们返回 CSS 长度字符串,任何接受 Length 的地方都能用。
尺寸与间距#
.width(640)
.height(percent(100))
.minWidth(200)
.minHeight(120)
.maxWidth(720)
.maxHeight(400)
.padding(24)
.padding(16, 24) // 纵向, 横向
.padding({ top: 8, left: 16 }) // 单独设置某几边
.margin(12)
.margin(8, 16) // 纵向, 横向
.margin({ bottom: 24 }) // 单独设置某几边
.gap(20)
.gap(12, 40) // 先行间距,后列间距
maxWidth() 是把一段正文限制在易读行宽内的办法。padding() 和 margin() 的对象形式里,没写的边是 0——和 CSS 简写一样:padding({ top: 8 }) 会把其余三边设为 0,而不是保持不变。
外观#
.background("#0f172a")
.color("#f8fafc")
.border("1px solid #334155")
.radius(16)
.opacity(0.8)
字体#
.size(pt(28))
.fontSize(pt(28))
.weight(600)
.fontWeight(600)
.bold()
.lineHeight(1.4)
.textAlign("center")
size() 是 fontSize() 的别名,weight() 是 fontWeight() 的别名。
文字角色提供带语义的默认值:
.body()
.title()
.hero()
.subtitle()
.author()
.eyebrow()
.lead()
.caption()
.quote()
这些角色可用于小写的 text() 命令返回的对象。
弹性布局#
下面这些修饰符每个对象都能调用,但它们是被布局的不同部分回答的。这三类作用于对象自己的子对象,所以需要它本身是行、列或网格:
.row()
.column()
.stack()
.grid(3)
.center()
.align("center")
.justify("space-between")
.wrap()
.alignContent("center")
另外这几个描述的是这个对象在容器里怎么摆,所以需要那个容器是行、列或网格:
.selfAlign("center")
.centerSelf()
.grow()
align()、selfAlign()、alignContent() 接受 "start"、"center"、"end"、"stretch";justify() 接受 "start"、"center"、"end"、"space-between"、"space-around"、"space-evenly",alignContent() 也接受这些分布方式,并且只有开了 wrap() 才有意义。
align() 和 selfAlign() 作用在横跨区域的方向——列里是水平,行里是垂直——而 justify() 作用在沿着区域的方向。完整对照表见各个修饰符动的是哪根轴;只居中一个对象而不是整个区域,见只让一个对象居中。
对象默认在交叉轴上拉伸,所以只有当它自己有尺寸时 selfAlign() 才会让它移动——在列里是 width(),在行里是 height()。
修饰符落到不可能生效的地方时,浏览器会一声不响地忽略它。frameseq check 会把这类问题报成 inert-modifier,而不是让渲染结果和源码悄悄对不上。
定位与变换#
.position({ x: 80, y: 120 })
.anchor("center")
.rotate(-4)
position() 使用绝对定位,面向画布或其它刻意定位过的父容器。anchor() 则相对于父容器摆放,不用写坐标 —— 见 Diagrams(英文)。
要在普通流式布局里放一个定位区域,给容器起个名字并把它变成局部画布:
at("panel").canvas().width(600).height(260).clip();
text("Local coordinates").position({ x: 32, y: 24 });
写在 at("panel") 之后的对象都属于这个容器。它的 .canvas() 让子对象的坐标变成局部的,.clip() 把它们裁在面板内;.clip(false) 可恢复溢出可见。
渐进揭示#
text("Appears first").showAt(1);
text("Appears second").showAt(2);
揭示序号从 1 开始。PDF 和打印模式下所有步骤都可见。
Tailwind CSS#
Tailwind 工具类是内置的,不需要任何配置。把工具类字符串传给 style():
text("A strong statement")
.style("text-4xl font-bold tracking-tight text-blue-600");
text("Precisely placed")
.style("absolute left-[80px] top-[120px] w-[640px]");
支持 text-[30px]、bg-[#0f172a]、grid-cols-[2fr_3fr] 这类任意值。动态选择的工具类要保持为完整字符串,Tailwind 才能扫描到:
const emphasis = important ? "text-red-600" : "text-slate-500";
text("Status").style(emphasis);
不要用 `text-${color}-600` 这种拼接写法 —— 完整的类名没有出现在源码里,Tailwind 找不到它。
内联 CSS 与类名#
对象形式仍然可以写内联 CSS:
text("Custom")
.className("my-callout")
.style({
letterSpacing: "0.08em",
textTransform: "uppercase",
});
传给 style() 的属性名用 JavaScript 风格,比如 letterSpacing。
内联属性的优先级高于 Tailwind 工具类,与调用顺序无关。 只想附加类名、不想用 style() 简写时,用 className()。