复杂 CSS 插图的建议 时间和练习 描摹是完全可以接受的 注意响应能力 三思而后行 对所有事物使用绝对定位 坚持一种方法 为你的风格保持坚实的结构 处理尴尬的形状 clip-path 是你的朋友 border-radius 是你的另一个朋友 阴影技术 预处理器非常有用 就是这样!

2025-06-09

复杂 CSS 插图的建议

时间和练习

追踪是完全可以接受的

注意响应能力

三思而后行

对所有事物使用绝对定位

坚持一种方法

保持风格的稳固结构

处理不规则形状

clip-path 是你的朋友

border-radius 是你的另一个朋友

阴影技术

预处理器非常有用

就是这样!

如果你问我关于前端开发最常听到的问题是什么,我会说是“如何提高 CSS 水平?”。这个问题通常是在我分享自己制作的 CSS 插图后提出的。我很喜欢在 CodePen 上分享这些内容。

对很多人来说,CSS 就像一头无法驯服的神秘野兽。Chris的这条推文让我忍不住笑了出来,因为虽然听起来很讽刺,但其中却不乏道理。话虽如此,如果我告诉你,你只需要掌握一些属性和技巧,就能创造出任何你想要的东西,你会怎么想?事实是,你确实离它很近了。

我一直想写一篇类似的文章,但这个话题很难涵盖,因为可能性和技巧太多,通常有不止一种方法可以完成同一件事。CSS 插图也是如此。它没有正确或错误的方法。我们都在使用同一个画布。只是有很多不同的工具可以将这些像素绘制到页面上。

虽然 CSS 插图没有“一刀切”的方法,但我可以提供一套可能对您的旅程有所帮助的技术。

时间和练习

CSS 插图需要大量的时间和练习。你追求的越精确,插图越复杂,花费的时间就越长。耗时的部分通常不是决定使用哪些属性以及如何使用,而是不断修改,让它们看起来正确。准备好熟悉浏览器开发工具中的样式检查器吧!如果你还没用过VisBug,我也推荐你试试

Ben Evans 和 Diana Smith 是两位出色的 CSS 艺术家。他们最近都谈到了 CSS 插画创作的时间消耗。

使用 CSS 制作的逼真女性截图

Diana 的 PureCSS Gaze 花了她两个漫长的周末才完成。她在这里和这里分享了一些技巧。“只要你有时间、耐心和动力,就一定可以做到,”她说。

我发布了一张关于杯子的表情包图片,Ben 的回复完美地总结了这一切:

当我第一次看到这条推文时,我很想用 CSS 创建它,但后来想到我的回复大约需要一个月的时间。

这需要时间!

追踪是完全可以接受的

我们通常对想要展示的内容有一个想法。毕竟,这篇文章不是关于设计的。它讲的是如何使用 DOM 和 CSS 渲染图像。我确信这项技术自古以来就存在。不过,最近几个月我一直在分享它。

  • 查找或创建您想要说明的图像。
  • 使用标签将其拉入您的 HTML <img>
  • 将其放置在能够位于插图下方的位置。
  • 降低图像不透明度,使其仍然可见但不会太过明显。
  • 使用 DOM 来追踪它。

令我惊讶的是,这项技术并不常见。但它对于创建精确的 CSS 插图来说非常有价值。

看看这个技巧的实际效果:

请在这里尝试一下:

注意响应能力

如果本文中有两种值得借鉴的技巧,那就是上面的“追踪”和下一个。

市面上有很多很棒的 CSS 插画示例。但遗憾的是,其中一些示例在小屏幕上缺乏样式,甚至无法显示。我们生活在一个科技产品第一印象至关重要的时代。不妨以一个用 CSS 绘制的键盘为例。有人偶然发现了你的作品,在智能手机上打开,却只看到了一半或一小部分插图。他们可能错过了演示中最精彩的部分!

这是我的诀窍:利用视口单位来绘制插图并创建您自己的缩放单位。

对于尺寸和定位,您可以选择使用缩放单位或百分比。这在需要使用框阴影时尤其有用,因为该属性接受视口单位,但不接受百分比。

以我上面创建的CSS egghead.io徽标为例。我找到了想要使用的图像,并用一个img标签将其弹出到 DOM 中。

<image src='egghead.png'/>
Enter fullscreen mode Exit fullscreen mode
img {
  height: 50vmin;
  left: 50%;
  opacity: 0.25;
  position: fixed;
  top: 50%;
  transform: translate(-50%, -50%);
}
Enter fullscreen mode Exit fullscreen mode

高度50vmin是 CSS 插图的期望尺寸。降低不透明度使我们能够在绘制过程中清晰地“追踪”插图。

然后,我们创建一个缩放单位。

/**
  * image dimensions are 742 x 769
  * width is 742
  * height is 769
  * my desired size is 50vmin
*/
:root {
  --size: 50;
  --unit: calc((var(--size) / 769) * 1vmin);
}
Enter fullscreen mode Exit fullscreen mode

确定了图像尺寸后,我们就可以创建一个统一的单位,它会随着图像的缩放而变化。我们知道高度是最大的单位,所以我们以高度为基数来创建一个分数单位。

我们得到如下结果:

--unit: 0.06501950585vmin;
Enter fullscreen mode Exit fullscreen mode

这看起来有点别扭,不过相信我,没关系。我们可以用它来调整插图容器的大小calc()

.egg {
  height: calc(769 * var(--unit));
  position: relative;
  width: calc(742 * var(--unit));
  z-index: 2;
}
Enter fullscreen mode Exit fullscreen mode

如果我们使用百分比或新的--unit自定义属性来设置 CSS 插图容器内的元素样式,我们将获得响应式 CSS 插图……而这只需要使用 CSS 变量进行几行数学运算!

调整此演示的大小,您将看到所有内容始终保持比例,并用作50vmin尺寸约束。

三思而后行

另一个技巧是测量。哎呀,如果你要测量实物,你甚至可以拿卷尺测量!

这看起来可能有点奇怪,但我测量了这个场景。这是我客厅里的电视组合单元。这些测量值以厘米为单位。我用这些值根据电视的实际高度得到了一个响应式单元。我们可以给这个数字——以及所有其他数字——起一个容易记住其用途的名称,这要归功于自定义属性。

:root {
  --light-switch: 15;
  --light-switch-border: 10;
  --light-switch-top: 15;
  --light-switch-bottom: 25;
  --tv-bezel: 15;
  --tv-unit-bezel: 4;
  --desired-height: 25vmin;
  --one-cm: calc(var(--desired-height) / var(--tv-height));
  --tv-width: 158.1;
  --tv-height: 89.4;
  --unit-height: 42;
  --unit-width: 180;
  --unit-top: 78.7;
  --tv-bottom: 114.3;
  --scaled-tv-width: calc(var(--tv-width) * var(--one-cm));
  --scaled-tv-height: calc(var(--tv-height) * var(--one-cm));
  --scaled-unit-width: calc(var(--unit-width) * var(--one-cm));
  --scaled-unit-height: calc(var(--unit-height) * var(--one-cm));
}
Enter fullscreen mode Exit fullscreen mode

一旦我们计算出一个变量,就可以在任何地方使用它。我知道我的电视158.1cm又宽又89.4cm高。我查过手册。但在我的 CSS 插图中,它总是会缩放到25vmin

对所有事物使用绝对定位

这条规则能帮你省去不少敲击键盘的麻烦。通常情况下,你会希望元素能够绝对定位。省省力气,把这条规则放在某个地方吧。

/* Your class name may vary */
.css-illustration *,
.css-illustration *:after,
.css-illustration *:before,
.css-illustration:after,
.css-illustration:before {
  box-sizing: border-box;
  position: absolute;
}
Enter fullscreen mode Exit fullscreen mode

您的键盘会感谢您!

定位是 CSS 中一个比较棘手的概念。您可以阅读 CSS 年鉴,了解更多关于如何使用它的信息。

或者,玩一下这个小型定位游乐场:

坚持一种方法

这是迄今为止最难的事情。你该如何处理 CSS 插图?你该从哪里开始?你应该从最外层开始,然后再逐步深入吗?那样不太好。

你很可能会尝试一些方法,最终找到更好的方案。你肯定会反复尝试,但练习得越多,你就越能发现规律,并找到最适合自己的方法。

我倾向于将我的方法与创建矢量图形(插图由多个图层组成)联系起来。如果需要,可以将其拆分并在纸上绘制草图。但是,要从底部开始,然后逐步向上。这通常意味着先绘制较大的形状,然后再绘制更精细的细节。当需要移动元素时,您可以随时调整堆叠索引。

保持风格的稳固结构

这引出了我们关于结构的问题。尽量避免在插图中使用扁平的 DOM 结构。保持元素原子化可以更轻松地移动插图的各个部分。这也使得显示和隐藏插图的各个部分,甚至稍后为其添加动画变得更加容易。以 CSS Snorlax 演示为例。手臂、脚、头等都是独立的元素。这使得为手臂添加动画比我尝试将它们放在一起要容易得多,因为我可以直接将动画应用于类.snorlax__arm-left

这是我创建演示的延时镜头:

处理不规则形状

有一篇关于 CSS-Tricks 的文章非常精彩,教你如何使用 CSS 创建形状。但是,对于那些比较“别扭”的形状,比如长曲线,甚至是外曲线,该怎么办呢?在这种情况下,我们需要打破常规。诸如overflowborder-radius、 和 之类的属性clip-path会非常有帮助。

参考这个 CSS Jigglypuff 演示。切换复选框。

这就是创建曲线形状的关键!我们有一个比主体大得多的元素,并border-radius应用了 。然后我们将其应用overflow: hidden到主体上,以截断该部分。

我们如何创建外曲线?这个有点棘手。但我喜欢用的一个技巧是transparent使用粗边框元素。然后应用一个border-radius,并根据需要剪掉多余的部分。

如果你点击切换按钮,它会显示我们用来跨越那个角的元素。另一个技巧是叠加一个与背景颜色匹配的圆圈。在我们需要更改背景颜色之前,这样做是没问题的。如果你有一个变量或其他东西来表示该颜色,那就没问题了。但是,这可能会使维护变得有点困难。

clip-path 是你的朋友

你可能已经注意到上一个演示中几个有趣的 CSS 属性,包括clip-path。如果你想创建复杂的 CSS 形状,你很可能需要 clip-path 。当隐藏父框溢出无法满足需求时,它对于截断元素部分尤其有用。

这是我之前制作的一个小演示,展示了不同的clip-path可能性。

还有这个演示,它采用了“CSS 的形状”文章中的想法并用 重新创建clip-path

border-radius 是你的另一个朋友

你需要使用border-radius来创建曲线。一个不常见的技巧是使用“double”语法。这样你就可以为每个角创建水平和垂直半径。

玩一下这个演示,真正体会一下的威力border-radius。我主张全面使用百分比,以保持响应速度。

阴影技术

所有形状都画好了,布局也合理,颜色也都到位了……但还是有地方看起来不对劲。很可能是缺少阴影。

阴影增加了深度,营造出一种逼真的感觉。不妨看看这张 Gal Shir 插画的复刻版。Gal 非常擅长运用阴影和渐变来创作精美的插画。我觉得重新创作一下,并添加一个可以切换阴影的开关,看看效果会很有趣。

box-shadow阴影效果通常由和组合产生background-image

这些属性的关键在于,我们可以将它们堆叠在一个逗号分隔的列表中。例如,演示中的大锅就包含一个用于整个身体的渐变列表。

.cauldron {
  background:
    radial-gradient(25% 25% at 25% 55%, var(--rim-color), transparent),
    radial-gradient(100% 100% at -2% 50%, transparent, transparent 92%, var(--cauldron-color)),
    radial-gradient(100% 100% at -5% 50%, transparent, transparent 80%, var(--darkness)),
    linear-gradient(310deg, var(--inner-rim-color) 25%, transparent), var(--cauldron-color);
}
Enter fullscreen mode Exit fullscreen mode

请注意,这里使用的radial-gradient()和 alinear-gradient()并不总是使用精确的整数值。同样,这些数字是没问题的。事实上,你会花很多时间在样式检查器中调整和修改它们。

它和box-shadow 的作用基本相同。然而,我们也可以用它inset来创建复杂的边框和额外的深度。

.cauldron__opening {
  box-shadow:
    0 0px calc(var(--size) * 0.05px) calc(var(--size) * 0.005px) var(--rim-color) inset,
    0 calc(var(--size) * 0.025px) 0 calc(var(--size) * 0.025px) var(--inner-rim-color) inset,
    0 10px 20px 0px var(--darkness), 0 10px 20px -10px var(--inner-rim-color);
}
Enter fullscreen mode Exit fullscreen mode

当然,有时使用filter:drop-shadow()来获得您想要的效果会更有意义。

Lynn Fisher 的a.singlediv.com 网站就是这些属性应用的一个绝佳范例。不妨浏览一下这个网站,看看其中的一些插图,了解一下如何在插图中巧妙地运用box-shadow它们。background-image

box-shadow它非常强大,你可以用它来创作整幅插画。我曾经开玩笑说要用 CSS 创作一美元的插画。

我使用一个生成器来创建带有单个 div 的插图。但是 Alvaro Montoro更进一步,他编写了一个生成器来代替 div 来实现这个功能box-shadow

预处理器非常有用

虽然预处理器并非必需,但使用它们可以帮助保持代码简洁。例如,Pug 可以加快 HTML 编写速度,尤其是在使用循环处理大量重复元素时。这样,我们就可以限定 CSS 自定义属性的范围,只需定义一次样式,然后在需要的地方覆盖它们。

下面是另一个演示 DRY 结构的示例。花朵使用相同的标记构造,但每个花朵都有自己的索引类,用于应用作用域 CSS 属性。

第一朵花具有以下特性:

.flower--1 {
  --hue: 190;
  --x: 0;
  --y: 0;
  --size: 125;
  --r: 0;
}
Enter fullscreen mode Exit fullscreen mode

这是第一个,所以其他所有花都基于它。注意第二朵花的位置稍微偏右上。只需为相同的自定义属性分配不同的值即可:

.flower--2 {
  --hue: 320;
  --x: 140;
  --y: -75;
  --size: 75;
  --r: 40;
}
Enter fullscreen mode Exit fullscreen mode

就是这样!

继续吧,运用这些技巧,提出你自己的,分享它们,并分享你的 CSS 杰作!嘿,如果你有自己的建议,也请分享!这绝对是通过大量尝试和错误才能学到的东西——对我有用的方法可能与对你有用的方法不同,我们可以从这些不同的方法中学习。

鏂囩珷鏉ユ簮锛�https://dev.to/jh3y/advice-for-complex-css-illustrations-2di0
PREV
CSS动画Google字体
NEXT
CSS 动画指南 - 第三部分 CSS 变量 曲线动画路径 JavaScript 钩子 你真的需要 CSS 动画吗?就是这么简单!🎉