如何创建纯 CSS 插图并使其动起来 - 第 1 部分基础知识更多高级概念

2025-05-24

如何创建纯 CSS 插图并使其动起来 - 第一部分

基础知识

更高级的概念

我一直对设计、插画和配色方案非常感兴趣,但过去几年我一直专注于成为一名更优秀的前端开发者,几乎没有时间练习我的创意技能。当我第一次接触到 CSS 图像时,我迫不及待地想尝试一下。终于,我可以一边写代码,一边玩转各种形状和颜色,探索和发展我的创造力了!

但首先,什么是纯 CSS 图像?

纯 CSS 图片是指使用 HTML 和 CSS 构建的插图。它不使用图片文件导入,也不使用在插图软件中导出图片生成的代码。换句话说,它是完全在代码编辑器中手动编码的图片,仅使用 HTML 和 CSS。

原理很简单:使用 HTML,您可以创建任意数量的 div,每个 div 代表最终图像组件的基本形状。使用 CSS 属性(例如渐变、变换、边框半径、阴影等),您可以变换这些基本形状,并将它们排列成美观的插图。

为什么使用 CSS 图像?

但你可能会问,CSS 图像的意义何在?毕竟,CSS 的主要作用是为网页设计样式,而且还有更灵活高效的工具可以为网页设计制作高质量、轻量级的图形(比如 SVG)。事实上,使用 CSS 进行插图绘制不仅存在一些设计限制,而且结果可能过于复杂、耗时,并面临一些严重的跨浏览器/设备问题。

所以,CSS 图像肯定有其适用之处。然而,创作 CSS 插图是提高 CSS 水平的好方法,还能学习新的工具和概念,例如动画、预处理器或一些鲜为人知的 CSS 属性。自从我开始编写 CSS 图像代码以来,我的 CSS 技能突飞猛进,而且我对一些以前不太了解的概念也更加熟悉了,比如各种各样的 CSS 选择器、3D 变换和关键帧动画。

它适合谁?

CSS 插图非常适合:

  • 希望利用自己的设计技能学习或增强对 html/css 的信心的插画师或设计师
  • 希望发挥创造力并培养良好设计眼光的前端开发人员
  • 任何想在加强 CSS 技能的同时获得一些乐趣的人
  • 任何希望与社区建立联系、激励他人并受到启发的人
  • 或者任何愿意接受挑战的人

在本系列中,我们将学习如何创建三个 CSS 插图,涵盖从简单到复杂的各种元素。我们将学习 CSS 动画的基础知识以及如何使用它们来制作插图动画。在此过程中,我们将了解哪些概念、工具和技巧可以帮助我们加快工作流程。

第 1 部分:通过 CSS 笑脸学习基础知识和工作流程技巧
第 2 部分:通过 CSS 宝丽来介绍 CSS 动画
第 3 部分:通过 CSS 灯塔场景介绍更高级的技术

虽然本教程系列不需要任何高级的 Web 开发知识,但我假设您至少熟悉 HTML 和 CSS。

在我们开始之前有几点建议:

  • 如果你还没有CodePen账户,那就赶紧注册一个吧。这会省去你设置项目的麻烦,尤其是因为我们会用到 CSS 预处理器和模板语言。
  • 使用 Chrome 或 Firefox,因为其他浏览器已被证明存在 CSS 插图错误。

基础知识

好了,说得够多了,让我们开始制作我们的第一个 CSS 图像!

这是一个圆圈:

<div class="circle"></div>
Enter fullscreen mode Exit fullscreen mode
html,
body {
  height: 100%;
  width: 100%;
  overflow: hidden;
  padding: 0;
  margin:0;
}
body {
  background: #FEEE9D;
}
.circle {
  position: absolute;
  width: 300px;
  height: 300px;
  transform: translate(-50%, -50%);
  top: 50%;
  left: 50%;
  border-radius: 50%;
  background-color: #FBD671;
}
Enter fullscreen mode Exit fullscreen mode

到目前为止没有什么令人印象深刻的。

我们要添加一些元素,把这个圆圈变成笑脸。这个圆圈就是笑脸的头部,我们可以添加眼睛和嘴巴:

<div class="head">
  <div class="face">
    <div class="mouth"></div>
    <div class="eye-group">
      <div class="eye eye-left"></div>
      <div class="eye eye-right"></div>
    </div>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode
html,
body {
  height: 100%;
  width: 100%;
  overflow: hidden;
  padding: 0;
  margin: 0;
}
body {
  background: #FEEE9D;
}
* {
  position: absolute;
}
.head {
  width: 300px;
  height: 300px;
  transform: translate(-50%, -50%);
  top: 50%;
  left: 50%;
  border-radius: 50%;
  background-color: #FBD671;
}
.face {
  width: 150px;
  height: 170px;
  left: 75px;
  top: 75px;
}
.mouth {
  width: 100%;
  height: 75px;
  bottom: 0;
  left: 0;
  background-color: #20184E;
  border-radius: 10px 10px 150px 150px;
  border: 5px solid #20184E;
}
.eye-group {
  width: 150px;
  height: 50px;
  top: 10px;
  left: 0;
}
.eye {
  background-color: #20184E;
  width: 30px;
  height: 50px;
  border-radius: 50%;
}
.eye-left {
  left: 15px;
}
.eye-right {
  right: 15px;
}
Enter fullscreen mode Exit fullscreen mode

好的,让我们看看这里发生了什么。

主容器

我们有一个主容器,在本例中是.head元素,它包含所有其他 HTML 元素。正如你所期望的,它将我们的插图居中,并作为其他所有内容定位的参考。

绝对定位

所有元素都具有该position: absolute属性。借助 top/right/bottom/left 属性,可以精确地将它们相对于父元素进行定位。需要注意的是,绝对定位会将元素从页面的自然流中移除。这意味着具有该属性的元素的位置不会影响其他元素的位置,也不会受到其他元素位置的影响。默认position: absolute为所有元素分配该属性将确保它们彼此独立。更多关于定位的信息,请点击此处

* {
  position:absolute;
}
Enter fullscreen mode Exit fullscreen mode

嵌套

按照这个逻辑,我们使用嵌套将元素组合在一起。观察.face元素。它不是图像的实际组成部分,而仅用于将眼睛和嘴巴组合在一起。.mouth.eye-group的位置(和大小,如果我们使用%而不是px)都将引用.face。例如,如果我们决定稍后重新定位头部的脸部,我们可以立即完成,而不必调整.mouth和的属性.eyes。这是基本的CSS逻辑,如果您有UI开发经验,这对您来说并不陌生。根据经验,嵌套可以提供更清晰的结构,因为它将属于一起的元素分组,并使插图更易于操作。

堆叠

使用绝对定位使我们能够更好地控制元素的堆叠顺序。堆叠顺序自然遵循 HTML 元素的流动。第一个对象将位于堆叠的底部(最远),而最后一个对象将位于顶部(最靠近您)。使用 z-index 属性,我们可以更改堆叠中每个元素的位置,并使它们按所需的方式重叠,前提是这些元素属于同一个堆叠上下文。z-index 的值越高,它在堆叠中的位置就越高。

堆叠上下文有点棘手,它并不总是按照你预期的方式运行。你可以在这里阅读更多关于触发创建新堆叠上下文的信息。

仅限课程

我们仅使用 CSS 类来定位和设置 HTML 元素的样式,因为我们不想受到特殊性问题的困扰。


呼,已经说了这么多了。但这些对于 CSS 插图,乃至整个 CSS 来说,都是非常重要的概念。一旦你熟悉了定位和堆叠,你的 CSS 技能就会大幅提升。

现在我们已经对如何定位元素有了基本的了解,让我们来稍微美化一下笑脸。我想添加一些细节,比如舌头、瞳孔和阴影。

阴影很简单,但却增添了美感:

.head {
  width: 100%;
  height: 100%;
  background-color: #FBD671;
  border-radius: 50%;
  box-shadow:inset -10px -10px 0px #EFBB42;
}
Enter fullscreen mode Exit fullscreen mode

舌头是一个简单的粉色圆圈,但我们只想显示它的一部分,以营造它在嘴里的错觉。为此,我们将嵌套.tongue.mouth应用overflow: hidden属性到.mouth.

<div class="head">
  <div class="face">
    <div class="mouth">
      <div class="tongue"></div>
    </div>
    <div class="eye-group">
      <div class="eye eye-left"></div>
      <div class="eye eye-right"></div>
    </div>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode
.mouth {
  width: 100%;
  height: 75px;
  background-color: #20184E;
  left: 0;
  bottom: 0;
  border-radius: 10px 10px 150px 150px;
  border: 5px solid #20184E;
  overflow:hidden;
}
.tongue {
  width: 100px;
  height: 80px;
  left: 25px;
  top: 30px;
  background-color: #F15962;
  border-radius: 50%;
}
Enter fullscreen mode Exit fullscreen mode

我们可以在.eye元素内部添加带有简单椭圆形的学生。

<div class="container">
  <div class="head">
    <div class="face">
      <div class="mouth">
        <div class="tongue"></div>
      </div>
      <div class="eye-group">
        <div class="eye eye-left">
          <div class="pupil"></div>
        </div>
        <div class="eye eye-right">
          <div class="pupil"></div>
        </div>
      </div>
    </div>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode
.pupil {
  width: 10px;
  height: 15px;
  top: 5px;
  background-color: #FBD671;
  border-radius: 50%;
}
Enter fullscreen mode Exit fullscreen mode

看起来已经好多了。

更高级的概念

现在我们已经构建了第一个 CSS 图片,让我们回顾一下,看看如何改进代码。虽然这些步骤对于构建 CSS 图片来说并非必需,但我发现它们极大地改善了我的工作流程,并帮助我总体上提高了 CSS 的水平。

CSS预处理器

如果您熟悉CSS 预处理器,您就会知道有更好的方法来实现这一点。我不会深入探讨如何设置预处理器,因为这超出了本文的讨论范围。我强烈建议您使用Codepen,它内置了所有预处理器。您只需在 CSS 设置中选择所需的预处理器即可。

我个人喜欢使用SASS/SCSS,但您可以随意使用任何可用的选项。

预处理器最著名的特性是能够使用变量。预处理器变量的工作方式与 JavaScript 变量类似。您只需声明并赋值一次,就可以在整个代码中重复使用它们。这是一个非常棒的工具,因为它避免了重复,并赋予了您更大的灵活性。让我们在 CSS 中实现一些变量。变量的一个好用途是定义颜色。

SCSS 变量始终以 $ 符号开头:

$black: #20184E;
Enter fullscreen mode Exit fullscreen mode

您可以随意命名它,但它必须以 $ 开头并分配有效的 CSS 属性。

然后你可以像这样使用它:

background-color: $black;
Enter fullscreen mode Exit fullscreen mode

你已经看到了它有多方便。如果我们之后决定要更改这个特定的颜色,只需在一个地方修改,它就会反映在代码中所有使用该变量的地方。此外,对于颜色来说,记住你创建的变量的名称比记住 RGB 或十六进制值要容易得多。

我把新的颜色变量添加到代码顶部,以便我们轻松找到它们。在全局范围内声明变量(而不是在选择器中声明)可以确保我们可以在任何地方使用它们。

$black: #20184E;
$head-color: #FBD671;
$background: #FEEE9D;
$tongue-color: #F15962;
Enter fullscreen mode Exit fullscreen mode

现在我们可以改变我们的 css 属性,使它们指向变量而不是硬编码的十六进制值。

例如:

.mouth {
  width: 100%;
  height: 75px;
  bottom: 0;
  background-color: $black;
  border: 5px solid $black;
  border-radius: 10px 10px 150px 150px;
  overflow: hidden;
}
Enter fullscreen mode Exit fullscreen mode

CSS 现在有了原生变量,这几乎让预处理器变量变得不再必要。然而,预处理器的功能远不止变量,在很多其他方面仍然非常有用。

SCSS 还附带许多辅助函数,包括颜色函数。这些函数非常强大,可以让你非常轻松地操作颜色。

我们来看一下头部的内嵌阴影。目前我们使用的是硬编码的十六进制值,我不得不手动查找。我们将使用 darken 函数来生成这个值:

.head {
  border-radius: 50%;
  width: 100%;
  height: 100%;
  background-color: $head-color;
  box-shadow: inset -10px -10px 0px darken($head-color, 20%);
}
Enter fullscreen mode Exit fullscreen mode

基本上,该函数将$head-color其作为参数,并将黑暗程度增加 20%。

我喜欢使用颜色功能,因为它们不仅消除了借助某些设计软件来生成颜色的需要,而且还有助于为您的插图创建更和谐的调色板。

SASS 的另一个很棒的功能是嵌套。嵌套允许你将选择器嵌套在父选择器中,以便创建快捷方式。它为 CSS 创造了更好的层次结构和可读性,并避免了反复使用选择器。

例如

.pink {
  background-color: pink;
  .purple {
    background-color: purple;
  }

}
Enter fullscreen mode Exit fullscreen mode

将被编译为:

.pink { 
  background-color: pink;
}
.pink .purple { 
  background-color: purple;
} 
Enter fullscreen mode Exit fullscreen mode

SASS 还提供了 & 选择器,它基本上指的是父选择器。所以

.pink {
  background-color: pink;
  &.purple{
    background-color: purple;
  }
}
Enter fullscreen mode Exit fullscreen mode

将被编译为:

.pink { 
  background-color: pink;
}
.pink.purple { 
  background-color: purple;
} 
Enter fullscreen mode Exit fullscreen mode

使用 & 选择器不会.purple像上例一样定位到带有 class 的子元素。它会定位到带有 class .pinkAND的父元素.purple

注意不要嵌套过多,因为它会使你的代码过于复杂,可读性降低,这与我们的预期背道而驰。通常情况下,我倾向于最多 3 层嵌套。

考虑到这一点,让我们在代码中实现嵌套。例如:

.eye-group {
  top: 10px;
  left: 0;
  width: 150px;
  height: 50px;
}
.eye {
  background-color: $black;
  width: 30px;
  height: 50px;
  border-radius: 100%;
}
.eye-left {
  left: 15px;
}
.eye-right {
  right: 15px;
}
Enter fullscreen mode Exit fullscreen mode

变为:

.eye-group {
  top:10px;
  left:0;
  width: 150px;
  height: 50px;
  .eye {
    background-color: $black;
    width: 30px;
    height: 50px;
    border-radius: 100%;
    &.eye-left {
      left:15px;
    }
    &.eye-right {
      right:15px;
    }
  }  
}
Enter fullscreen mode Exit fullscreen mode

预处理器是构建 CSS 图像的利器,能够显著加快您的工作流程。它们还提供更多高级选项,例如函数、循环、混合宏等。这些功能在更复杂的插图中非常有用,我们将在本系列的下一篇中看到。

:before 和 :after

到目前为止,我们为笑脸中的每个形状都创建了一个 div。虽然这完全没问题,但还有一种方法可以减少 HTML 元素的数量。这就是伪选择器的作用:before所在:after

这些伪选择器会自动随您创建的任何 HTML 元素一起提供。因此,对于 HTML 中的任何元素,您都会获得两个额外的容器来添加内容。虽然它们最初并不存在于 DOM 中,但您可以使用 content 属性来定位它们,如下所示:

.some-class:before, .some-class:after { 
  content: "";
}
Enter fullscreen mode Exit fullscreen mode

此属性可用于插入文本或图像等内容。在 CSS 插图中,我们不需要这些,但仍需要使用选择器,可以使用空引号来实现。虽然这看起来像是一个不必要的步骤,但此属性可以确保这些选择器可用,因此请确保它存在。避免忘记它并避免重复的一个好方法是将其默认分配给所有:after和元素::before

*:before, *:after {
  position: absolute;
  content: '';
}
Enter fullscreen mode Exit fullscreen mode

正如您所期望的,:before:after大小和定位取决于其父级。

让我们看看如何在代码中使用这些。考虑.mouth元素。它有一个子元素:.tongue元素。我们将.tongue:after伪选择器替换选择器:

.mouth {
  width: 100%;
  height: 75px;
  bottom: 0;
  background-color: $black;
  border: 5px solid $black;
  border-radius: 10px 10px 150px 150px;
  overflow: hidden;
  &:after {
    background-color: $tongue-color;
    width: 100px;
    height: 80px;
    border-radius: 50%;
    left:25px;
    top:30px;
  }
}
Enter fullscreen mode Exit fullscreen mode

可以应用相同的逻辑来替换.pupil元素:

.eye-group {
  top: 10px;
  width: 150px;
  height: 50px;
  .eye {
    background-color: $black;
    width: 30px;
    height: 50px;
    border-radius: 100%;
    border: 5px solid $black;
    &:after {
      width: 10px;
      height: 15px;
      top: 5px;
      background-color: #FBD671;
      border-radius: 50%;
    }
    &.eye-left {
      left: 15px;
    }
    &.eye-right {
      right: 15px;
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

现在我们可以去掉html 中的.tongue和div:.pupil

<div class="head">
  <div class="face">
    <div class="mouth"></div>
    <div class="eye-group">
      <div class="eye eye-left"></div>
      <div class="eye eye-right"></div>
    </div>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

虽然这并非绝对必要,但我发现这种做法有助于保持代码简洁,并避免 HTML 内容过于拥挤。再次强调,仅在合理的情况下才使用伪选择器。(例如:创建与其父容器在视觉上相关的元素)。

HTML模板语言

改进代码的另一个方法是使用 HTML 模板语言。我喜欢使用Pug,它也内置于 Codepen 编辑器中。

它的工作原理如下:Pug 使用标签名称来表示完整的 HTML 元素。例如,在 Pug 中,<div></div>会被直接翻译为div。它使用缩进来表示嵌套,从而重建 HTML 的树形结构。

在 CSS 图像中,建议仅使用 div 元素,并为其分配一个类,以便轻松定位它们。在 Pug 中使用类表示 div 的方法如下:

正常html:

<div class="container"></div>
```



Pug:



```html
div.container
```



Or, because `div` is the default tag name, it can be omitted:



```html
.container
```



I find this syntax to be much cleaner, and it allows me to focus on the class. Since I already know that all my elements are divs, I don't need any useless syntax polluting my code.

Let's convert our HTML to Pug:



```html
.head
  .face
    .mouth
    .eye-group
      .eye.eye-left
      .eye.eye-right
```



Much cleaner. 

Similarly to CSS preprocessors, there are many things you can do with Pug as it is powered by JavaScript: mixins, includes etc. When it comes to CSS images, one of the most powerful features is loops. We'll see a bit later how to use them.

Here's the final project in CodePen. You can see that none of our latest changes have affected the illustration at all.




Right, we’ve learned a lot already! How to create various shapes and assemble them into a cohesive illustration, how to use hacks to emulate more complex shapes, how to use preprocessors, templating languages and pseudo-selectors to improve our workflow and clean up our code. In the second part of this series, we'll practice these new concepts and build a CSS Polaroid. Then, we'll learn how to animate it.
 
[Part 2: Intro to CSS animations with a CSS Polaroid](https://dev.to/agathacco/how-to-create-pure-css-illustrations-and-animate-them---part-2-1ao4) 
Enter fullscreen mode Exit fullscreen mode
文章来源:https://dev.to/agathacco/how-to-create-pure-css-illustrations-and-animate-them---part-1-1j1k
PREV
如何撰写 SOLID 开发者简历,成为 2018 年 STAR
NEXT
如何保持动力,完成个人项目?什么能让你保持动力?完成副业的技巧 结论