使用react-notion-x与Next App Router时Notion视频图片显示不一致求助
问题1:9:16视频导致布局破坏,与Notion端显示差异
原因
Notion内部针对媒体内容(包括视频)实现了一套自适应布局逻辑:
- 动态根据媒体原始宽高比计算容器的
aspect-ratio - 限制容器的最大宽度(通常不超过页面内容区宽度),超出时按比例缩小
- 媒体内容使用
object-fit: contain保证完整显示,不会溢出容器
而react-notion-x的默认VideoBlock组件并未完全复刻这套逻辑:默认样式可能固定了宽高比(比如16:9),或者未设置合理的最大尺寸限制,导致竖屏视频撑爆布局;若强制修改全局样式适配9:16,又会覆盖其他比例视频的正常显示。
解决方案
1. 自定义VideoBlock组件,复刻Notion的自适应逻辑
react-notion-x支持自定义块渲染,你可以重写视频块的渲染逻辑,动态适配视频比例:
import { VideoBlock } from 'react-notion-x' const CustomVideoBlock = (props) => { const { block } = props const { width, height } = block.properties.source[0][0]?.video ?? {} // 计算视频宽高比,默认 fallback 到16:9 const aspectRatio = width && height ? `${width}/${height}` : '16/9' return ( <div style={{ maxWidth: '100%', margin: '1rem auto', aspectRatio, position: 'relative' }} > <video style={{ width: '100%', height: '100%', objectFit: 'contain', borderRadius: '0.375rem' }} controls src={block.properties.source[0][0].video.url} /> </div> ) }
然后在NotionRenderer中配置自定义块:
<NotionRenderer blocks={page.blocks} components={{ video: CustomVideoBlock }} // 其他props />
2. 全局样式兜底调整
如果不想自定义组件,可以给全局的视频容器添加样式:
.notion-video { max-width: 100% !important; max-height: 80vh !important; } .notion-video video { object-fit: contain !important; }
注意:!important仅在默认样式优先级过高时使用,优先推荐自定义组件方案。
问题2:WebP/GIF显示裁剪、时序/视觉异常
原因
- 裁剪问题:react-notion-x默认的
ImageBlock组件可能使用了object-fit: cover(用于填充容器),而Notion端对图片类内容使用object-fit: contain保证完整显示,导致部分内容被裁剪。 - 时序/视觉问题:
- 图片加载时未预留布局空间,导致页面跳动(布局偏移)
- WebP的渐进式加载配置与Notion端不一致,或GIF的帧渲染未被正确处理
- 部分浏览器对WebP的兼容性处理存在差异
解决方案
1. 修复裁剪问题:修改图片块样式
自定义ImageBlock组件,调整object-fit和容器尺寸:
import { ImageBlock } from 'react-notion-x' const CustomImageBlock = (props) => { const { block } = props const { width, height } = block.properties.source[0][0]?.image ?? {} return ( <div style={{ maxWidth: '100%', margin: '1rem auto', aspectRatio: width && height ? `${width}/${height}` : undefined }} > <img style={{ width: '100%', height: 'auto', objectFit: 'contain', borderRadius: '0.375rem' }} src={block.properties.source[0][0].image.url} width={width} height={height} loading="lazy" /> </div> ) }
在NotionRenderer中配置:
<NotionRenderer blocks={page.blocks} components={{ image: CustomImageBlock }} // 其他props />
2. 解决时序/视觉异常
- 预留布局空间:给图片添加width和height属性(如上代码),让浏览器提前计算容器尺寸,避免加载时布局跳动。
- 优化WebP编码:确保上传的WebP使用与Notion一致的编码方式(比如无损/有损、渐进式/基线),避免浏览器渲染异常。
- GIF帧处理:导出GIF时保持与Notion上传版本的帧速率、尺寸一致,若仍有问题,可尝试将GIF转换为WebM格式(Notion支持,且渲染性能更优)。
- 添加加载占位符:在自定义ImageBlock中添加加载状态占位符,提升视觉体验:
import { useState } from 'react' import { ImageBlock } from 'react-notion-x' const CustomImageBlock = (props) => { const [loaded, setLoaded] = useState(false) const { block } = props const { width, height } = block.properties.source[0][0]?.image ?? {} return ( <div style={{ maxWidth: '100%', margin: '1rem auto', aspectRatio: width && height ? `${width}/${height}` : undefined }} > {!loaded && ( <div style={{ width: '100%', height: '100%', backgroundColor: '#f7f7f7', borderRadius: '0.375rem' }} /> )} <img style={{ width: '100%', height: 'auto', objectFit: 'contain', borderRadius: '0.375rem', display: loaded ? 'block' : 'none' }} src={block.properties.source[0][0].image.url} width={width} height={height} loading="lazy" onLoad={() => setLoaded(true)} /> </div> ) }
内容的提问来源于stack exchange,提问作者user28251316
相关产品推荐
相关产品推荐

