CSS画一个草率的冰淇淋

2,962 阅读4分钟

我正在参加「初夏创意投稿大赛」详情请看:初夏创意投稿大赛

简介

初夏一晃一摇的走到了尾声,高温预警一波波在试探着用来。让我们烦躁的,不止有高温的天气,还有高温的天气。烦躁到什么程度呢?一根冰淇淋解决不了。

那就用最朴实的CSS来画一个冰淇淋吧,画完心里哇凉哇凉的,草率了。

草率的代码

老规矩,简单的代码和码上掘金更搭,码上show一show。

码上掘金

勾勒形状

简单的盘算下,冰淇淋大形可分为头部、身体,再给它来个围巾。

<div class="ice">
  <!-- 头部 -->
  <div class="head"></div>
  <!-- 身体 -->
  <div class="body"></div>
  <!-- 围巾 -->
  <div class="scarf"></div>
  <!-- 穗子 -->
  <div class="hem"></div>
</div>

定义基础色

:root {
  --body: #decd99;
  --line: #e6d2a4;
  --face: #faf2ce;
  --eye: #c4a939;
  --cheek: #f3a15f;
  --mouth: #e0b85f;
  --tongue: #fecabd;
  --scarf: #17c9bf;
  --scarf-deep: #04bea9;
  --scarf-light: rgba($color:#17c9bf, $alpha:0.36);
}

头部输出

大头大头,下雨不愁。那我们就先来画一个大头吧,顺便点出两只眼睛。

大头就比较简单了,矩形加上圆角的设定border-radius: 90px 90px 0 0;就能搞定。

结合borderbox-shadow使用,让眼睛显得稍微立体一点点,然后使用伪类元素:after来画一个相对定位的眼珠。再使用@keyframes设置一个简单的旋转动画模拟眼珠的滚动。

HTML

<div class="head">
  <div class="eye"></div>
  <div class="eye eye-right"></div>
</div>

CSS

/** 冰淇淋容器定位 **/
.ice {
  width: 200px;
  margin: 20px 32px;
  position: relative;
}
/** 大头绘制 **/
.head {
  width: 180px;
  height: 120px;
  background-color: var(--face);
  border-radius: 90px 90px 0 0;
  position: relative;
}
/** 小眼睛 **/
.eye {
  width: 40px;
  height: 40px;
  border-radius: 100%;
  background-color: #fff;
  border: 1px solid #f4f5f6;
  box-shadow: 1px 0 2px rgba(0, 0, 0, 0.16);
  position: absolute;
  top: 50px;
  left: 40px;
  animation: eyeRotate 5s linear infinite;
  &:after {
    content: '';
    width: 12px;
    height: 12px;
    border-radius: 100%;
    background-color: var(--eye);
    box-shadow: inset 0 0 3px white, inset 0 0 5px white;
    position: absolute;
    right: 10px;
    top: 14px;
  }
  &-right {
    left: auto;
    right: 40px;
  }
}
/** 眼珠简单转动 **/
@keyframes eyeRotate {
  0% {
    transform: rotate(0deg);
  }
  50% {
    transform: rotate(180deg);
  }
  100% {
    transform: rotate(0deg);
  }
}

身体力行

身体画起来有点纠结,怎么说呢。我最初是使用常规border法画了一个三角形,但是其实冰淇淋的蛋卷是有点圆滑的,越想越不得劲,就使用transform旋转变形重新画了一个body

HTML

简单又不简单的身体。身体很简单,不简单的是在上面一点点添上纹理。

<div class="body">
  <div class="roll"></div>
  <div class="roll roll2"></div>
  <div class="roll roll3"></div>
  <!-- 循环,调整位置,补充纹理细节... -->
</div>

CSS

使用body结合伪元素来画一个带圆角的三角形。

.body {
  &,
  &:before,
  &:after {
    width: 90px;
    height: 90px;
  }
  & {
    background-color: var(--body);
    border-top-right-radius: 30%;
    transform: rotate(120deg) skewX(-30deg) scale(1,.866);
    position: absolute;
    left: 45px;
    top: 150px;
  }
  &:before,
  &:after {
    content: '';
    background-color: inherit;
    position: absolute;
  }
  &:before {
    transform: rotate(225deg) skewX(-45deg) scale(1.414, .707) translate(0,-50%);
  }
  &:after {
    transform: rotate(-225deg) skewY(-45deg) scale(.707, 1.414) translate(50%);
  }
}
​
// 纹理
.roll {
  width: 10px;
  height: 10px;
  border: 4px solid var(--line);
  background-color: var(--body);
  transform: rotate(240deg) skewX(-30deg) scale(1,.866);
  position: absolute;
  top: 0;
  left: 59px;
  z-index: 1;
  &2 {
    left: 44px;
  }
  &3 {
    left: 50px;
    top: 12px;
  }
  // 一点点调整纹理的位置...
}

冷系围巾

围巾,一圈圈相互独立又层叠在一起的上边框透明的圆角矩形组成的。

围巾的第一圈比较特殊,使用伪元素把圈内部填充起来。

HTML

<div class="ice">
  <!--...-->
  <div class="scarf5"></div>
  <div class="scarf4"></div>
  <div class="scarf3"></div>
  <div class="scarf"></div>
  <div class="scarf2"></div>
</div>

CSS

.scarf {
  width: 192px;
  height: 30px;
  border: 10px solid var(--scarf);
  border-top-color: transparent;
  border-radius: 120% 120% / 120px;
  position: absolute;
  top: 80px;
  left: -16px;
  &:before {
    content: '';
    height: 10px;
    border: 10px solid var(--scarf);
    border-radius: 4px;
    background-color: var(--scarf-deep);
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    z-index: -1;
  }
}
​
.scarf2 {
  width: 192px;
  height: 30px;
  border: 10px solid rgba($color:#17c9bf, $alpha:0.86);
  border-top-color: transparent;
  border-radius: 120% 120% / 120px;
  position: absolute;
  top: 80px;
  left: -16px;
  transform: rotate(354deg);
}

打结的穗边

最后又单独画了带穗边的结。

HTML

<div class="hem">
  <div class="tassel"></div>
  <div class="tassel tassel2"></div>
  <div class="tassel tassel3"></div>
  <div class="tassel tassel4"></div>
  <div class="tassel tassel5"></div>
</div>
<div class="hem hem2">
  <div class="tassel"></div>
  <div class="tassel tassel2"></div>
  <div class="tassel tassel3"></div>
  <div class="tassel tassel4"></div>
  <div class="tassel tassel5"></div>
</div>

CSS

.hem {
  width: 30px;
  height: 90px;
  border-radius: 2px 2px;
  background-color: var(--scarf);
  transform-origin: 0 0;
  transform: rotate(350deg);
  position: absolute;
  top: 142px;
  right: 54px;
  &::after {
    content: '';
    width: 6px;
    height: 80px;
    border-radius: 6px;
    background: linear-gradient(0deg, transparent 0%, var(--scarf-deep) 50%, transparent 100%);
    position: absolute;
    top: 10px;
    left: 12px;
  }
  &2 {
    right: 60px;
    transform: rotate(10deg);
  }
}
.tassel {
  width: 4px;
  height: 10px;
  border-radius: 0 0 4px 4px;
  background: linear-gradient(180deg, var(--scarf-deep) 0%, transparent 100%);
  position: absolute;
  bottom: -10px;
  left: 1px;
}
​
@for $i from 2 through 5 {
  .tassel#{$i} {
    left: ($i - 1) * 6 + 1px;
  }
}

写在最后

用CSS画图形确实太累太累了(特别是要画很多细节的),如果使用svg或许要轻松的多吧。做个草率的小游戏跳过六一过端午,一起来掘个粽子吧,感觉都没这么费事。

细节就是魔鬼,一个草率的冰淇淋奉上。