基于图像的形状

在本指南中,我们将了解如何使用带有 Alpha 通道的图像文件或甚至 CSS 渐变来创建形状。这是一种非常灵活的创建形状的方法。与其在 CSS 中使用复杂的 `polygon()` 绘制路径,不如在图形程序中创建形状,然后使用不透明度低于阈值像素所创建的路径。

从图像创建形状

要使用图像创建形状,图像需要具有 Alpha 通道,即不完全不透明的区域。shape-image-threshold 属性用于为此不透明度设置阈值。不透明度高于此值的像素将用于计算形状的区域。

在下面的示例中,有一个星星图像,它有一个纯红色区域和一个完全透明的区域。图像文件的路径用作 shape-outside 属性的值。内容现在围绕星形进行环绕。

html
<div class="box">
  <img
    alt="A red star"
    src="https://mdn.github.io/shared-assets/images/examples/star-shape.png" />
  <p>
    One November night in the year 1782, so the story runs, two brothers sat
    over their winter fire in the little French town of Annonay, watching the
    grey smoke-wreaths from the hearth curl up the wide chimney. Their names
    were Stephen and Joseph Montgolfier, they were papermakers by trade, and
    were noted as possessing thoughtful minds and a deep interest in all
    scientific knowledge and new discovery. Before that night—a memorable night,
    as it was to prove—hundreds of millions of people had watched the rising
    smoke-wreaths of their fires without drawing any special inspiration from
    the fact.
  </p>
</div>
css
body {
  font: 1.2em / 1.5 sans-serif;
}
img {
  float: left;
  shape-outside: url("https://mdn.github.io/shared-assets/images/examples/star-shape.png");
}

你可以使用 shape-margin 将文本从形状移开,在创建的形状和文本之间留出边距。

css
body {
  font: 1.2em / 1.5 sans-serif;
}

img {
  float: left;
  shape-outside: url("https://mdn.github.io/shared-assets/images/examples/star-shape.png");
  shape-margin: 20px;
}

CORS 兼容性

从图像创建形状时你会遇到的一个问题是,你使用的图像必须 CORS 兼容。托管在你网站同一域上的图像应该可以正常工作,但是,如果你的图像托管在不同的域上(例如 CDN),则应确保它们发送正确的标头以使其可用于形状。由于对 CORS 兼容图像的此要求,如果你在本地预览文件而没有使用本地 Web 服务器,则你的形状将无法工作。

这是一个 CORS 问题吗?

DevTools 可以帮助你识别 CORS 错误。在 Chrome 中,控制台会提醒你 CORS 问题。在 Firefox 中,如果你检查属性,你会收到图像无法加载的警报。这应该会提醒你,由于 CORS,你的图像不能用作形状的来源。

设置阈值

shape-image-threshold 属性可以从不完全透明的区域创建形状。如果 shape-image-threshold 的值为 0.0(这是初始值),则该区域必须完全透明。如果值为 1.0,则它完全不透明。介于两者之间的值意味着你可以将半透明区域设置为定义区域。

在下面的示例中,星星的背景不是完全透明的,它在我的图形程序中创建时具有 20% 的不透明度。如果我将 shape-image-threshold 设置为 0.2 或更大,那么我看到形状,如果我将其设置为小于 0.2,则我得不到形状。

css
body {
  font: 1.2em / 1.5 sans-serif;
}

img {
  float: left;
  shape-outside: url("https://mdn.github.io/shared-assets/images/examples/star-red-20.png");
  shape-image-threshold: 0.2;
}

使用带生成内容的图像

在上面的示例中,我既将图像用作 shape-outside 的值,也将其添加到了页面中。许多演示都这样做,因为它有助于显示我们正在跟随的形状,但是 shape-outside 属性与页面上显示的图像无关,因此你无需显示图像即可使用图像创建形状。

你确实需要一些浮动的东西,但这可能是一些生成的内容,如以下示例所示。我正在浮动生成的内容,并使用一个更大的星形图像来塑造我的内容,而不在页面上显示任何图像。

html
<div class="box">
  <p>
    One November night in the year 1782, so the story runs, two brothers sat
    over their winter fire in the little French town of Annonay, watching the
    grey smoke-wreaths from the hearth curl up the wide chimney. Their names
    were Stephen and Joseph Montgolfier, they were papermakers by trade, and
    were noted as possessing thoughtful minds and a deep interest in all
    scientific knowledge and new discovery. Before that night—a memorable night,
    as it was to prove—hundreds of millions of people had watched the rising
    smoke-wreaths of their fires without drawing any special inspiration from
    the fact.
  </p>
</div>
css
body {
  font: 1.2em / 1.5 sans-serif;
}

.box::before {
  content: "";
  float: left;
  width: 400px;
  height: 300px;
  shape-outside: url("https://mdn.github.io/shared-assets/images/examples/star-shape.png");
  shape-image-threshold: 0.3;
}

使用渐变创建形状

因为 CSS 渐变被视为图像,所以你可以通过将透明或半透明区域作为渐变的一部分来使用渐变生成形状。

下一个示例使用生成的内容。内容已浮动,为其提供了线性渐变的背景图像。我使用相同的值作为 shape-outside 的值。线性渐变从紫色变为透明。通过更改 shape-image-threshold 的值,你可以决定创建形状的像素需要有多透明。你可以在下面的示例中尝试该值,以了解对角线如何根据该值在形状上移动。

你还可以尝试完全删除背景图像,从而纯粹使用渐变创建形状,而根本不将其显示在页面上。

html
<div class="box">
  <p>
    One November night in the year 1782, so the story runs, two brothers sat
    over their winter fire in the little French town of Annonay, watching the
    grey smoke-wreaths from the hearth curl up the wide chimney. Their names
    were Stephen and Joseph Montgolfier, they were papermakers by trade, and
    were noted as possessing thoughtful minds and a deep interest in all
    scientific knowledge and new discovery. Before that night—a memorable night,
    as it was to prove—hundreds of millions of people had watched the rising
    smoke-wreaths of their fires without drawing any special inspiration from
    the fact.
  </p>
</div>
css
body {
  font: 1.2em / 1.5 sans-serif;
}

.box::before {
  content: "";
  float: left;
  height: 250px;
  width: 400px;
  background-image: linear-gradient(
    to bottom right,
    rebeccapurple,
    transparent
  );
  shape-outside: linear-gradient(to bottom right, rebeccapurple, transparent);
  shape-image-threshold: 0.3;
}

下一个示例使用带有椭圆的径向渐变,再次使用渐变的透明部分来创建形状。

css
body {
  font: 1.2em / 1.5 sans-serif;
}

.box::before {
  content: "";
  float: left;
  height: 250px;
  width: 400px;
  background-image: radial-gradient(
    ellipse closest-side,
    rebeccapurple,
    blue 50%,
    transparent
  );
  shape-outside: radial-gradient(
    ellipse closest-side,
    rebeccapurple,
    blue 50%,
    transparent
  );
  shape-image-threshold: 0.3;
}

你可以在这些实时示例中直接进行实验,以了解更改渐变如何改变形状的路径。