CSS Shapes 入门:自定义路径区域的文字环绕

发布于 2022-08-01 12:51:43 字数 15670 浏览 311 评论 0

长期以来,网页设计师被迫在矩形的约束范围内进行创作。 网络上的大多数内容仍然被困在简单的盒子里,因为大多数非矩形布局的创造性冒险都以失败告终。 随着 CSS Shapes 的引入,这种情况即将改变,从 Chrome 37 开始可用。

CSS Shapes 允许网页设计师围绕自定义路径包装内容,如圆形、椭圆和多边形,从而摆脱矩形的约束。

形状可以手动定义,也可以从图像中推断出来。

让我们看一个非常简单的例子。

也许你和我一样天真,当第一次浮动带有透明部分的图像时,期望内容能够包裹并填补空白,结果却对元素周围持续存在的矩形包裹形状感到失望。 CSS Shapes 可以用来解决这个问题。

Extracting a shape from an image

<img class=”element” src=”image.png” />
<p>Lorem ipsum…</p>

<style>
.element{
  shape-outside: url(image.png);
  shape-image-threshold: 0.5;
  float: left;
}
</style>

shape-outside: url(image.png) CSS 声明告诉浏览器从图像中提取形状。

shape-image-threshold 属性定义将用于创建形状的像素的最小不透明度级别。 它的值必须在 0.0(完全透明)和 1.0(完全不透明)。 所以, shape-image-threshold: 0.5 表示只有不透明度为 50% 及以上的像素将用于创建形状。

float财产是这里的关键。 虽然 shape-outside 属性定义内容将环绕的区域的形状,没有浮动,您将看不到形状的效果。

元素的另一侧有一个浮动区域 float 价值。 例如,如果带有咖啡杯图像的元素向左浮动,则浮动区域将创建在杯子的右侧。 即使您可以设计一个两边都有间隙的图像,内容只会环绕由 float 属性指定的另一侧的形状,左侧或右侧,永远不会同时环绕。

将来可以使用 shape-outside 浮动的元素上 CSS Exclusions

手动创建形状

除了从图像中提取形状之外,您还可以手动对其进行编码。 您可以从几个函数值中进行选择来创建形状: circle()ellipse()inset()polygon()。每个形状函数都接受一组坐标,并与建立坐标系的参考框配对。 稍后会详细了解参考框。

circle() 函数

Illustration of the circle() shape value

圆形值的完整符号是 circle(r at cx cy) 在哪里 r 是圆的半径,而 cxcy 是圆心在 X 轴和 Y 轴上的坐标。 圆心的坐标是可选的。 如果省略它们,则元素的中心(其对角线的交点)将用作默认值。

.element{
  shape-outside: circle(50%);
  width: 300px;
  height: 300px;
  float: left;
}

在上面的示例中,内容将环绕圆形路径的外部。 单一论据 50% 指定圆的半径,在这种特定情况下,它等于元素宽度或高度的一半。 更改元素的尺寸将影响圆形的半径。 这是 CSS 形状如何响应的基本示例。

在进一步讨论之前,先说一句:重要的是要记住 CSS 形状只影响元素周围浮动区域的形状。 如果元素有背景,则不会被形状剪裁。 要实现这种效果,您必须使用 CSS Masking - clip-path mask-image 。 这 clip-path 属性非常方便,因为它遵循与 CSS 形状相同的符号,因此您可以重用值。

Illustration of `circle()` shape + clip-path

本文档中的插图使用剪辑来突出显示形状并帮助您了解效果。

当使用百分比作为圆半径时,该值实际上是使用稍微复杂的 公式计算 :sqrt(width^2 + height^2) / sqrt(2)。 理解这一点很有用,因为它将帮助您想象如果元素的尺寸不相等,最终的圆形会是什么。

所有 CSS 单位类型都可以在形状函数坐标中使用——px、em、rem、vw、vh 等等。 您可以根据需要选择足够灵活或刚性的。

您可以通过为其中心的坐标设置显式值来调整圆的位置。

.element{
  shape-outside: circle(50% at 0 0);
}

这会将圆心定位在坐标系的原点。 什么是坐标系? 这是我们引入参考框的地方。

CSS 形状的参考框

参考框是元素周围的虚拟框,它建立了用于绘制和定位形状的坐标系。 坐标系的原点在其左上角,X 轴指向右侧,Y 轴指向下方。

Coordinate system for CSS Shapes

请记住 shape-outside 改变内容将环绕的浮动区域的形状。 浮动区域延伸到由 margin 财产。 这被称为 margin-box 如果没有明确提及,它是形状的默认参考框。

以下两个 CSS 声明具有相同的结果:

.element{
  shape-outside: circle(50% at 0 0);
  /* identical to: */
  shape-outside: circle(50% at 0 0) margin-box;
}

我们还没有在元素上设置边距。 此时可以安全地假设坐标系的原点和圆心位于元素内容区域的左上角。 当您设置边距时,情况会发生变化:

.element{
  shape-outside: circle(50% at 0 0) margin-box;
  margin: 100px;
}

坐标系的原点现在位于元素的内容区域之外(向上 100 像素,向左 100 像素),圆心也是如此。 圆半径的计算值也会增加,以说明由 margin-box 参考框。

Margin-box coordinate system with and without margin

有几个参考框选项可供选择: margin-box, border-box, padding-boxcontent-box. 他们的名字暗示了他们的界限。 我们之前解释过 margin-box。这 border-box 受元素边界的外边缘约束, padding-box 受元素的填充约束,而 content-box 与元素内内容使用的实际表面积相同。

Illustration of all reference boxes

在给定时间只能使用一个参考框 shape-outside 宣言。 每个参考框都会以不同且有时微妙的方式影响形状。 还有一篇文章深入研究并帮助您 理解 CSS Shapes 的参考框

ellipse() 函数

Illustration of ellipse() shape value

椭圆看起来像压扁的圆圈。 它们被定义为 ellipse(rx ry at cx cy), 在哪里 rxry 是椭圆在 X 轴和 Y 轴上的半径,而 cxcy 是椭圆中心的坐标。

.element{
  shape-outside: ellipse(150px 300px at 50% 50%);
  width: 300px;
  height: 600px;
}

百分比值将从坐标系的维度计算。 这里不需要有趣的数学。 您可以省略椭圆中心的坐标,它们将从坐标系的中心推断出来。

X 和 Y 轴上的半径也可以用关键字定义: farthest-side 产生的半径等于椭圆中心与参考框最远离它的一侧之间的距离,而 closest-side 意思正好相反——使用中心和边之间的最短距离。

.element{
  shape-outside: ellipse(closest-side farthest-side at 50% 50%);
  /* identical to: */
  shape-outside: ellipse(150px 300px at 50% 50%);
  width: 300px;
  height: 600px;
}

当元素的尺寸(或参考框)可能以不可预知的方式发生变化时,这可能会派上用场,但您希望椭圆形状适应。

相同 farthest-sideclosest-side 关键字也可以用于半径 circle() 形函数。

polygon() 函数

Illustration of polygon() shape value

如果圆形和椭圆形太有限,多边形形状功能打开了一个选项的世界。 格式是 polygon(x1 y1, x2 y2, ...) 您可以在其中为多边形的每个顶点(点)指定 xy 坐标对。 指定多边形的最小对数是三个,一个三角形。

.element{
  shape-outside: polygon(0 0, 0 300px, 300px 600px);
  width: 300px;
  height: 600px;
}

顶点放置在坐标系上。 对于响应式多边形,您可以对部分或全部坐标使用百分比值。

.element{
  /* polygon responsive to font-size*/
  shape-outside: polygon(0 0, 0 100%, 100% 100%);
  width: 20em;
  height: 40em;
}

有一个可选的 fill-rule 参数, 从 SVG 导入 ,指示浏览器在自相交路径或封闭形状的情况下如何考虑多边形的“内部”。 Joni Trythall 很好地解释 了 fill-rule 属性 在 SVG 中的工作原理。 如果未定义,则 fill-rule 默认为 nonzero

.element{
  shape-outside: polygon(0 0, 0 100%, 100% 100%);
  /* identical to: */
  shape-outside: polygon(nonzero, 0 0, 0 100%, 100% 100%);
}

inset() 函数

inset() shape 函数允许您创建矩形形状来包装内容。 考虑到 CSS Shapes 将 Web 内容从简单的盒子中解放出来的最初前提,这听起来可能违反直觉。 很可能是这样。 我还没有找到一个用例 inset() 这还不能通过浮动和边距或 polygon()。尽管 inset() 确实为矩形形状提供了比 polygon()

插入形状函数的完整符号是 inset(top right bottom left border-radius),前四个位置参数是从元素边缘向内的偏移量。 最后一个参数是矩形的边框半径。 它是可选的,因此您可以忽略它。 它遵循 border-radius 您已经在 CSS 中使用的速记符号。

.element{
  shape-outside: inset(100px 100px 100px 100px);
  /* yields a rectangular shape which is 100px inset on all sides */
  float: left;
}

从参考框创建形状

如果您不指定形状函数 shape-outside 属性,您可以允许浏览器从元素的参考框派生形状。 默认参考框是 margin-box。到目前为止没有什么异国情调,这就是花车已经工作的方式。 但是应用这种技术,您可以重用元素的几何形状。 让我们看看 border-radius 财产。

如果你用它来圆浮动元素的角,你会得到剪裁效果,但浮动区域仍然是矩形。 添加 shape-outside: border-box 环绕由 border-radius

Extracting a shape from an element's border-radius using the border-box reference box

.element{
  border-radius: 50%;
  shape-outside: border-box;
  float: left;
}

当然,您可以以这种方式使用所有参考框。 这是派生形状的另一个用途——偏移拉引号。

Creating an offset pull-quote using the content-box reference box

仅使用 float 和 margin 属性就可以实现偏移拉引号效果。 但这需要您将引用元素定位在 HTML 树中您希望它呈现的位置。

以下是如何通过增加灵活性来实现相同的偏移量拉引号效果:

.pull-quote{
  shape-outside: content-box;
  margin-top: 200px;
  float: left;
}

我们明确设置 content-box 形状坐标系的参考框。 在这种情况下,拉引号中的内容量定义了外部内容将环绕的形状。 这 margin-top 此处使用属性来定位(偏移)拉引号,而不管它在 HTML 树中的位置。

形状边距

您会注意到将内容包裹在形状周围会使它与元素摩擦得太近。 您可以在形状周围添加间距 shape-margin 财产。

.element{
  shape-outside: circle(40%);
  shape-margin: 1em;
  float: left;
}

效果类似于您习惯使用常规的效果 margin 财产,但 shape-margin 只影响周围的空间 shape-outside 价值。 只有在坐标系中有空间时,它才会在形状周围添加间距。 这就是为什么在上面的示例中,圆半径设置为 40%,而不是 50%。 如果半径设置为 50%,圆将占据坐标系中的所有空间 shape-margin,请记住,形状最终受限于元素的 margin-box(元素加上它的周围 margin)。 如果形状较大并溢出,它将被剪裁到 margin-box 你最终会得到一个矩形。

了解这一点很重要 shape-margin 只接受一个正值。 它没有长手符号。 无论如何,圆的形状边距顶部是什么?

动画形状

您可以将 CSS 形状与许多其他 CSS 功能(例如过渡和动画)混合使用。 不过,我必须强调,当用户在阅读时文本布局发生变化时,他们会觉得很烦人。 如果您决定支持动画形状,请密切注意体验。

您可以为半径和中心设置动画 circle()ellipse() 形状,只要它们是在浏览器可以插入的值中定义的。 从 circle(30%)circle(50%) 是可能的。 然而,动画之间 circle(closest-side)circle(farthest-side) 会阻塞浏览器。

.element{
  shape-outside: circle(30%);
  transition: shape-outside 1s;
  float: left;
}

.element:hover{
  shape-outside: circle(50%);
}

GIF of animated circle

动画时可以实现更有趣的效果 polygon() 形状,重要的是多边形必须在两个动画状态之间具有相同数量的顶点。 如果您添加或删除顶点,浏览器将无法进行插值。

一个技巧是添加您需要的最大数量的顶点并将它们聚集在动画状态中,您希望形状的感知边缘更少。

.element{
  /* four vertices (looks like rectangle) */
  shape-outside: polygon(0 0, 100% 0, 100% 100%, 0 100%);
  transition: shape-outside 1s;
}

.element:hover{
  /* four vertices, but second and third overlap (looks like triangle) */
  shape-outside: polygon(0 0, 100% 50%, 100% 50%, 0 100%);
}

GIF of animated triangle

在形状内包装内容

Screenshot of Alice in Wonderland demo using CSS Shapes to wrap content

CSS Shapes 规范的初稿包括一个 shape-inside 允许您将内容包装在形状内的属性。 甚至在 Chrome 和 Webkit 中有一段时间的实现。 但是将任意定位的内容包装在自定义路径中需要更多的努力和研究才能涵盖所有可能的场景并避免错误。 这就是为什么 shape-inside 属性已被推迟到 CSS Shapes Level 2 并且它的实现已被撤回。

但是,通过一些努力和一些妥协,您仍然可以实现将内容包裹在自定义形状中的效果。 hack是使用两个浮动元素 shape-outside,位于容器的相对两侧。 妥协是你必须使用一两个没有语义意义的空元素,但作为支柱来创造内部形状的错觉。

<div>
  <div class="left-shape"></div>
  <div class="right-shape"></div>

  Lorem ipsum...
</div>

.left-shape.right-shape 容器顶部的支柱元素很重要,因为它们会左右浮动,以便在内容的两侧浮动。

.left-shape{
  shape-outside: polygon(0 0, ...);
  float: left;
  width: 50%;
  height: 100%;
}

.right-shape{
  shape-outside: polygon(50% 0, ...);
  float: right;
  width: 50%;
  height: 100%;
}

Illustration of workaround for shape-inside for Alice demo

这种样式使两个浮动支柱占据了元素内的所有空间,但是 shape-outside 属性为其余内容腾出空间。

如果浏览器不支持 CSS 形状,则会通过将所有内容向下推而产生丑陋的效果。 这就是为什么以逐步增强的方式使用该功能很重要的原因。

在前面的形状动画示例中,您会注意到文本四处移动可能很麻烦。 并非所有用例都需要动画形状。 但是您可以为与 CSS 形状交互的其他属性设置动画,以在有意义的地方添加效果。

在 CSS Shapes 的 Alice in Wonderland 演示中,我们使用滚动位置来更改内容的上边距。 文本被压缩在两个浮动元素之间。 当它向下移动时,它必须根据 shape-outside 两个浮动元素。 这给人的印象是文本正在进入兔子洞,并增加了讲故事的体验。 边缘无偿? 也许。 但它看起来确实很酷。

因为文本布局是由浏览器本地完成的,所以性能比使用 JavaScript 解决方案要好。 但是在滚动时更改 margin-top 确实会触发大量重新布局和绘制事件,这可能会显着降低性能。 谨慎使用! 然而,使用 CSS Shapes 而不对其进行动画处理并不会带来明显的性能影响。

渐进式增强

首先假设浏览器不支持 CSS Shapes,并在您检测到该功能时在此基础上进行构建。 Modernizr 中有一个针对 CSS 形状的测试 “非核心检测” 部分

一些浏览器在 CSS 中通过 @supports 规则而不需要外部库。 也支持 CSS Shapes 的 Google Chrome 理解 @supports 规则。 这是您使用它逐步增强的方式:

.element{
  /* styles for all browsers */
}

@supports (shape-outside: circle(50%)){
  /* styles only for browsers which support CSS Shapes */
  .element{
    shape-outside: circle(50%);
  }
}

Lea Verou 写了更多关于 如何使用 CSS @supports 规则的文章

从 CSS 排除中消除歧义

我们今天所知的 CSS 形状在规范的早期曾被称为 CSS 排除和形状。 命名的转换可能看起来很细微,但实际上非常重要。 CSS Exclusions ,现在是一个单独的规范,可以将内容包裹在任意位置的元素周围,而不需要 float 属性。 想象一下将内容包裹在绝对定位的元素周围; 这是 CSS 排除的一个用例。 CSS Shapes 只是定义了内容环绕的路径。

因此,形状和排除不是一回事,但它们确实相辅相成。 CSS Shapes 现在可以在浏览器中使用,而 CSS Exclusions 还没有通过形状交互实现。

使用 CSS 形状的工具

您可以在经典图像创作工具中创建路径,但在撰写本文时,它们都没有导出 CSS Shapes 值所需的语法。 即使他们这样做了,那样的工作也不会太实际。

CSS Shapes 旨在用于浏览器,它们对页面上的其他元素做出反应。 可视化编辑形状对其周围内容的影响非常有用。 有一些工具可以帮助您完成此工作流程:

括号 :括号的 CSS 形状编辑器扩展 使用代码编辑器的实时预览模式覆盖交互式编辑器以编辑形状值。

谷歌浏览器 :谷歌浏览器的 CSS 形状编辑器扩展 扩展了浏览器的开发者工具,带有创建和编辑形状的控件。 它将交互式编辑器放置在选定元素的顶部。

Google Chrome 中的检查器内置了对突出显示形状的支持。 将鼠标悬停在带有 a 的元素上 shape-outside属性,它会亮起以说明形状。

图像中的形状 :如果您喜欢生成图像并让浏览器从中提取形状,Rebecca Hauck 为 Photoshop 编写了一个很好的教程

Polyfill :Google Chrome 是第一个发布 CSS Shapes 的主流浏览器。 即将在 Apple 的 iOS 8 和 Safari 8 上支持该功能。其他浏览器供应商将来可能会考虑它。 在那之前,有一个 CSS Shapes polyfill 来提供基本的支持。

结论

在内容大多被困在简单盒子中的 Web 中,CSS Shapes 提供了一种创建富有表现力的布局的方法,弥合了 Web 和印刷设计之间的保真度差距。 当然,形状可能会被滥用并造成干扰。 但是,当运用品味和良好的判断力时,形状可以增强内容呈现并以他们独有的方式集中用户的注意力。

我给你留下 的作品集 ,大部分来自印刷品,展示了非矩形布局的有趣用途。 我希望这能激发您尝试 CSS Shapes 并尝试新的设计理念。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

绝影如岚

暂无简介

0 文章
0 评论
424 人气
更多

推荐作者

遂心如意

文章 0 评论 0

5513090242

文章 0 评论 0

巷雨优美回忆

文章 0 评论 0

junpengz2000

文章 0 评论 0

13郎

文章 0 评论 0

qq_xU4RDg

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文