CSS 形状是一个标准,它允许我们在浮动元素上创建几何形状,使这些元素周围的内联内容(通常是文本)沿着指定的形状包裹。
这种形状的文本流在编辑设计或处理文本密集内容的设计中效果很好,可以从文本块中添加一些视觉上的缓解。
以下是一个使用 CSS 形状的示例
shape-outside
属性使用基本形状函数之一(circle()
、ellipse()
、polygon()
或 inset()
)或图像来指定浮动区域的形状,如下所示
内联内容沿着左浮动元素的右侧和右浮动元素的左侧包裹。
在这篇文章中,我们将使用 CSS 形状和表情符号的概念来创建有趣的文本包裹效果。图像都是矩形。我们在 CSS 中绘制的许多形状也都是方块,或者至少限于标准形状。另一方面,表情符号提供了打破常规的绝佳机会!
以下是我们的操作方法:首先,我们将从表情符号创建一个图像,然后将其浮动并应用 CSS 形状。
我已经在这篇关于 创意背景图案 的文章中介绍了多种将表情符号转换为图像的方法。在那篇文章中,我说我无法弄清楚如何使用 SVG <text>
进行转换,但我现在已经解决了这个问题,并在本文中向您展示了如何操作。 您不必阅读过那篇文章才能理解本文,但如果您想了解更多信息,可以点击链接阅读。
让我们创建一个表情符号图像
我们用来创建表情符号图像的三个步骤是
- 在 SVG 中创建一个表情符号形状的剪切
- 通过 URL 编码并将
data:image/svg+xml
添加到前面来将 SVG 代码转换为 DataURL - 使用 DataURL 作为元素
background-image
的url()
值。
以下是用 SVG 代码创建的表情符号形状的剪切
<svg width='150px' height='150px' xmlns='http://www.w3.org/2000/svg'>
<clipPath id='emojiClipPath'>
<text x='0' y='130px' font-size='130px'>🦕</text>
</clipPath>
<text x='0' y='130px' font-size='130px' clip-path='url(#emojiClipPath)'>🦕</text>
</svg>
这里发生的事情是我们提供了一个 <text>
元素,该元素带有表情符号字符作为 <clipPath>
。剪切路径是指当剪切路径应用于元素时保持可见的区域的轮廓。在我们的代码中,该轮廓是表情符号字符的形状。
然后,表情符号的剪切路径由一个带有相同表情符号字符的 <text>
元素引用,使用其 clip-path
属性,在表情符号形状中创建一个剪切。
现在,我们将 SVG 代码转换为 DataURL。您可以手动对其进行 URL 编码,或者使用在线工具(例如这个工具!)来完成此操作。
以下是生成的 DataURL,用作 CSS 中 .emoji
元素背景图像的 url()
值
.emoji {
background: url("data:image/svg+xml,<svg width='150px' height='150px' xmlns='http://www.w3.org/2000/svg'> <clipPath id='emojiClipPath'> <text x='0' y='130px' font-size='130px'>🦕</text> </clipPath> <text x='0' y='130px' font-size='130px' clip-path='url(%23emojiClipPath)'>🦕</text></svg>");
}
如果我们在此处停止并为 .emoji
元素设置尺寸,我们将看到我们的字符作为背景图像显示
现在让我们将其转换为 CSS 形状
我们可以通过两个步骤完成此操作
- 浮动带有表情符号背景的元素
- 使用 DataURL 作为元素
shape-outside
属性的url()
值
.emoji {
--image-url: url("data:image/svg+xml,<svg width='150px' height='150px' xmlns='http://www.w3.org/2000/svg'> <clipPath id='emojiClipPath'> <text x='0' y='130px' font-size='130px'>🦕</text> </clipPath> <text x='0' y='130px' font-size='130px' clip-path='url(#emojiClipPath)'>🦕</text></svg>");
background: var(--image-url);
float: left;
height: 150px;
shape-outside: var(--image-url);
width: 150px;
margin-left: -6px;
}
我们将 DataURL 放置在自定义属性 --image-url
中,这样我们就可以轻松地在 background
和 shape-outside
属性中引用它,而无需多次重复那个长长的编码 SVG 字符串。
现在,任何靠近浮动 .emoji
元素的内联内容都将以表情符号的形状流动。我们可以使用 margin
或 shape-margin
来进一步调整内容,在形状周围添加空间。
如果您想要一个颜色块的表情符号形状,可以通过将剪切路径应用于 SVG 中的 <rect>
元素来实现
<svg width='150px' height='150px' xmlns='http://www.w3.org/2000/svg'>
<clipPath id='emojiClipPath'>
<text x='0' y='130px' font-size='130px'>🦕</text>
</clipPath>
<rect x='0' y='0' fill='green' width='150px' height='150px' clip-path='url(#emojiClipPath)'/>
</svg>
相同的技巧也适用于字母!
请注意,Firefox 并不总是渲染表情符号形状。我们可以通过更新 SVG 代码来解决这个问题。
<svg xmlns='http://www.w3.org/2000/svg' width='150px' height='150px'>
<foreignObject width='150px' height='150px'>
<div xmlns='http://www.w3.org/1999/xhtml' style='width:150px;height:150px;line-height:150px;text-align:center;color:transparent;text-shadow: 0 0 black;font-size:130px;'>🧗</div>
</foreignObject>
</svg>
这通过使表情符号透明并使用内联 CSS 为其提供 text-shadow
来创建一个块状颜色表情符号形状。然后将包含表情符号和内联 CSS 样式的 <div>
插入到 SVG 的 <foreignObject>
元素中,这样 HTML <div>
代码就可以在 SVG 命名空间中使用。此技巧中其余代码与上一个相同。
现在我们需要将形状居中
由于 CSS 形状只能应用于浮动元素,因此文本将根据元素浮动的位置在元素的右侧或左侧流动。为了将元素和形状居中,我们将执行以下操作
- 将表情符号分成两半
- 将表情符号的左半部分浮动到右侧,将右半部分浮动到左侧
- 将两边放在一起!
这种策略有一个注意事项:如果您在设计中使用的是连续句子,则需要手动对齐两边的字母。
以下是我们想要制作的内容
首先,我们看到设计左侧和右侧的 HTML。它们是相同的。
<div id="design">
<p id="leftSide">A C G T A <!-- more characters --> C G T A C G T A C G T <span class="emoji"></span>A C G <!-- more characters --> C G T </p>
<p id="rightSide">A C G T A <!-- more characters --> C G T A C G T A C G T <span class="emoji"></span>A C G <!-- more characters --> C G T </p>
</div>
p#leftSide
和 p#rightSide
在 #design
中并排排列在一个网格中。
#design {
border-radius: 50%; /* A circle */
box-shadow: 6px 6px 20px silver;
display: grid;
grid: "1fr 1fr"; /* A grid with two columns */
overflow: hidden;
width: 400px; height: 400px;
}
以下是表情符号的 CSS
span.emoji {
filter: drop-shadow(15px 15px 5px green);
shape-margin: 10px;
width: 75px;
height: 150px;
}
/* Left half of the emoji */
p#leftSide>span.emoji {
--image-url:url("data:image/svg+xml,<svg width='150px' height='150px' xmlns='http://www.w3.org/2000/svg'> <clipPath id='emojiClipPath'> <text x='0' y='130px' font-size='130px'>🦎</text> </clipPath> <rect x='0' y='0' width='150px' height='150px' clip-path='url(%23emojiClipPath)'/></svg>");
background-image: var(--image-url);
float: right;
shape-outside: var(--image-url);
}
/* Right half of the emoji */
p#rightSide>span.emoji {
--image-url:url("data:image/svg+xml,<svg width='150px' height='150px' xmlns='http://www.w3.org/2000/svg'> <clipPath id='emojiClipPath'> <text x='-75px' y='130px' font-size='130px'>🦎</text> </clipPath> <rect x='0' y='0' width='150px' height='150px' clip-path='url(%23emojiClipPath)'/></svg>");
background-image: var(--image-url);
float: left;
shape-outside: var(--image-url);
}
包含表情符号图像的 <span>
元素(span.emoji
)的宽度为 75px,而 SVG 表情符号图像的宽度为 150px。这会在将图像显示在跨度内时自动将图像裁剪为一半。
在设计的右侧,使用左浮动表情符号(p#rightSide>span.emoji
),我们需要将表情符号向左移动一半,以显示右半部分,因此 DataURL 中 <text>
中的 x
值更改为 75px。这是设计左侧和右侧 DataURL 的唯一区别。
以下是再次展示的结果
就是这样!您可以尝试使用上述方法将任何 CSS 形状居中,只要您能够将元素分成两部分,并使用 CSS 将两部分重新组合在一起即可。
这种技巧确实很巧妙 - 我错过了您之前的那篇文章,所以这让我意识到
shape-outside
实际上可以与图像一起使用。感谢您的分享!Safari 中存在一个 已知错误,它会导致使用
<foreignObject>
解决方法时图像的响应式调整大小失败 - 例如,如果您以em
或vw
单位指定背景图像大小,或者背景图像的px
大小与 SVG 的大小不匹配。所以要么是 Safari 问题,要么是 Firefox 问题,但不会同时出现两者…对于设计师/开发人员来说,有一种方法可以获取原始形状:它们在 Github 上的 Noto 项目中提供。您需要知道表情符号的 Unicode 代码点。在您的第一个示例中,它是
U+1F995
。只需转到https://github.com/googlefonts/noto-emoji/blob/master/svg/emoji_u1f995.svg
您将获得源 SVG 元素。它可能与您根据操作系统或浏览器看到基于字体的表情符号不匹配。但您可以下载该文件,直接包含其源代码,然后从那里开始操作。然后您可以自由地对图形进行重新着色、绘制变体、生成效果,并获得更广泛的浏览器和操作系统支持。
您好 Preethi,在 CSS 中,Unicode 的写法不同,不是 “🦕”!正确的写法是 “\1f995;”
这在 Chrome 中似乎不起作用 ♂️