若要让段落文字环绕超出卡片边缘的图片,请将图片浮动,并使用负外边距。添加 shape-outside 可创建弯曲轮廓。本教程会构建一个完整的本地示例,你可以在 Mac 上用 Safari 打开。

怎样才能让文字环绕重叠的图片?

图片需要参与段落的浮动布局。CSS float 会将元素放在容器的一侧,让相邻文字在其旁边环绕。本例中,向右浮动会让文字从图片左侧流动,然后继续排在图片下方。MDN:float。

有三个设置会决定最终效果:浮动会创建环绕行为,负右外边距会让图片超出容器,而 shape-outside 会定义周围文字沿着哪种轮廓排列。普通浮动会产生矩形环绕;形状则可以让每一行文字沿圆形排列。MDN:shape-outside。

仅仅在视觉上移动图片是不够的。绝对定位的图片不会占用普通流中的空间,因此周围元素会表现得像图片不存在一样。平移会改变渲染位置,却不会重新排列文档的普通流。这些行为解释了为什么使用 position: absolute 或 transform: translateX(...) 定位重叠图片时,图片可能会遮住文字。MDN:position,MDN:使用 CSS 变换。

这里的任务范围很明确:一张圆形图片越过一张文字卡片的右边缘,而卡片中的段落沿着圆形的左侧轮廓排列。图片和段落属于同一个环绕区域。

在 Mac 上构建完整示例

在纯文本代码编辑器中创建一个名为 overlap-wrap.html 的文件。粘贴下面的完整文档,保存,然后在 Safari 中打开。示例通过数据 URL 内置了一张抽象 SVG 图片,因此无需安装图片文件、程序包或构建工具。

浮动图片出现在它要影响的段落之前。这一顺序很重要,因为浮动位置受文档中更早出现的内容限制。让标题保持在浮动图片之前,也能让标题占据卡片的全部文字宽度。W3C:视觉格式化模型。

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Overlapping image and paragraph wrapping</title>
  <style>
    * { box-sizing: border-box; }
    body {
      margin: 0;
      padding: 32px 96px 32px 32px;
      background: #eef1f5;
      color: #243247;
      font: 18px/1.65 system-ui, sans-serif;
    }
    .card {
      display: flow-root;
      width: 100%;
      max-width: 640px;
      margin: 0 auto;
      padding: 24px;
      background: white;
      box-shadow: 0 0 0 1px #cbd3df;
      overflow: visible;
    }
    .card h2 {
      margin: 0 0 16px;
      font-size: 26px;
      line-height: 1.25;
    }
    .card p { margin: 0 0 16px; }
    .card p:last-child { margin-bottom: 0; }
    .art {
      display: block;
      float: right;
      width: 240px;
      height: 240px;
      margin: 0 -88px 16px 16px;
      border-radius: 50%;
      shape-outside: circle(50%) border-box;
      shape-margin: 16px;
    }
    @media (max-width: 760px) {
      body { padding: 16px; }
      .art {
        float: none;
        width: min(240px, 100%);
        height: auto;
        margin: 0 auto 24px;
        shape-outside: none;
      }
    }
  </style>
</head>
<body>
  <article class="card">
    <h2>Study A: circles and spacing</h2>
    <img class="art" width="240" height="240" alt=""
      src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240' viewBox='0 0 240 240'%3E%3Crect width='240' height='240' fill='%233a628b'/%3E%3Ccircle cx='90' cy='85' r='60' fill='%23b9d8eb'/%3E%3Ccircle cx='165' cy='170' r='45' fill='%238db5cc'/%3E%3C/svg%3E">
    <p>Panel A pairs a circular graphic with a continuous passage of
      sample text. Follow the right edge of this paragraph as each
      line approaches the curved outline. Near the widest part of
      the circle, the available space becomes narrower.</p>
    <p>Panel B continues the same passage with a second paragraph.
      The graphic extends into the outer gutter while the words
      remain inside the white card. As the contour curves inward,
      later lines can use more of the available width.</p>
    <p>Panel C provides enough additional text to show the transition
      below the graphic. Once the passage continues beyond the
      wrapping region, its lines return to the full content width.
      Resize the window to compare the desktop arrangement with
      the stacked layout used in a narrower window.</p>
  </article>
</body>
</html>

当视口宽度大于 760px 时,预期效果是圆形图像伸入右侧边栏,段落文字沿其左侧排列。当视口宽度不超过 760px 时,图片会变成居中的块级元素,显示在段落上方。这个断点只是示例中的设计选择;查询条件匹配时,@media 会应用其中的声明。MDN:@media。

示例图像仅用于装饰,因此其图片元素使用 alt=""。如果你将它替换为承载信息的图像,请提供恰当的文本替代内容。WHATWG 区分了装饰性图片和需要用文本等效内容表达其信息的图片。WHATWG:为图片提供替代文本的要求。

如何选择重叠量和文字间距?

先设置图片的位置,再调整轮廓。向右浮动的元素会根据其外边距框定位。在本例中,负右外边距让图片右边缘超出卡片内容边缘 88px。卡片的右内边距为 24px,因此图片会超出白色背景 64px。这些是本例推算得出的尺寸,以 CSS 像素为单位。W3C:浮动元素的定位。

数值 示例值 计算方式或用途
图片宽度 240px 显示圆形的直径
超出内容边缘的距离 88px 负右外边距的绝对值
卡片内边距 24px 内容边缘与背景边缘之间的间距
超出背景的可见部分 64px 88 − 24
图片在内容区域内剩余的宽度 152px 240 − 88
矩形回退预留空间 168px 240 − 88 + 16,包含左外边距

在你自己的布局中,将期望的超出距离加上容器的右内边距,就能算出负外边距的绝对值。例如,超出 40px 且内边距为 24px 时,右外边距应设为 -64px。每当放大图片或缩小容器宽度时,都要重新检查剩余的文字宽度。

圆形版本使用 shape-outside: circle(50%) border-box,使形状几何特征与正方形图片框一致。这里显式选择 border-box 很有用,因为不对称外边距会改变外边距框。如果不明确指定参考框,基本形状默认使用 margin-box。MDN:使用 shape-outside 创建基本形状。

shape-margin: 16px 会在环绕轮廓周围增加间距。正的左外边距会在面向文字的一侧为这段间距留出空间。形状及其形状外边距都会被裁剪到浮动元素的外边距框内;仅增大 shape-margin 并不能无限扩大环绕区域。负右外边距也会在朝外的一侧裁剪形状,而本例这一侧没有段落文字。W3C:CSS Shapes 模块第 1 级。

对于矩形图片,将 border-radius 改为 0,将 shape-outside 改为 none,并将 shape-margin 改为 0。保留浮动和外边距。这样就能在保持相同外移位置的同时,获得边缘笔直的文字环绕。若只移除形状而保留圆形裁剪,图片仍然是圆形,但文字避让区域会是矩形。

哪些容器边界会影响文字环绕?

卡片使用 display: flow-root 建立块级格式化上下文,从而在垂直方向上包含其浮动元素。这样即使文字很短,卡片高度也会将图片计算在内。它还会让此环绕区域独立于外部浮动元素。MDN:块级格式化上下文。

段落应在该区域内保持普通块级流布局。如果图片是直接的 flex 或 grid 项目,它的浮动就无法实现这种段落环绕方式。同样,如果单独的段落包装元素有自己的块级格式化上下文,外部浮动就不会影响其内部内容。外层网格可以负责定位整张卡片;卡片内部仍可使用流布局。MDN:块级格式化上下文。

另外检查裁剪情况。示例让溢出内容保持可见,以便显示超出部分。用 overflow 来包含浮动元素可能会导致裁剪或出现滚动条;flow-root 可以包含浮动元素,而不必采用这种方式。如果图片恰好在某个祖先元素的边缘消失,也要检查外层组件。MDN:包含内部浮动元素。

CSS Shapes 还有方向上的限制:右浮动允许文字在其左侧环绕,左浮动则允许文字在其右侧环绕。单个浮动元素无法让文字同时从居中图片的两侧穿过。本任务适用的布局方式是将图片浮动到边缘。W3C:CSS Shapes 与浮动行为。

这种方法能用于 Tailwind CSS 吗?

可以。在现有的 Tailwind 项目中,float-right 会生成 float: right,而 float-none 会取消浮动。Tailwind 提供这些实用类;文字布局仍由浏览器完成。Tailwind CSS:float。

对于轮廓声明,Tailwind 的任意属性语法可以表达 [shape-outside:circle(50%)_border-box] 和 [shape-margin:16px]。下划线代表 border-box 前面的空格。这些是已配置 Tailwind 项目中的类名片段,不能替代上面的完整文档。改写时要保留相同的尺寸、外边距、容器布局,以及窄视口下的重置设置。Tailwind CSS:添加自定义样式。

如何诊断看起来不对的文字环绕?

先以本地示例为基准,再逐项引入现有样式。按以下步骤检查决定布局的条件:

  1. 先确认矩形环绕。 临时设置 shape-outside: none。如果文字仍然排在图片下方,请检查图片是否浮动、采用绝对定位,或者是 flex/grid 的直接子项。
  2. 检查文档顺序。 将浮动元素放在需要环绕它的段落之前。
  3. 检查环绕区域。 让浮动元素和段落内容位于同一个块级格式化上下文中;从段落包装元素中移除不必要的独立上下文。
  4. 检查轮廓。 恢复圆形及其明确指定的 border-box 参考框。确认显示的图片是正方形,再应用圆形裁剪。
  5. 检查边栏空间。 增大视口宽度,并查看卡片或其祖先元素是否裁剪了内容。确认页面为超出部分预留了足够的外部空间。
  6. 检查窄视口布局。 调整尺寸越过示例的断点,确认浮动和负外边距都已重置。

这些检查遵循关于浮动元素定位、格式化上下文和形状参考框的文档规则。不要添加手动换行来修补个别行;这样会让段落受限于某一个特定的窗口尺寸。

MDN 指出 shape-outside 已得到广泛支持,同时说明其部分语法的支持情况可能有所不同。本示例使用文档所述的 circle() 形式。请在计划支持的 Mac 浏览器中比较页面,并评估文字间距和可读性,无需强求各浏览器的换行位置完全相同。如果不支持形状声明,浮动仍会保留矩形环绕效果。MDN:shape-outside。

完成布局时,应一并选择图片尺寸和超出距离,为文字区域保留足够宽度,并保留窄视口下的堆叠回退布局。尺寸合适后,再用轮廓微调图片周围的间距。这样,即使文字或可用宽度发生变化,段落也能重新排布。

来源