随着圣诞节的临近,街头巷尾都弥漫着浓浓的节日氛围。这不仅仅是一个普通的节日,更是一年中最适合表达爱意的时刻。今晚的平安夜,你是否想为你的女朋友准备一份特别的礼物?如果你是一位编程爱好者,那么我有一个非常独特且富有创意的想法——用CSS手绘一个可爱的圣诞老人!
可能你会问,为什么要选择CSS绘画?其实,CSS不仅仅是前端开发的基石,它还有着无限的创造潜力。通过精心的设计和编程,我们可以用CSS创造出各种生动的图形和动画,这不仅可以展示你的技术实力,更能以一种极具创意的方式表达你的心意。
在这篇文章中,我将带你一步步制作这个充满圣诞气息的CSS圣诞老人。不论你是编程的初学者,还是有一定基础的开发者,都可以轻松跟随。准备好了吗?让我们一起开启这段编程与创意并存的旅程,用代码绘制出一个温暖的圣诞惊喜吧!
本案例的效果如下图所示:
创建响应式的CSS画布
首先,我们需要创建一个画布(canvas),但这里的“canvas”并非指HTML中的<canvas>元素,而是一个我们将在其中进行绘画的区域。这个画布对我们来说非常有用,因为我们可以用它来定位我们的元素。
我们的目标是制作一个响应式的图像,所以画布和内容将主要使用相对单位,比如百分比(%)或视口最小单位(vmin)。这样做的好处是,无论在什么设备上查看,我们的CSS圣诞老人都能保持良好的显示效果。
利用渐变背景创建辅助网格
为了更方便地定位元素,我们可以添加一个重复的线性渐变来创建背景网格。这个网格将作为我们的绘图辅助工具。
<div class="canvas"></div>
复制
.canvas { width: 80vmin; height: 80vmin; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); border: 1px solid #ddd; background-image: repeating-linear-gradient(transparent 0 9.85%, #ddd 0 10%), repeating-linear-gradient(to right, transparent 0 9.85%, #ddd 0 10%); }
复制
注意:为了能够精确地放置不同的元素,画布必须设置为相对或绝对定位。
这些线条将帮助我们进行位置参考,稍后我们会将它们移除。此外,为了保持颜色的一致性并便于更改,我们将使用CSS变量来定义颜色。
通过这样的准备工作,我们为绘制圣诞老人奠定了基础。接下来的步骤将涉及更具体的CSS技巧,但不用担心,我会逐步引导大家,确保即使是初学者也能轻松跟上。让我们继续,用代码绘制一个充满节日气息的圣诞老人吧!
绘制圣诞老人的头部
在这个阶段,我们用几个简单的圆形和椭圆形创建了圣诞老人的脸、眼睛和脸颊。
绘制脸部: 我们使用一个大圆形来代表圣诞老人的脸。通过设置border-radius属性为50%,我们可以将正方形的div变成一个完美的圆形。
添加眼睛和脸颊: 为了让图像更加生动,我们添加了小圆形来表示眼睛,以及椭圆形来展现脸颊的红晕。在CSS中,我们同样使用border-radius属性来实现眼睛和脸颊的圆润边缘。
定位元素: 为了更精确地放置眼睛和脸颊,我们使用position: absolute;并结合top、left、right属性。通过这种方式,我们可以确保无论脸部大小或位置如何变化,眼睛和脸颊都能保持在正确的位置。
响应式设计: 在CSS中使用相对单位(如%)确保我们的绘制可以在不同尺寸的屏幕上保持响应性。尽管在原始版本中,眼睛和脸颊的位置是相对于整个画布的,但在这个版本中,我们将它们放置在脸部内部,这样做可以更容易地进行管理。
代码优化: 在原始版本中,我使用了box-shadow来复制第二个眼睛和脸颊,但box-shadow需要使用非百分比单位,这导致绘画只是部分响应式。通过复制眼睛和脸颊的元素,我们可以使图像更加稳健和易于维护。
<div class="canvas"> <div class="head"> <div class="cheek"></div> <div class="cheek"></div> <div class="eye"></div> <div class="eye"></div> </div> </div>
复制
.canvas { --skin: #fca; /* 肤色 */ --eyes: #630a; /* 眼睛颜色 */ --cheeks: #f001; /* 脸颊红晕颜色 */ /* ... 其他样式 */ } /* ... 其他样式 */ .head { --positionX: 28%; /* 水平定位 */ --positionY: 63%; /* 垂直定位 */ position: absolute; top: 10%; left: 50%; border-radius: 50%; width: 25%; height: 25%; transform: translate(-50%, 0); background: var(--skin); } .eye { position: absolute; top: var(--positionY); left: var(--positionX); width: 12%; height: 12%; background: var(--eyes); border-radius: 50%; } .eye + .eye { left: auto; right: var(--positionX); } .cheek { position: absolute; top: calc(var(--positionY) + 7%); left: calc(var(--positionX) - 12%); width: 20%; height: 12%; background: var(--cheeks); border-radius: 50%; } .cheek + .cheek { left: auto; right: calc(var(--positionX) - 12%); }
复制
绘制圣诞老人的胡须和小胡子
这一次我们添加了胡须和小胡子。这两个部分的添加让我们的圣诞老人看起来更加生动和真实。
绘制胡须: 胡须是通过一个椭圆形状的div元素来实现的,它位于头部的下方。我们利用border-radius的两个值(分别代表水平轴和垂直轴的半径)来创建这个椭圆形。这种方法允许我们精确地控制椭圆的形状。
添加小胡子: 小胡子位于头部的上方,由两个具有相似样式(只是旋转角度不同)的元素组成,它们并排放置。为了更好地控制两者的样式,我们可以使用相邻兄弟选择器(+)。
<div class="canvas"> <div class="beard"></div> <div class="head"> <div class="cheek"></div> <div class="cheek"></div> <div class="eye"></div> <div class="eye"></div> <div class="mustache"></div> <div class="mustache"></div> <div class="hat"></div> </div> </div>
复制
.canvas { --beard: #eee; /* 胡须颜色 */ --mustache: #fff; /* 小胡子颜色 */ /* ... 其他样式 */ } /* ... 其他样式 */ .beard { position: absolute; top: 10%; left: 50%; width: 30%; height: 40%; background: var(--beard); transform: translate(-50%, 0); border-radius: 100% / 120% 120% 80% 80%; /* 椭圆形胡须的边框半径 */ } .mustache { position: absolute; top: 88%; left: 52%; width: 40%; height: 40%; background: var(--mustache); border-radius: 100% 10% 100% 0; /* 小胡子的边框半径 */ transform-origin: top right; transform: translate(-100%, 0) rotate(25deg); } .mustache + .mustache { left: 48%; border-radius: 10% 100% 0 100%; /* 相邻小胡子的边框半径 */ transform-origin: top left; transform: rotate(-25deg); }
复制
以上就是如何用CSS创建圣诞老人的胡须和小胡子的详细步骤。通过简单的形状和位置调整,我们就能够创造出有趣的效果。这种技术不仅能用来创造节日图像,同样也可以应用到其他各种各样的图形设计中。
绘制圣诞老人的帽子
在这个环节,我们将绘制圣诞老人的帽子,这包括帽子本身和两个伪元素:::before 和 ::after。使用伪元素的好处在于它们的大小和位置将相对于帽子元素,这意味着我们只需修改帽子元素,就可以同时更新所有三个部分。虽然我们可以用三个独立的元素来构建帽子、帽檐和球状饰品,但通过使用伪元素,我们可以更好地练习和展示CSS的能力。
构建帽子主体: 帽子的主体是一个基本的矩形,我们通过给左上角设置一个100%的border-radius,来创建一个漂亮的弯曲边缘。
添加帽子的球状饰品(pompom): 球状饰品很简单,只是一个圆形。我们可以使用border-radius: 50%;来实现。
设计帽子的底部: 对于帽子底部,我们将使用我称之为“管状”(pipe)的形状。我们通过设置一个矩形的border-radius为100% / 50%,使其顶部和底部弯曲,而两侧保持平直。
设置背景渐变: 一旦我们有了这个形状,我们可以添加一个径向渐变作为背景。然后我们就得到了那个弯曲的底部。为了让它更适合头部,我们可能需要对其进行一点旋转。
<div class="canvas"> <div class="beard"></div> <div class="head"> <div class="cheek"></div> <div class="cheek"></div> <div class="eye"></div> <div class="eye"></div> <div class="mustache"></div> <div class="mustache"></div> <div class="hat"></div> </div> </div>
复制
html { background: #bcd; /* 背景色 */ } .canvas { --suit: #d00; /* 帽子颜色 */ /* ... 其他样式 */ } /* ... 其他样式 */ .hat { position: absolute; width: 98%; height: 80%; background: var(--suit); border-radius: 100% 20% 0 0; /* 帽子主体的边框半径 */ top: -40%; left: 50%; transform: translate(-50%, 0) rotate(1deg); } .hat::before { content: ""; /* 重要:即使没有内容,也必须设置content属性 */ display: block; position: absolute; bottom: -17%; left: -5%; width: 110%; height: 40%; border-radius: 100% / 50%; /* 帽子底部的边框半径 */ transform: rotate(-2deg); background: radial-gradient(200% 100% at 50% 100%, #0000 30%, var(--mustache) 31%); /* 底部渐变 */ } .hat::after { content: ""; /* 球状饰品 */ display: block; position: absolute; right: -25%; top: -15%; width: 40%; aspect-ratio: 1; /* 保持宽高比 */ border-radius: 50%; /* 圆形 */ background: var(--beard); /* 球状饰品的颜色 */ }
复制
通过上面的步骤,我们可以完成一个有帽檐和球状饰品的圣诞帽。整个过程不仅锻炼了我们对CSS伪元素的运用,还让我们的圣诞老人看起来更加完整和可爱。
绘制圣诞老人的身体部分
在绘制圣诞老人的身体部分时,我们将使用一个类似钟形的形状,它在CSS中基本上是一个椭圆形,底部角半径较小。关于CSS中的形状,可以阅读我在这里发表的文章获得更多信息。
但身体部分真正有趣的是,我们将使用CSS渐变来绘制腰带和按钮:分别是径向渐变(radial-gradient())和线性渐变(linear-gradient())。
按钮部分是一个简单的从左到右的线性渐变,使用了三种颜色:透明、白色和再次透明。在颜色之间留出一小部分百分比,以增加一些“模糊”效果。
腰带的绘制略微复杂:它是一个圆形(径向)渐变,我们必须玩转这些值以确保它精确地定位在我们想要的位置。它遵循与按钮部分类似的透明-颜色-透明模式:
<div class="canvas"> <div class="body"></div> <div class="beard"></div> <div class="head"> <div class="cheek"></div> <div class="cheek"></div> <div class="eye"></div> <div class="eye"></div> <div class="mustache"></div> <div class="mustache"></div> <div class="hat"></div> </div> </div>
复制
.canvas { --belt: #222; /* 腰带颜色 */ /* ... 其他样式 */ } /* ... 其他样式 */ .body { position: absolute; top: 35%; left: 50%; width: 50%; height: 50%; background: var(--suit); /* 身体颜色 */ border-radius: 100% / 150% 150% 25% 25%; /* 身体形状的边框半径 */ transform: translate(-50%, 0); background-image: radial-gradient(circle at 50% -50%, transparent 75%, var(--belt) 75.1% 83%, transparent 83.1%), linear-gradient(to right, transparent 42%, white 42.2% 57%, transparent 57.2%); }
复制
注意,在身体的渐变中,后一个渐变不是恰好从前一个渐变结束的地方开始,而是添加了一个小数点。这是因为浏览器对CSS渐变的边缘处理过于锐利(SVG则不会),这个小数点有助于平滑边缘。
现在,我们的圣诞老人身体部分就完成了。但看起来可能有些单调,接下来我们需要通过添加一些装饰来改善它,让圣诞老人看起来更加生动和有趣。
为圣诞老人的身体添加细节
为圣诞老人的身体添加细节是赋予我们作品生命力的关键一步。
首先,我们会添加按钮,它们将是单独的圆形元素,通过不同的阴影来实现立体效果。这与我们之前为眼睛使用的技术类似,但阴影将垂直放置,而不是水平放置。
腰带扣其实就是一个矩形!我们在其周围添加金色边框,边框半径略微增加一点(我们不想要一个椭圆形)。背景也将是金色的,但通过一个内嵌的box-shadow,我们可以突出显示扣环。
在一些圣诞老人的插画中,许多都将圣诞老人外套的底部画成白色。因此,我们可以扩展身体上的径向渐变,让它结束于白色而不是透明。
<div class="canvas"> <div class="body"> <div class="belt"></div> </div> <div class="beard"></div> <div class="head"> <div class="cheek"></div> <div class="cheek"></div> <div class="eye"></div> <div class="eye"></div> <div class="mustache"></div> <div class="mustache"></div> <div class="hat"></div> </div> </div>
复制
.canvas { --belt-buckle: gold; /* 腰带扣颜色 */ /* ... 其他样式 */ } /* ... 其他样式 */ .body { /* ... */ background-image: /* 按钮 */ radial-gradient(circle at 50% 36%, var(--belt) 2.75%, #0000 3%), radial-gradient(circle at 50% 48%, var(--belt) 3%, #0000 3.25%), radial-gradient(circle at 50% 60%, var(--belt) 2.75%, #0000 3%), radial-gradient(circle at 50% 90%, var(--belt) 2.25%, #0000 2.5%), /* 腰带 */ radial-gradient(circle at 50% -50%, transparent 75%, var(--belt) 75.1% 83%, transparent 83.1%), /* 底部翻边 */ linear-gradient(to right, transparent 42%, white 42.2% 57%, transparent 57.2%); clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 51% 100%, 50% 96%, 49% 100%, 0% 100%); } .belt { /* ... */ background: linear-gradient(var(--belt-buckle) 0 0) 75% 50% / 25% 12% no-repeat, linear-gradient(var(--belt) 0 0) 50% 50% / 85% 80% no-repeat, var(--belt-buckle); }
复制
注意到按钮有不同的大小,但它们看起来大小相同。这是因为尺寸是从最远的角到按钮计算的,所以如果我们为所有按钮设置相同的百分比,它们实际上会有不同的大小。
最后,我们添加了一个clip-path来修剪按钮部分的底部,使其看起来像是外套重叠在一起。
通过这些步骤,我们的圣诞老人身体部分就更加丰富和完整了。添加细节不仅能让视觉效果更加吸引人,也能提高作品的整体质感。现在,圣诞老人的形象更加生动,为节日氛围增添了欢乐和温馨。
绘制圣诞老人的手臂
圣诞老人的手臂将采用与身体相同的钟形形状,但这个钟形会更短更宽。这样,当我们将它放置在身体后面时,它会在两侧“溢出”。
通过添加从透明到半透明黑色的小垂直渐变,手臂在视觉上与身体产生距离。这种渐变效果看起来像是阴影,并强调了手臂的后置位置。
手部同样简单,就是一个圆形。与眼睛或按钮的绘制方法相同。我们本可以选择更复杂的形状(甚至是椭圆形),但我必须承认我不擅长绘制手部……所以这里用一个圆形就可以了:
<div class="canvas"> <div class="hand"></div> <div class="hand"></div> <div class="arms"></div> <div class="body"> <div class="belt"></div> </div> <div class="beard"></div> <div class="head"> <div class="cheek"></div> <div class="cheek"></div> <div class="eye"></div> <div class="eye"></div> <div class="mustache"></div> <div class="mustache"></div> <div class="hat"></div> </div> </div>
复制
.arms { position: absolute; top: 37%; left: 50%; transform: translate(-50%, 0); width: 65%; height: 40%; background: #a00; /* 手臂的颜色 */ border-radius: 100% / 170% 170% 25% 25%; /* 手臂的形状 */ background-image: linear-gradient(transparent 20%, #0003); /* 手臂的渐变阴影 */ } .hand { --positionX: 18%; /* 手的水平定位 */ position: absolute; top: 70%; left: var(--positionX); width: 13%; height: 13%; background: var(--belt); /* 手的颜色 */ border-radius: 50%; /* 手的圆形 */ } .hand + .hand { left: auto; right: var(--positionX); }
复制
现在,我们的圣诞老人的上半部分已经完成了。这甚至可以作为网站的一个可爱元素(例如,从页面底部动画弹出)。通过这些步骤,我们的圣诞老人变得越来越可爱,为网站添加了节日的气息和趣味性。
绘制圣诞老人的腿部
圣诞老人的腿部将由两部分组成:腿本身和靴尖(只有尖部,因为靴子将通过腿部上的线性渐变来绘制)。
我们绘制矩形作为腿部,使用我们之前为小胡子用过的相邻兄弟选择器稍微分开它们,添加红色到黑色的渐变来区分裤子和靴子……然后稍微倾斜它们(使用skew()),这样它们看起来不会太对称。
最后,对于靴尖,我们使用::after伪元素,并且圆滑顶部的角:
<div class="canvas"> <div class="hand"></div> <div class="hand"></div> <div class="arms"></div> <div class="leg"></div> <div class="leg"></div> <div class="body"> <div class="belt"></div> </div> <div class="beard"></div> <div class="head"> <div class="cheek"></div> <div class="cheek"></div> <div class="eye"></div> <div class="eye"></div> <div class="mustache"></div> <div class="mustache"></div> <div class="hat"></div> </div> </div>
复制
.leg { position: absolute; top: 75%; left: 29%; width: 19%; height: 25%; background: var(--suit); /* 腿部的颜色 */ transform: skew(2deg); /* 腿部的倾斜 */ background-image: linear-gradient(#0002, transparent 70%, var(--belt) 0); /* 裤子和靴子的分界线 */ } .leg + .leg { left: 52%; /* 第二条腿的位置 */ } .leg::after { content: ""; display: block; position: absolute; bottom: 0; left: -6%; width: 110%; height: 20%; background: black; /* 靴尖的颜色 */ border-radius: 50% / 100% 100% 0 0; /* 靴尖的圆角 */ } .leg + .leg::after { left: -4%; /* 第二个靴尖的位置 */ }
复制
通过上述代码,我们的圣诞老人就绘制完成了……但它孤零零地漂浮在灰色的虚空中看起来有些悲伤。让我们添加一些背景景观来营造氛围。
添加地面和一些雪花
添加地面和一些雪花可以让我们的圣诞老人图画更加完整,尽管这一步是可选的。我们将从地面开始,因为它更简单。我们甚至不需要新增一个元素!我们可以使用<canvas>的::before伪元素。
我们将制作一个非常大的地面,大到它会溢出视口,我们需要在文档的<body>中添加overflow: hidden,以避免出现烦人的滚动条。
然后我们将其放置在画布的底部,并添加一点微小的弯曲度(通过制作一个倒置的钟形!)。就这样,我们的圣诞老人站在了一个小山丘上。
雪花的步骤也相当简单。我们将通过向<body>添加一系列径向渐变来创建它,每一个都是一个不同大小的背景图像(这样它们看起来更不规则)。
注意:background-image允许多个值,只要它们由逗号分隔。同样的原则适用于background-position、background-repeat、background-size...
结果看起来是这样的:
html { background: #abc; /* 背景色 */ overflow: hidden; background-image: radial-gradient(circle at 50% 50%, white 2.5%, transparent 0), radial-gradient(circle at 30% 90%, white 1.5%, transparent 0), radial-gradient(circle at 70% 10%, white 1%, transparent 0), radial-gradient(circle at 10% 40%, white 1%, transparent 0); background-size: 45vmin 35vmin, 50vmin 70vmin, 60vmin 50vmin, 65vmin 60vmin; background-position: 0 0; } .canvas::before { content: ""; display: block; position: absolute; top: 90%; left: 50%; width: 200vmax; height: 200vmax; background: white; /* 地面颜色 */ transform: translate(-50%, 0) rotate(1deg); border-radius: 100% / 20%; /* 地面的弯曲度 */ } /* ... */
复制
通过上述代码,我们的圣诞老人图画就完成了。最后,我们需要稍微清理一下,移除作为指导线的网格,这样我们的圣诞老人就可以在一个冬日美景中展现了。
给场景添加动画
给场景添加动画可以让我们的静态绘图活跃起来:
圣诞老人的眨眼动画:通过简单的动画,让眼睛的高度从当前值变为零,然后再变回来。我们可能需要添加一个垂直位移动画,以获得更好的效果。
胡子的动画:这也是一个简单的动画,但因为我们需要同步两侧的胡子(记住它是两部分!),所以开始会有点“混乱”。通过调整时间和角度,可以获得很好的效果。
下落的雪花动画:我们可以通过动画background-position来使其看起来像雪花在下落。垂直下落很容易实现,但看起来不够真实。雪花在下落时会做锯齿形的运动,所以我们将在动画中添加这种锯齿形运动。
注意:动画的真正挑战在于时间控制。如果所有动画部分都使用相同的时间函数并且持续相同的时间,动画看起来会很假。混合不同的动画会使其看起来更自然、更美观……不幸的是,我在这方面并不擅长。作为参考,你可以查看Adam Kuhn、Sarah Drasner或Jhey Tompkins的作品。他们在这方面确实很了不起。
以下是动画的CSS代码示例:
@keyframes snow { 0% { background-position: 0 0, 0 0, 0 0, 0 0; } 40% { background-position: 10px 14vmin, -20px 28vmin, 20px 20vmin, 10px 24vmin; } 60% { background-position: -10px 21vmin, -30px 42vmin, 30px 30vmin, 15px 36vmin; } 100% { background-position: 0 35vmin, 0 70vmin, 0 50vmin, 0 60vmin; } } @keyframes blink { 0%, 6%, 100% { height: 12%; } 3% { height: 0%; } } @keyframes moveMustache { 0%, 40%, 44%, 100% { transform: translate(-100%, 0) rotate(25deg); } 42% { transform: translate(-100%, 0) rotate(30deg); } } @keyframes moveMustache2 { 0%, 40%, 44%, 100% { transform: rotate(-25deg); } 42% { transform: rotate(-30deg); } } html { animation: snow infinite 7s linear; /* ... */ } .eye { animation: blink 5s infinite linear; /* ... */ } .mustache { animation: moveMustache 7s infinite linear; /* ... */ } .mustache + .mustache { animation: moveMustache2 7s infinite linear; /* ... */ } /* ... */
复制
重要的是要考虑用户的意愿,如果用户选择减少运动(特别是考虑到辅助功能),则应该禁用动画。我们可以使用prefers-reduced-motion媒体功能来实现这一点。
@media (prefers-reduced-motion) { * { animation: none !important; } }
复制
这个选择器过于泛化。如果你在网站上嵌入了这个圣诞老人的绘图,你可能需要调整它,以免影响你页面上的其他动画。
让辅助技术识别我们的CSS艺术作品
CSS艺术绘图虽然不能像图片那样直接添加替代文本,但我们可以采取措施让辅助技术识别我们的CSS艺术作品。如果我们希望辅助技术能够识别我们的圣诞老人绘图,并为其提供描述,那么添加适当的辅助功能将是一个好方法。
在这种情况下,我们需要在绘图的根部添加一个角色(role)为img,并且在根部也添加一个aria-label:
<div class="canvas" role="img" aria-label="一个站在雪地小山上的圣诞老人卡通形象。"> <!-- ... --> </div>
复制
通过这样做,我们就完成了使CSS艺术作品更易于辅助技术访问的过程。
此外,您可以随意添加更多细节:增加眉毛会很好,帽子下露出一些头发,圣诞老人周围放一些礼物,甚至在某个地方添加一个驯鹿!
关于响应性的最后说明
目前,绘图位于.canvas根元素内部,其宽度和高度为80vmin。由于vmin是一个响应式单位(取决于视图框架的大小),绘图会适应屏幕大小,但这可能不是我们想要的效果。
我们可能希望将绘图添加到页面中的特定空间,那时vmin单位可能会成为问题。不用担心。我们做一个小改动来解决这个问题:
.canvas { width: 80vmin; aspect-ratio: 1; /* 移除 height */ /* ... */ }
复制
通过移除高度并指定aspect-ratio为1,画布将始终保持正方形。由于我们在所有尺寸和背景中使用了百分比,我们可以将宽度改变为我们想要的任何值,绘图都会很好地缩放。例如,将宽度设置为200像素后,效果如下:
同样的圣诞老人绘图,只是更小了。
就这样!我们创建了一个带有圣诞老人的动画场景,在这个过程中,我们练习了很多CSS:
动画(Animations)
背景(Backgrounds)
边框半径(Border-radius)
盒子阴影(Box-shadow)
组合器(Combinators)
渐变(Gradients)
溢出(Overflow)
定位(Positioning)
伪元素(Pseudo-elements)
变形(Transforms)
单位和颜色(Units & colors)
变量(Variables)
宽高比(Aspect ratio)
最终代码
<div class="canvas" role="img" aria-label="一个站在雪地小山上的圣诞老人卡通形象。"> <div class="hand"></div> <div class="hand"></div> <div class="arms"></div> <div class="leg"></div> <div class="leg"></div> <div class="body"> <div class="belt"></div> </div> <div class="beard"></div> <div class="head"> <div class="cheek"></div> <div class="cheek"></div> <div class="eye"></div> <div class="eye"></div> <div class="mustache"></div> <div class="mustache"></div> <div class="hat"></div> </div> </div>
复制
@keyframes snow { 0% { background-position: 0 0, 0 0, 0 0, 0 0; } 40% { background-position: 10px 14vmin, -20px 28vmin, 20px 20vmin, 10px 24vmin; } 60% { background-position: -10px 21vmin, -30px 42vmin, 30px 30vmin, 15px 36vmin; } 100% { background-position: 0 35vmin, 0 70vmin, 0 50vmin, 0 60vmin; } } @keyframes blink { 0%, 6%, 100% { height: 12%; } 3% { height: 0%; } } @keyframes moveMustache { 0%, 40%, 44%, 100% { transform: translate(-100%, 0) rotate(25deg); } 42% { transform: translate(-100%, 0) rotate(30deg); } } @keyframes moveMustache2 { 0%, 40%, 44%, 100% { transform: rotate(-25deg); } 42% { transform: rotate(-30deg); } } @media (prefers-reduced-motion) { * { animation: none !important; } } html { background: #abc; overflow: hidden; background-image: radial-gradient(circle at 50% 50%, white 2.5%, transparent 0), radial-gradient(circle at 30% 90%, white 1.5%, transparent 0), radial-gradient(circle at 70% 10%, white 1%, transparent 0), radial-gradient(circle at 10% 40%, white 1%, transparent 0); background-size: 45vmin 35vmin, 50vmin 70vmin, 60vmin 50vmin, 65vmin 60vmin; background-position: 0 0; animation: snow infinite 7s linear; } .canvas { --skin: #fca; --eyes: #630a; --cheeks: #f001; --beard: #eee; --mustache: #fff; --suit: #a00; --belt: #222; --belt-buckle: gold; width: 60vmin; aspect-ratio: 1; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } .canvas::before { content: ""; display: block; position: absolute; top: 90%; left: 50%; width: 200vmax; height: 200vmax; background: white; transform: translate(-50%, 0) rotate(1deg); border-radius: 100% / 20%; } .head { --positionX: 27%; --positionY: 63%; position: absolute; top: 10%; left: 50%; border-radius: 50%; width: 25%; height: 25%; transform: translate(-50%, 0); background: var(--skin); } .eye { position: absolute; top: var(--positionY); left: var(--positionX); width: 12%; height: 12%; background: var(--eyes); border-radius: 50%; animation: blink 5s infinite linear; } .eye + .eye { left: auto; right: var(--positionX); } .cheek { position: absolute; top: calc(var(--positionY) + 7%); left: calc(var(--positionX) - 12%); width: 20%; height: 12%; background: var(--cheeks); border-radius: 50%; } .cheek + .cheek { left: auto; right: calc(var(--positionX) - 12%); } .beard { position: absolute; top: 10%; left: 50%; width: 30%; height: 40%; background: var(--beard); transform: translate(-50%, 0); border-radius: 100% / 120% 120% 80% 80%; } .mustache { position: absolute; top: 88%; left: 52%; width: 40%; height: 40%; background: var(--mustache); border-radius: 100% 10% 100% 0; transform-origin: top right; transform: translate(-100%, 0) rotate(25deg); animation: moveMustache 7s infinite linear; } .mustache + .mustache { left: 48%; border-radius: 10% 100% 0 100%; transform-origin: top left; transform: rotate(-25deg); animation: moveMustache2 7s infinite linear; } .hat { position: absolute; width: 98%; height: 80%; background: var(--suit); border-radius: 100% 20% 0 0; top: -40%; left: 50%; transform: translate(-50%, 0) rotate(1deg); } .hat::before { content: ""; display: block; position: absolute; bottom: -17%; left: -5%; width: 110%; height: 40%; border-radius: 100% / 50%; transform: rotate(-2deg); background: radial-gradient(200% 100% at 50% 100%, #0000 30%, var(--mustache) 31%); } .hat::after { content: ""; display: block; position: absolute; right: -25%; top: -15%; width: 40%; aspect-ratio: 1; border-radius: 50%; background: var(--beard); } .body { position: absolute; top: 35%; left: 50%; width: 50%; height: 50%; background: var(--suit); border-radius: 100% / 150% 150% 25% 25%; transform: translate(-50%, 0); background-image: /* buttons */ radial-gradient(circle at 50% 36%, var(--belt) 2.75%, #0000 3%), radial-gradient(circle at 50% 48%, var(--belt) 3%, #0000 3.25%), radial-gradient(circle at 50% 60%, var(--belt) 2.75%, #0000 3%), radial-gradient(circle at 50% 90%, var(--belt) 2.25%, #0000 2.5%), /* belt */ radial-gradient(circle at 50% -50%, transparent 75%, var(--belt) 75.1% 83%, transparent 83.1%), /* flap */ linear-gradient(to right, transparent 42%, white 42.2% 57%, transparent 57.2%); clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 51% 100%, 50% 96%, 49% 100%, 0% 100%); } .belt { position: absolute; top: 75%; left: 50%; transform: translate(-50%, -50%); width: 23%; height: 15%; background: linear-gradient(var(--belt-buckle) 0 0) 75% 50% / 25% 12% no-repeat, linear-gradient(var(--belt) 0 0) 50% 50% / 85% 80% no-repeat, var(--belt-buckle); } .arms { position: absolute; top: 37%; left: 50%; transform: translate(-50%, 0); width: 65%; height: 40%; background: #a00; border-radius: 100% / 170% 170% 25% 25%; background-image: linear-gradient(transparent 20%, #0003); } .hand { --positionX: 18%; position: absolute; top: 70%; left: var(--positionX); width: 13%; height: 13%; background: var(--belt); border-radius: 50%; } .hand + .hand { left: auto; right: var(--positionX); } .leg { position: absolute; top: 75%; left: 29%; width: 19%; height: 25%; background: var(--suit); transform: skew(2deg); background-image: linear-gradient(#0002, transparent 70%, var(--belt) 0); } .leg + .leg { left: 52%; } .leg::after { content: ""; display: block; position: absolute; bottom: 0; left: -6%; width: 110%; height: 20%; background: black; border-radius: 50% / 100% 100% 0 0; } .leg + .leg::after { left: -4%; }
复制
结束
在这篇文章中,我们探索了如何使用CSS技术来创作一个动态的圣诞老人场景。从构建圣诞老人的各个部分(如头部、眼睛、胡子、帽子、身体、手臂、腿部)到为这些部分添加细节和动画,我们逐步构建了这个温馨的节日形象。通过使用变量、伪元素、渐变、边框半径和动画关键帧等CSS功能,我们不仅制作出了一个有趣的圣诞老人图像,还实现了雪花飘落的效果,让整个场景更加生动。
为了提升可访问性,我们还使用了role和aria-label属性,使得这个CSS艺术作品对于使用辅助技术的用户也是可访问的。同时,我们考虑到不同用户的需求,通过媒体查询prefers-reduced-motion来适配那些偏好减少动画的用户。
总的来说,这个项目不仅是一次对CSS技术的深入练习,也是一个创造节日氛围的有趣方式。无论你是一个热爱编程的专业人士,还是对网页设计有兴趣的爱好者,这个项目都能提供一种创造性的方式来庆祝节日,同时锻炼你的技术技巧。通过这样的实践,我们可以看到,CSS不仅仅是用来构建网站布局的工具,它还可以成为创造艺术的画布。
希望你喜欢这个小项目,并且能够在你自己的项目中找到灵感和乐趣!圣诞快乐!🎅🎄✨