纯 CSS 画条喷火龙怎么说?

大家好,这里是大家的林语冰。坚持阅读,自律打卡,每天一次,进步一点

最近,我有一个阿宅朋友在狂追一个小姐姐,是的没错,就是《狩龙人拉格纳》的女主角蕾欧妮卡。这部二次元作品还挺有趣的,通过插叙 + 倒叙的超现实创作手法,将未来和现在重新编织为一个故事。目前 B 站狂砍 9.6 分,豆瓣好评 7.4 分。

说巧不巧,刚好龙年在前端社区看到有大佬用纯 CSS 画了条二次元版本的喷火龙,爷青回!加上语冰最近正在练习 UnoCSS,不如就用 UnoCSS 复刻一下大佬的神操作。

基本原理如下,现实魔法世界的龙可能是这样子的,比如《权力的游戏》:

而二次元版本的龙可以把喷火龙的局部特征抽象为若干相对规则的几何图形,一般的几何图形则可以使用纯 CSS 的奇技淫巧直接渲染出来,比如一道回头率超高的面试题 ------ 请你用纯 CSS 实现一个"三角恋图形",简称三角形。

这些解离出来的几何图形,搭配生动的色彩,以及通过定位叠加图层和视差,就能用简单的 CSS,实现各种奇奇怪怪的卡通图案。

在现实开发中,这也是一种有意义的优化手段,以前远古时代我们可能会使用"雪碧图"的方案,把多个小型 icon 或图形压缩合成在一张图片上,这样有且仅有触发一次网络请求,然后前端再通过图片裁切的技术,抠图获取对应图形,开发体验和性能都十分猪头。

随着原生 CSS 越发给力,以及 Web 绘图技术的支持日趋成熟,现在我们甚至可以不请求任何网络资源的情况下,完成某些极具创意的操作,进一步优化性能。

所以本期共享的是 ------ 用纯 CSS 整一条喷火龙。

龙头

首先,我们准备一个喷火龙的容器,简单的绝对定位居中布局即可。

然后按照喷火龙的身体结构,自上而下逐步绘制。这里脸部主要包括眼睛、鼻孔、耳朵、双角等局部细节,代码如下:

html 复制代码
<main>
  <div class="box">
    <div class="face">
      <div class="eye"></div>
      <div class="nostril"></div>
      <div class="ear"></div>
      <div class="horn horn-left"></div>
      <div class="horn horn-right"></div>
    </div>
  </div>
</main>

然后根据定义的基本结构,添加对应的 CSS 样式,这里我们使用简单的 UnoCSS 原子类,大家也可以根据自己熟悉的 CSS 方案,比如 SCSS/LESS/Tailwind 等,或者直接使用原生 CSS,实现"图灵等价"的样式,代码如下:

css 复制代码
main {
  --uno: h-screen w-screen bg-black;
   & .box {
    /* 居中布局 */
    --uno: absolute top-50% left-50% translate--50% h-25rem w-30rem b-1 b-solid
      b-white;
    /* 脸部 */
    & .face {
      --uno: absolute top-3rem ma right-0 left-0 bg-red-5 h-6rem w-5rem rd-5rem;

      &::before,
      &::after {
        --uno: absolute content-empty;
      }
      &::before {
        --uno: top-5rem bg-red-9 h-3rem w-full rd-5rem z--1;
      }
      &::after {
        --uno: top-3rem left--0.6rem bg-red-4 w-6.5rem h-4.3rem rd-4rem;
      }
      /* 眼睛 */
      & .eye {
        --uno: absolute top-1.8rem left-1rem bg-black h-0.6rem w-0.6rem rd-50%;
        box-shadow: 2.5rem 0 #000;
      }
      /* 鼻孔 */
      & .nostril,
      & .nostril::after {
        --uno: absolute h-1rem w-1rem bg-red-5 rd-50% b-0.6rem b-solid b-red-4
          z-1;
      }
      & .nostril {
        --uno: top-2.8rem left--0.9rem;

        &::after {
          --uno: content-empty top--0.6rem left-4.2rem;
        }
      }
      /* 耳朵 */
      & .ear,
      & .ear::before {
        --uno: absolute bg-red-5 h-3.1rem w-0.6rem rd-1.3rem b-o.5rem b-solid
          b-red-4;
      }
      & .ear {
        --uno: top--1.8rem left--0.8rem z--1 rotate--40;

        &::before {
          --uno: content-empty left-3.7rem top-3rem rotate-80;
        }
      }
      /* 双角 */
      .horn {
        --uno: absolute top--2.6rem h-4.2rem w-1.2rem bg-orange rd-2.4rem z--1;

        &.horn-left {
          --uno: left-0.6rem;
        }
        &.horn-right {
          --uno: left-3.4rem;
        }

        &.horn-left::before,
        &.horn-right::before {
          --uno: absolute content-empty bg-red h-0.25rem w-70% rd-0.2rem ma
            left-0 right-0 top-0.62rem;
          box-shadow: 0 0.5rem #e76a12, 1 1rem #e76a12, 0 1.5rem #e76a12,
            0 2rem #e76a12;
        }
      }
    }
}

粉丝请注意,大家不必完全按照这个 HTML 结构来设计,因为其中某些结构也可以使用诸如 ::before/::after 等伪元素来实现,CSS 的实现从来没有绝对正确和唯一的写法,关键在于样式的还原,所以可以尽情发挥天马行空的想象力。

如无意外,基本效果大抵如下:

下半身

我们遵循同样的套路循序渐进地绘制下半身即可,下半身主要由躯体、腹部、手脚和双翼组成,HTML 的基本结构如下:

html 复制代码
<div class="box">
  <!-- 头部如上 -->
  <div class="body">
    <div class="stomach"></div>
  </div>
  <div class="wing wing-left"></div>
  <div class="wing wing-right"></div>
  <div class="arm arm-left"></div>
  <div class="arm arm-right"></div>
  <div class="forearm forearm-left"></div>
  <div class="forearm forearm-right"></div>
  <div class="leg leg-left"></div>
  <div class="leg leg-right"></div>
</div>

然后绘制对应的样式,让抽象的躯体形象地反应出不同的生理特征,这通过配色、定位视差效果以及动画来实现,具体样式如下:

css 复制代码
main {
  & .box {
    /* 躯体 */
    & .body {
      --uno: absolute ma left-0 right-0 top-11rem w-2.9rem h-5.6rem bg-red-5
        z--2;
      /* 腹部 */
      & .stomach {
        --uno: relative top-3.1rem right-3rem h-8.8rem w-8.8rem rd-50% bg-red-5;

        &::before,
        &::after {
          --uno: absolute content-empty;
        }
        &::before {
          --uno: top-4.3rem left-2.5rem h-3.8rem w-3.8rem bg-red-4 rd-50%;
        }
        &::after {
          --uno: top--2.7rem ma left-0 right-0 h-0.5rem w-2rem bg-red-9
            rd-0.5rem;
          box-shadow: 0 0.9rem #8c1436, 0 1.8rem #8c1436, 0 2.7rem #8c1436, 0
              3.6rem #8c1436, 0 4.5rem #8c1436, 0 5.4rem #8c1436;
        }
      }
    }
    /* 翅膀 */
    & .wing {
      --uno: absolute top-12.5rem h-6rem w-12rem bg-cyan rd-t-8rem z--3;

      &.wing-left {
        --uno: left-2.25rem rotate-25;
        animation: wing-l 2s infinite;
      }
      &.wing-right {
        --uno: left-16rem;
        transform: rotateY(-180deg) rotate(25deg);
      }

      &.wing-left::before,
      &.wing-right::before,
      &.wing-right::after,
      &.wing-left::after {
        --uno: absolute bottom-0 content-empty h-2rem w-4rem bg-black rd-t-4rem;
      }
      &.wing-left::before,
      &.wing-right::before {
        --uno: left--0;
      }
      &.wing-right::after,
      &.wing-left::after {
        --uno: left-4rem;
      }
    }
    /* 手臂 */
    & .arm {
      --uno: absolute top-14rem h-6rem w-3rem bg-red-9 rd-3rem z--3;

      &.arm-left {
        --uno: rotate-45 left-8rem;
      }
      &.arm-right {
        --uno: rotate--45 left-19rem;
      }
    }
    & .forearm {
      --uno: absolute top-17rem h-2.8rem w-6.2rem bg-red-4 rd-5.6rem;
      &.forearm-right {
        --uno: rotate-180 left-17rem;
      }
      &.forearm-left {
        --uno: left-7rem;
      }
      &.forearm-left::after,
      &.forearm-right::after {
        --uno: absolute left-5.5rem top-0.4rem content-empty h-0.4rem w-1rem
          bg-orange rd-0.3rem;
        box-shadow: 0 0.75rem #fca01b, 0 1.5rem #fca01b;
      }
    }
    /* 大腿 */
    & .leg {
      --uno: absolute top-18rem h-5.6rem w-5.6rem bg-red-9 rd-3rem z--3;
      &.leg-left {
        --uno: left-8rem;
      }
      &.leg-right {
        --uno: left-16rem rotate-y-180;
      }
      &.leg-left::after,
      &.leg-right::after {
        --uno: absolute content-empty top-2.8rem left-10rem h-2.8rem w-5.6rem
          bg-red-4 rd-t-5.6rem;
      }
    }
  }
}

这里的翅膀还可以加一点动画,让喷火龙整体更加栩栩如生,但不是所有的卡通版形象都需要,或者都允许添加动画,这只鱼你的需求有关。

码到这里,一条由纯 CSS 绘制而成的卡通喷火龙就欧了,完整版的静态效果如图所示。

除了沉浸式创意实验,这种抽象卡通画在某些实际开发场景中也由用武之地,不会像传统的静态图像资源那样,每张图可能都被迫不断地发送网络请求。

当然了,二次元里除了宝可梦的喷火龙,还有其他的龙,大家可以按照自己喜欢的配色方案上色,比如岛国动作片《七龙珠》的许愿神龙。就像集齐七颗龙珠能够许愿一样,集齐 777 个赞,大家一定也能梦想成真吧!

本期话题是 ------ 你目前最常用的 CSS 样式方案是什么,以及为什么?

欢迎在本文下方群聊自由言论,文明共享。谢谢大家的点赞,掰掰~

《前端 9 点半》每日更新,坚持阅读,自律打卡,每天一次,进步一点

相关推荐
new出一个对象1 小时前
uniapp接入BMapGL百度地图
javascript·百度·uni-app
你挚爱的强哥2 小时前
✅✅✅【Vue.js】sd.js基于jQuery Ajax最新原生完整版for凯哥API版本
javascript·vue.js·jquery
y先森3 小时前
CSS3中的伸缩盒模型(弹性盒子、弹性布局)之伸缩容器、伸缩项目、主轴方向、主轴换行方式、复合属性flex-flow
前端·css·css3
前端Hardy3 小时前
纯HTML&CSS实现3D旋转地球
前端·javascript·css·3d·html
susu10830189113 小时前
vue3中父div设置display flex,2个子div重叠
前端·javascript·vue.js
IT女孩儿4 小时前
CSS查缺补漏(补充上一条)
前端·css
吃杠碰小鸡5 小时前
commitlint校验git提交信息
前端
虾球xz6 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇6 小时前
HTML常用表格与标签
前端·html
疯狂的沙粒6 小时前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript