使用 Emoji 创建 CSS 形状

Avatar of Preethi
Preethi

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费积分!

CSS 形状是一个标准,它允许我们在浮动元素上创建几何形状,使这些元素周围的内联内容(通常是文本)沿着指定的形状包裹。

这种形状的文本流在编辑设计或处理文本密集内容的设计中效果很好,可以从文本块中添加一些视觉上的缓解。

以下是一个使用 CSS 形状的示例

shape-outside 属性使用基本形状函数之一(circle()ellipse()polygon()inset())或图像来指定浮动区域的形状,如下所示

内联内容沿着左浮动元素的右侧和右浮动元素的左侧包裹。

在这篇文章中,我们将使用 CSS 形状和表情符号的概念来创建有趣的文本包裹效果。图像都是矩形。我们在 CSS 中绘制的许多形状也都是方块,或者至少限于标准形状。另一方面,表情符号提供了打破常规的绝佳机会!

以下是我们的操作方法:首先,我们将从表情符号创建一个图像,然后将其浮动并应用 CSS 形状。

我已经在这篇关于 创意背景图案 的文章中介绍了多种将表情符号转换为图像的方法。在那篇文章中,我说我无法弄清楚如何使用 SVG <text> 进行转换,但我现在已经解决了这个问题,并在本文中向您展示了如何操作。  您不必阅读过那篇文章才能理解本文,但如果您想了解更多信息,可以点击链接阅读。

让我们创建一个表情符号图像

我们用来创建表情符号图像的三个步骤是

  • 在 SVG 中创建一个表情符号形状的剪切
  • 通过 URL 编码并将 data:image/svg+xml 添加到前面来将 SVG 代码转换为 DataURL
  • 使用 DataURL 作为元素 background-imageurl() 值。

以下是用 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 中,这样我们就可以轻松地在 backgroundshape-outside 属性中引用它,而无需多次重复那个长长的编码 SVG 字符串。

现在,任何靠近浮动 .emoji 元素的内联内容都将以表情符号的形状流动。我们可以使用 marginshape-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#leftSidep#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 将两部分重新组合在一起即可。