十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Jupyter Notebook 插图指南:尺寸、对齐、路径与导出

Jupyter Notebook 插图指南:尺寸、对齐、路径与导出 第一次在 Notebook 里贴图多数人都会先敲下![](./figs/result.png)图是出来了但一张 4000 像素宽的实验截图直接铺满整个页面把周围的文字和代码挤得七零八落。等你回过头想把它缩到一半、再往中间挪一挪才发现标准 Markdown 的图片语法里压根就没有尺寸和对齐这两个参数。这不是你语法记错了而是这套语法从设计之初就没打算管排版——它的定位是把图放进来不是把图摆好看。要把图摆好看就得换几条路走。这篇内容把在 Jupyter Notebook 里插图的几条路线拆开讲清楚每条路分别能控制什么、尺寸和对齐该怎么写才不会在不同环境下翻车、路径为什么会莫名其妙失效、导出成 HTML 和 PDF 时图去哪了以及并排图、图注、样式复用这些真正做报告时才需要的排版手法。不管你是刚装完 Jupyter 的新手还是已经在用 Notebook 写实验记录、数据分析报告、教学课件的老手下面这些写法都能直接抄走用。1. 标准 Markdown 语法的能力上限在哪1.1 感叹号语法只有一个参数标准 Markdown 的图片语法长这样![替代文字](图片路径)。方括号里是替代文字圆括号里是路径就这两样再无其他。你想加个尺寸写![图](a.png 500)不认。写![图](a.png){width500}那是 Pandoc 的扩展语法Jupyter 的解析器也不认。想加个对齐写![图](a.png center)那个引号位置是给 title 属性用的只会变成鼠标悬停提示跟对齐没有任何关系。所以第一件要接受的事是在标准 Markdown 语法里尺寸和对齐这两个需求从根本上就无处安放。这不是有个隐藏参数你没找到而是语法层面就没有位置留给它。你想控制外观必须借助下面的渲染链路绕出去。1.2 Markdown 单元格最终变成了什么理解这条路的关键是想清楚 Notebook 里一个标记单元格到底被谁渲染。链路其实很短你写的 Markdown 文本 → 被解析器转成 HTML 片段 → 塞进页面的 DOM 里由浏览器渲染。也就是说只要能被浏览器认识的 HTML你就能直接写进标记单元格Jupyter 会把这一段原样交给浏览器。这条结论相当重要它意味着img srca.png width480能直接用因为浏览器认识img标签和width属性。div styletext-align:center.../div也能直接用因为style属性是标准的 CSS 内联写法。table、figure、span、br这些标签同样可以混在 Markdown 里写甚至能和 Markdown 语法嵌套使用缩进四空格或空行分隔比较稳妥。反过来说凡是浏览器不认识的东西写进去就是一段死文本直接显示在页面上。所以判断一个写法能不能用标准非常简单把它单独存成一个.html文件用浏览器打开能正常显示那在 Notebook 的标记单元格里基本也能正常显示。1.3 四条插入路线各自能管什么在动手之前先把可选路线摆清楚避免你在错误的路上反复试探。下面是四条最常用的路径的实际能力边界。路线写在哪种单元格尺寸控制对齐控制典型用途标准 Markdown 语法标记单元格不支持不支持快速预览、临时贴图HTML img 标签标记单元格width 属性 / style 宽度父容器居中、块级居中、浮动绝大多数固定排版需求IPython.display.Image代码单元格width、height 参数不支持需外层包装程序化生成、动态图片display(HTML(...))代码单元格完整 CSS 能力完整 CSS 能力数据流程里动态拼排版这张表建议先记住结论要排版就用 HTML要动态就拿 IPython.display 拼一段 HTML 出来。剩下两节分别展开这两条主线以及路径、导出这些让人抓狂的细节。2. 用 HTML img 标签一次解决尺寸和对齐2.1 最小可用写法与 width 的取值规则最省事的写法就是在标记单元格里直接写 HTMLimg src./figs/result.png width480这一行的效果是图片按 480 像素宽渲染如果原图比这个大就缩小比这个小就拉伸到 480。注意这里有个很容易被忽略的点——width属性在 HTML 规范里要求是非负整数单位是像素而且不能带px后缀。你写width480px在多数浏览器上会被忽略然后退回原图尺寸看起来就像改了没用。这个坑我踩过排查了半天才反应过来是单位写错了。如果要用百分比比如占正文宽度的 60%属性方式是靠不住的得换成内联样式img src./figs/result.png stylewidth:60%;style里的width是 CSS 层面的事接受60%、32rem、calc(100% - 40px)这类写法。凡是想用百分比、想算动态宽度、想加最大宽度限制一律走 style不要走属性。两者的适用场景区分得非常清楚固定像素用属性相对尺寸用样式。2.2 三种对齐写法与可靠性排序对齐比尺寸更容易翻车因为img标签本身没有水平居中这个属性。下面三种写法我都长期用过按可靠性从高到低排第一种父容器text-align。img默认是行内元素所以把它包在一个块级容器里让容器居中图片自然跟着居中div styletext-align:center; img src./figs/result.png width480 /div这是最稳的一种兼容性最好JupyterLab、Notebook 7、VS Code 的 Notebook 编辑器里表现一致。第二种块级 自动外边距。不想要外层容器的时候把图片本身变成块级元素img src./figs/result.png width480 styledisplay:block; margin-left:auto; margin-right:auto;写法稍长但好处是图片独占一行左右不会再有行内元素的空隙干扰垂直方向也更好控制。第三种旧式align属性。像img srca.png width480 alignright这种写法在浏览器里依然有效效果是让图片浮动到右侧、文字在左侧环绕。要提醒的是这个属性在 HTML5 里已经被标记为过时而且它的合法取值只有left、right、top、middle、bottom——没有center。很多人凭直觉写aligncenter结果就是什么也没发生。想居中老老实实回到第一种或第二种。提示如果图片要右对齐且不希望文字环绕可以用div styledisplay:flex; justify-content:flex-end;包一层这在现在的客户端里比alignright更好预期。2.3 只写一个维度的原因我在培训新人时反复强调一件事控制图片尺寸时永远只写宽度不写高度。理由很直接——图片的宽高比是固定的你只给宽度浏览器会自动按比例算出高度你同时给宽度和高度只要这两个值的比例和原图对不上图片就会被拉伸变形人像变胖、图表文字被压扁。举个具体例子。假设原图是 1600×900宽高比 16:9。你写width400浏览器自动渲染成 400×225比例正确。你写width400 height400渲染出来就是一个正方形图被纵向拉长。所以只有一种情况可以同时写宽高你确实打算把图片裁成另一个比例并且接受变形这种情况其实更适合先用图像工具裁好再来插入。顺带一个实用参数如果图片要放大显示比如一张 400px 的小图标放大到 800px放大后容易发虚可以在样式里加image-rendering: pixelated;让像素边界更硬朗反过来照片类图片放大时可以加image-rendering: auto;保持平滑。这两个参数在放大部分截图时特别有用。2.4 边框、圆角、阴影可复制的样式片段既然已经用上 HTML 了一些提升观感的小样式顺手就能加上。下面这几段是我在写实验报告时最常用的!-- 图片加细边框和浅阴影适合截图 -- img src./figs/screenshot.png width640 styleborder:1px solid #d0d7de; border-radius:6px; box-shadow:0 2px 6px rgba(0,0,0,0.08); !-- 限制最大宽度防止宽图撑破版面 -- img src./figs/wide.png stylemax-width:100%; height:auto; !-- 居中 限制最大宽度最通用的组合 -- div styletext-align:center; img src./figs/chart.png stylemax-width:80%; height:auto; /div这里重点说第二段里的max-width:100%和height:auto。这两个是防爆版面的保险丝无论原图多宽都不会超出内容区宽度同时height:auto保证缩放后比例仍然正确。我在写包含几十张图的报告时会把这两个值当成默认配置只有确实需要固定尺寸时才覆盖掉。有一个细节容易被忽略height:auto在大多数情况下是多余的因为不写 height 本身就是自动。但当你同时写了max-width又想覆盖某个继承来的高度约束时显式写出来更保险。这属于不写也行、写了更稳的一类防御性写法。3. IPython.display.Image代码单元格那条路3.1 display(Image(...)) 到底渲染出了什么标记单元格适合手写排版但有些图是算出来的——训练曲线、生成的对比图、预测结果可视化。这些图的路径只有在运行到那一步才知道就得在代码单元格里完成插入。from IPython.display import Image, display display(Image(filename./figs/curve.png, width520))这段代码的渲染结果本质上还是往单元格输出里塞了一个 HTML 的img标签只不过这个标签是 IPython 帮你生成的。这里的width520会被写进标签的width属性所以它遵循前面讲过的规则单位是像素不带后缀。想用百分比只能在外面包一层 HTML。3.2 三种数据来源的实际差别Image的构造参数看起来简单但不同来源的行为差别很大直接影响你的路径怎么写。传入方式写法路径相对谁解析会不会把图片嵌进 ipynb本地文件Image(filenamea.png)内核进程的当前工作目录会转成 base64 内嵌网络地址Image(urlhttps://.../a.png)由浏览器加载不会存的是链接字节数据Image(datapng_bytes)无路径概念会这里最需要警惕的是第一行。filename参数是在 Python 进程里读文件的所以它相对于内核的工作目录而不是相对于 notebook 文件所在的目录。这两个目录在很多情况下根本不是一个地方如果你是先cd到项目根目录再jupyter notebook那内核的工作目录通常是根目录而 notebook 文件可能躺在三层子目录里。于是同一个./figs/a.png在标记单元格里能显示在代码单元格里就报FileNotFoundError。我的做法是在写路径之前先在代码单元格里确认一次import os print(os.getcwd()) print(os.listdir(.))看到实际目录之后再用os.path.join拼路径或者干脆用一个相对 notebook 位置固定的变量from pathlib import Path fig_dir Path(figs) display(Image(filenamefig_dir / curve.png, width520))用pathlib的好处是跨平台不用操心斜杠方向Windows 上也不会因为反斜杠被当成转义字符而报错。3.3 对齐能力缺失的补齐办法Image本身没有对齐参数这一点常被抱怨。解决办法是绕开它自己拼 HTMLfrom IPython.display import HTML, display path figs/curve.png display(HTML(f div styletext-align:center; img src{path} stylewidth:70%; max-width:640px; /div ))这个写法的关键细节在于这里的src是交给浏览器解析的所以路径的相对基准又变回了 notebook 文件所在目录。也就是说同一个路径字符串用Image(filename...)和用display(HTML(...))可能会指向两个不同的位置。这个现象第一次遇到会非常困惑记住一句话就够了谁读文件路径就相对谁。Python 读文件看内核工作目录浏览器读图看 notebook 所在目录。3.4 什么时候必须放弃 ImageImage有一个明显的代价filename模式会把图片转成 base64 塞进输出结果里。一张 2MB 的截图转 base64 之后约 2.7MB如果一次循环里插入二十张notebook 文件会迅速膨胀到几十兆保存变慢、打开变卡、git diff直接卡死。所以我给自己定了一条线手动排版的成图一律用标记单元格的 HTML 写法只有图片内容每次运行都会变的场景才用代码单元格动态生成。如果动态图确实很多我会让代码先把图片存到磁盘再只输出一个相对路径的 img 标签而不是把字节数据留在输出里out Path(figs/auto) out.mkdir(parentsTrue, exist_okTrue) fpath out / fepoch_{epoch:03d}.png save_plot(fpath) display(HTML(fdiv styletext-align:center;img src{fpath.as_posix()} stylewidth:60%;/div))注意这里用了as_posix()把 Windows 的\统一换成/避免路径进 HTML 之后出问题。这个小动作在跨系统协作的仓库里非常值钱。4. 图片显示不出来的排查链路4.1 相对路径到底相对谁前面反复提到路径基准的问题这里给一个能记住的结论标记单元格里的img src...由浏览器发起请求基准是 notebook 文件所在的目录。代码单元格里的Image(filename...)由 Python 进程读取基准是内核的工作目录。代码单元格里display(HTML(img src...))又回到浏览器解析基准是 notebook 文件所在目录。导出成 HTML 之后基准变成导出的 HTML 文件所在的目录。四条规则里最后一条最容易被忘。导出后的 HTML 如果和图片不在同一个相对关系下图就全裂了。所以我习惯在项目里保持一个固定结构把 notebook 和图片放在一起project/ report.ipynb figs/ result.png导出时用jupyter nbconvert --to html report.ipynbHTML 落在同目录figs/result.png的相对关系不变图片照样能显示。4.2 中文名、空格、反斜杠这三个雷文件名里有空格img src./my fig.png会被截断成./my。要么把空格换成下划线或连字符要么把路径做 URL 编码写成./my%20fig.png。我倾向于直接改文件名省得后面每一处都要记得编码。文件名里有中文浏览器一般能正确显示但在导出、跨平台、命令行工具链比如某些 LaTeX 转换流程里容易出问题。经验是项目内的资源文件一律用 ASCII 命名中文标题写在图注里不放文件名。反斜杠路径在 Windows 上复制来的路径是figs\result.png写进 Markdown 之后\r可能被解释成回车写进 HTML 之后也基本不会按预期解析。统一改成正斜杠figs/result.png在 Windows 上照样能用。4.3 裂图的四步定位法图片显示成一个带破图标的占位框时按下面顺序走基本能在两分钟内定位。步骤操作判断依据1在代码单元格执行import os; print(os.getcwd()); print(os.listdir(figs))文件是否真的存在、内核工作目录在哪2换成绝对路径再试一次如果绝对路径能显示问题就在相对基准上3打开浏览器开发者工具的 Network 面板刷新页面看那条图片请求返回的是 404 还是 2004检查文件名大小写与扩展名服务器区分大小写.PNG和.png不是一回事第三步特别值得做一次。很多人只看页面上是裂图就以为是路径写错了其实有可能是图片太小看不出来、或者样式把width设成了 0比如width:0%或者某个继承来的max-width把它压没了。Network 面板里看到 200说明请求成功了问题就在样式看到 404问题才在路径。先分清是找不到还是看不见比盲目改路径高效得多。注意如果你把 notebook 分享给了别人对方打开看到裂图还有一种可能是图片文件没一起发过去。.ipynb文件里默认只存路径不存图片内容除非你用了附件模式。5. 并排图、图注与图组排版5.1 用 table 做两图并排对比实验最常需要两图并排。用表格是最稳的做法因为表格天然就是等分的块级容器两个单元格里的图片会各自在自己的格子里适配table stylewidth:100%; border:none; tr td stylewidth:50%; text-align:center; border:none; img src./figs/before.png stylewidth:90%; div stylefont-size:0.85em; color:#57606a;处理前/div /td td stylewidth:50%; text-align:center; border:none; img src./figs/after.png stylewidth:90%; div stylefont-size:0.85em; color:#57606a;处理后/div /td /tr /table几个细节值得解释。图片宽度给90%而不是100%是为了在两图之间留出视觉间隙不然两张图会贴在一起看起来像一张。text-align:center加在td上让图片和图注一起居中。图注用div而不是p因为p自带上下外边距会把行高撑得很难看。最后显式写上border:none因为很多主题会给表格加边框并排图加了边框很像电子表格观感不好。这套写法还有个隐性好处导出成 PDF 时表格结构通常能被保住而 flex 布局在部分转换链路里会被拍平。如果你的 notebook 最终要出 PDF这条是重要参考。5.2 flex 容器做自适应并排如果不追求对齐得像表格那么死板flex 更省事尤其在图片数量不固定的时候div styledisplay:flex; gap:12px; justify-content:center; flex-wrap:wrap; img src./figs/a.png stylewidth:30%; min-width:180px; img src./figs/b.png stylewidth:30%; min-width:180px; img src./figs/c.png stylewidth:30%; min-width:180px; /divgap负责间隙flex-wrap:wrap保证窗口变窄时自动折行min-width保证折行之后图片不会缩成一条线。写三图并排时宽度给30%加上gap的占位刚好能排满一行给33%就会因为间隙挤下去。这里有个陷阱不要把这几张图的宽度设成固定的width300那样在窄窗口下会溢出容器出现横向滚动条。响应式排版里百分比加min-width的组合几乎总是比固定像素更好用。5.3 图注的写法与序号维护图注这件事在 Notebook 里没有原生支持只能手写。但手写有个麻烦序号会在插入新图之后全乱。我用的办法是先把序号写成一个固定格式插入新图时用编辑器的全局搜索替换逐个改。图多了确实会烦所以如果报告里有十几张图我会考虑两类替代方案。一类是用 Python 生成图注。把图片清单和说明放进一个列表用循环拼 HTMLfigs [ (figs/preprocess.png, 数据预处理流程), (figs/model.png, 模型结构), (figs/result.png, 最终结果对比), ] html .join( fdiv styletext-align:center; margin:12px 0; fimg src{p} stylemax-width:80%; fdiv stylefont-size:0.85em; color:#57606a;图 {i} {c}/div f/div for i, (p, c) in enumerate(figs, 1) ) display(HTML(html))序号自动递增增删顺序改列表即可。这个脚本我用了很久写教辅材料时尤其省事。另一类是干脆接受无序号的图注只在正文里说上图展示了……。这在实验记录里完全够用正式报告再补编号。分清场景别在内部笔记上花排版的功夫。6. custom.css 与附件插入6.1 custom.css 放哪、什么时候生效如果你每个 notebook 都要写一遍同样的样式说明该把它抽出来了。经典 Notebook 支持自定义 CSS 文件位置是~/.jupyter/custom/custom.css写好之后重启服务才生效。可以在里面定义全局规则比如让所有图片默认不超过内容区宽度/* ~/.jupyter/custom/custom.css */ .jp-OutputArea-output img, .text_cell_render img { max-width: 100%; height: auto; }这两条选择器覆盖了输出区和标记单元格两个位置等于给整个 Notebook 装了一道图片不会撑破版面的保险。我强烈建议每个刚配好环境的人都加上这两行它能省掉大量图又爆了的返工。要提醒的是JupyterLab 和 Notebook 7 的样式体系跟经典 Notebook 差别很大~/.jupyter/custom/custom.css不一定被读取。如果你的环境是这两个新版本更省事的做法是在每个 notebook 的第一个单元格里写一段注入样式的代码from IPython.display import HTML, display display(HTML( style .jp-OutputArea-output img, .text_cell_render img { max-width:100%; height:auto; } /style ))这段代码只在当前 notebook 打开时生效换个环境就没了但胜在不用折腾配置文件。6.2 定义自定义类与模板复用有了全局样式表就可以定义自己的类名把冗长的内联样式收敛成一个短类.fig-center { text-align:center; margin:14px 0; } .fig-center img { max-width:80%; height:auto; border-radius:6px; } .fig-caption { font-size:0.85em; color:#57606a; margin-top:4px; }之后写图只需要三行div classfig-center img src./figs/result.png div classfig-caption图 1 不同参数下的收敛曲线/div /div这就是模板化复用的思路把位置、尺寸、间距、说明文字样式打包成一组类正文里只留内容和路径。报告改版时只改 CSS 一处几十张图的风格一起变。写长报告这个投入产出比非常高。提示在部分客户端的消毒器配置下标记单元格里的style块会被过滤掉类名就失效了。如果发现类不生效先用内联style兜底排查是不是被消毒器拦了。6.3 Edit → Insert Image 的附件模式经典 Notebook 的菜单里有 Edit → Insert Image在标记单元格上右键也能找到。这个功能的效果和前面几种都不一样它把图片base64 编码后直接写进.ipynb文件插入的语法是![替代文字](attachment:image.png)好处很明显notebook 自包含发给别人不用附带图片目录换电脑打开也不会裂图。坏处同样明显.ipynb文件体积暴涨一张高清截图能让文件从几百 KB 涨到几 MB。版本管理几乎失效。每次替换图片base64 字符串整段变化git diff里是一坨看不懂的乱码代码评审没法看。想批量替换图片非常麻烦得重新走一遍插入流程。我的取舍是临时分享、单文件交付、图片只有一两张的小 notebook用附件模式项目仓库里的正式文档一律用外链图片目录。这个判断标准很实用不用纠结。6.4 和 LaTeX 里 \includegraphics 的思路对应写过 LaTeX 或者 Overleaf 的人进 Notebook 最容易带着\includegraphics的思维结果处处碰壁。把两者的对应关系理一遍迁移成本会降很多需求LaTeX / Overleaf 写法Notebook 对应写法指定宽度\includegraphics[width0.6\textwidth]{a.png}stylewidth:60%;固定像素宽\includegraphics[width480px]{a.png}width480水平居中放进figure环境并\centering外层div加text-align:center并排两图subfigure或minipagetable两个单元格或 flex 容器图注\caption{...}自动编号手动写或用脚本生成核心差别在于LaTeX 用环境 参数来描述排版意图Notebook 用HTML 结构 CSS来描述渲染结果。前者是文档语义后者是页面渲染。想通这一点就不会再去找有没有一个 center 参数了——直接问浏览器怎么居中一个元素答案自然就有了。7. 导出、协作与版本管理里的图片7.1 HTML 正常但 PDF 丢图的原因jupyter nbconvert --to html report.ipynb导出通常没问题因为 HTML 导出是把页面结构原样搬过去。但--to pdf走的是另一条路先把 Markdown 和 HTML 转成 LaTeX再用 LaTeX 引擎编译成 PDF。这条链路上HTML 里的样式信息大量丢失——stylewidth:60%很可能被丢掉图片直接按原始尺寸插入然后撑出页面边界。如果你的目标产物确实是 PDF有两个更稳的选择。第一个是改用webpdf 导出它用无头浏览器渲染页面再打印成 PDFCSS 会被完整保留jupyter nbconvert --to webpdf --allow-chromium-download report.ipynb第二个是在需要精确控制尺寸的位置用raw 单元格写 LaTeX。raw 单元格只有在导出目标匹配它的 mimetype 时才会被输出所以写text/latex的 raw 单元格在 HTML 导出里会被跳过在 PDF 导出里会被正确处理\begin{figure}[h] \centering \includegraphics[width0.7\textwidth]{figs/result.png} \caption{结果对比} \end{figure}这个技巧的实际价值在于同一份 notebook 里可以同时维护 HTML 版和 PDF 版的图片写法导出时各取所需互不干扰。代价是同一张图要写两遍所以只在对版式有硬性要求的正式交付物上用内部记录不必这么麻烦。7.2 base64 内嵌的取舍前面提到过Image(filename...)和附件模式都会把图片转成 base64。这里给一组具体数字感受一下一张 1.5MB 的 PNGbase64 之后大约 2MB写进.ipynb就是 2MB 的文本。如果一份报告里嵌了十张文件就是二十多兆。判断标准可以简化成三条需要保证发过去一定能打开用内嵌。需要版本管理、需要多人协作改图用外链目录。图片由代码生成且数量多一定用外链让磁盘文件承担体积。还有一点常被忽略内嵌之后原图一改notebook 不会自动更新你得重新走一遍插入流程。而外链模式下改磁盘文件即可notebook 不用动。这是外链在迭代期最大的优势。7.3 Git 仓库里的目录约定与检查点文件多人协作的 notebook 项目里图片目录的约定比技术细节更重要。我用的一套规则是project/ notebooks/ analysis.ipynb figs/ analysis/ step1.png step2.png .gitignore要点有三个。图片按 notebook 名字再分一层子目录避免几十张图挤在一个figs里互相覆盖同名文件。路径统一用相对路径../figs/analysis/step1.png而不是绝对路径——绝对路径在别人机器上必裂。.gitignore里加上*.ipynb_checkpoints/避免自动生成的检查点目录被提交进仓库。另外如果图片总量超过几百兆考虑用 Git 的二进制大文件扩展来管理或者干脆把图片放到对象存储、notebook 里引用链接。普通的纯文本仓库塞进大量二进制文件克隆会变得非常慢。7.4 不同客户端里的表现差异最后说一个实际会遇到的问题同一段 HTML 写法在不同客户端里表现不完全一致。JupyterLab 和 Notebook 7 用的是新的前端渲染管线对 HTML 的消毒比经典 Notebook 严格一些某些属性可能被过滤但img的width、style、常见容器标签都没问题。VS Code 内置的 Notebook 编辑器对 HTML 的支持也比较完整只是个别主题会覆盖图片的默认样式遇到显示异常时可以加!important试试。而在终端里运行的编辑器前端标记单元格的渲染能力受终端限制复杂的 HTML 排版不一定能完整显示这种环境下更适合保持写法简单把复杂排版留到浏览器里看。结论就是如果你写的 notebook 需要多人、多环境打开排版写法尽量保持在基础 HTML 内联样式这个子集里少用花哨的 CSS 特性兼容性会好很多。8. 几段可以直接抄的成品片段把前面所有内容压成四段模板用的时候改路径和宽就行。单图居中、按比例控制最通用的一段div styletext-align:center; margin:14px 0; img src./figs/result.png stylemax-width:80%; height:auto; border:1px solid #d0d7de; border-radius:6px; div stylefont-size:0.85em; color:#57606a; margin-top:6px;图 1 实验结果概览/div /div固定像素宽、需要精确对齐到某个视觉宽度的场景img src./figs/icon.png width480 styledisplay:block; margin-left:auto; margin-right:auto;两图并排带图注对比实验常用table stylewidth:100%; border:none; tr td stylewidth:50%; text-align:center; border:none; img src./figs/before.png stylewidth:92%; div stylefont-size:0.85em; color:#57606a;处理前/div /td td stylewidth:50%; text-align:center; border:none; img src./figs/after.png stylewidth:92%; div stylefont-size:0.85em; color:#57606a;处理后/div /td /tr /table动态生成图片后自动排版路径写死会失效时用这一段from pathlib import Path from IPython.display import HTML, display def show_fig(path, width70%, captionNone): p Path(path).as_posix() cap fdiv stylefont-size:0.85em; color:#57606a; margin-top:6px;{caption}/div if caption else display(HTML( fdiv styletext-align:center; margin:14px 0; fimg src{p} stylemax-width:{width}; height:auto;{cap}/div )) show_fig(figs/curve.png, width65%, caption图 2 训练曲线)我个人在实际操作中的体会是这套东西真正花时间的从来不是标签怎么写而是路径基准和导出链路这两件事。前者记住谁读文件路径就相对谁这一句就能解决大半后者只需要提前想清楚最终交付物是 HTML 还是 PDF然后在动手贴第一张图的时候就选对写法别等排了几十张图之后再回头改。至于尺寸和对齐只要养成宽度用 style 写百分比、对齐靠父容器的习惯后面几乎不会再遇到需要临时排查的情况。
返回列表