飞书文档风格的 Obsidian 宽表格:初始态与正文栏对齐,宽表向右浮出正文栏;横向滚动时列滑进两侧出血区,滚到底两侧收齐;边缘用柔和阴影提示「这边还有内容」。窄表完全不受影响。
Feishu/Lark-style wide tables for Obsidian: tables start aligned with the text column, float out into the pane's margins as you scroll, and show soft edge shadows as scroll hints. Narrow tables are untouched. The README below explains the full mechanism — feel free to feed it to your agent and reimplement it your way.
Obsidian 默认把表格硬塞进正文可读行宽:列被挤压、inline code 被拦腰折行、日期折成三行。飞书文档的答案是让表格「浮」在正文之上——先尽量展示内容,实在放不下才滚动。这个插件把那套行为搬进 Obsidian,纯 CSS 实现,不改 DOM、不监听事件、零性能开销,reading view 和 live preview 行为一致。
- 安装 BRAT 插件
- BRAT 设置 →
Add beta plugin→ 填本仓库地址 - 在设置里启用 Float Tables
设置项四个:总开关、边缘留白(默认 2em)、长文案列封顶宽(默认 34em,超过则换行)、滚动阴影浓度(0 关闭)。
核心是三个 CSS 机制的叠加,没有一行 JS 参与布局(main.js 只做设置面板和写 CSS 变量)。完整样式见 styles.css,可以直接抄成 snippet 用,不装插件也行。
表格的包装元素(reading view 的 .el-table、live preview 的 .cm-table-widget)的包含块是正文栏(受 readable line width 约束,100% ≈ 700px),但我们要浮出到整个编辑面板。Container query 解决取宽问题:
.markdown-preview-view,
.markdown-source-view.mod-cm6 {
container-type: inline-size;
}之后后代样式里的 100cqw 就是面板宽度,100% 是正文栏宽度——两个基准同时可用。
.el-table, .cm-table-widget {
--ft-bleed: max(0px, calc((100cqw - 100%) / 2 - 2em));
margin-inline: calc(0px - var(--ft-bleed)) !important;
padding-inline: var(--ft-bleed);
overflow-x: auto;
}- 负
margin-inline把滚动视口扩到面板出血区(两侧各留 2em) - 等量正
padding-inline把内容起点拉回正文栏左缘——所以初始态首列精确对齐正文;滚动时列滑进左侧出血区;由于尾部 padding 参与滚动溢出,滚到底时尾列同样收在对齐位 - 窄表:内容不溢出 → 不滚动 → padding 让它呆在原地,视觉零变化。不需要 JS 测量「表格是否溢出」,几何本身就是自适应的
!important是必要的:Obsidian 自带.cm-embed-block { margin-inline: -16px },优先级压过普通选择器(这是踩坑实测,别删)
background:
linear-gradient(90deg, var(--background-primary) 30%, transparent) left/32px 100%,
linear-gradient(270deg, var(--background-primary) 30%, transparent) right/32px 100%,
radial-gradient(farthest-side at 0 50%, rgba(0,0,0,.08), transparent) left/10px 100%,
radial-gradient(farthest-side at 100% 50%, rgba(0,0,0,.08), transparent) right/10px 100%;
background-repeat: no-repeat;
background-attachment: local, local, scroll, scroll;两层「遮罩」渐变(用页面背景色)attach 为 local,跟内容一起滚;两层阴影 attach 为 scroll,钉在视口边缘。哪一侧滚到头,遮罩就盖住那一侧的阴影——阴影只在「这边还有隐藏内容」时出现。这是 Lea Verou 的经典技巧,表格单元格背景透明所以直接可用。
table { width: max-content; max-width: none; } /* 列取自然宽度,不被挤压 */
td { max-width: 34em; } /* 长文案列封顶换行 */
td code { white-space: nowrap; } /* code token 永不拦腰折断 */没有这一段,表格永远不会比正文栏宽,前面的一切都不会触发。
- Obsidian reading view 和 live preview 是两套完全不同的 DOM。选择器必须成对写:
.markdown-rendered .el-table配.markdown-source-view.mod-cm6 .cm-table-widget - Live preview 的表格 widget 同时带有
.markdown-renderedclass,所以td/code级规则写.markdown-rendered一份即可覆盖两侧,但 wrapper 级(margin/padding)必须分开写 - 验证对齐别靠肉眼:DevTools 里量
table.getBoundingClientRect().left - content.getBoundingClientRect().left,等于 0 才算对齐
- 需要 Obsidian ≥ 1.6(container queries +
.el-tableDOM) - 「Readable line length」关闭时正文栏 ≈ 面板宽,浮出量自然趋近于 0,行为退化为普通横滚,符合直觉
- 只处理表格。代码块 / Mermaid / 图片的浮出是同一套几何,抄
styles.css换选择器即可——这正是把原理写清楚的意义
MIT。随便用,随便改,不用告诉我。
