Help us understand the problem. What is going on with this article?

突然「スマイルください」と言われたときの対策 ~ CSS 編 ~

More than 1 year has passed since last update.

「スマイルください」

笑顔を求めるその脅威は、突然私たちに襲い掛かる。
次の脅威はいつ、だれを襲うのか。予告なしに襲い掛かるその脅威から身を守り、被害を最小限に抑えるために、日頃から正しいスマイルの出し方を見につけておくことが重要である。

今回のスマイル :smiley:

今回作るスマイルはこのようなスマイル :smiley: で、原材料は CSS を使う。
また、本家スマイル1が極めて安価( 0 円)で、提供までの時間が短いことをリスペクトして、スマイルを作るにあたり、以下の規則を設け、遵守した。

  • 使用する要素は 1 つまで
  • 擬似要素は利用しないことが好ましい
  • 所要時間は 1 時間以内

スマイル :smiley: の作り方

HTML を書く

HTML は、上記の規則からnico-chanクラスを付与したdiv要素 1 つとした。

<div class="nico-chan"></div>

CSS を書く

まず、スマイル :smiley: をパーツごとに分割すると、円と楕円のみで構成されていることがわかる。円や楕円は、radial-gradient関数を使えば、描くことができる。

顔を描く

radial-gradient関数を使って、顔の輪郭を作っていく(動作例)。良い感じ。

:root {
  --canvas-size: 300px;

  --face-inside-color: #ffcc4d;
  --face-outline-color: #ffcc4d;
  --face: radial-gradient(
      circle,
      var(--face-inside-color) 140px,
      var(--face-outline-color) 141px,
      var(--face-outline-color) 149px,
      transparent 150px
    )
    no-repeat;
}

.nico-chan {
  width: var(--canvas-size);
  height: var(--canvas-size);

  background: var(--face);
}

目を描く

次に、目を作っていく(動作例)。

:root {
  --canvas-size: 300px;

  --eye-size: 17px;
  --eye: radial-gradient(
    11px 15px,
    #664500 calc(var(--eye-size) - 2px),
    transparent var(--eye-size)
  );

  --left-eye-position: 50px -50px;
  --right-eye-position: -50px -50px;

  --left-eye: var(--eye) var(--left-eye-position) no-repeat;
  --right-eye: var(--eye) var(--right-eye-position) no-repeat;

  --eyes: var(--left-eye), var(--right-eye);
}

.nico-chan {
  width: var(--canvas-size);
  height: var(--canvas-size);

  background: var(--eyes);
}

口を描く

次に、口を描く。これは、円の上に楕円を重ねれば良い感じに作れると思う(動作例)。

:root {
  --canvas-size: 300px;

  --face-inner-color: #ffcc4d;

  --mouth-size: 35px;
  --mouth-color: #664500;
  --mouth-overlay: radial-gradient(
      2px 1px,
      var(--face-inner-color) 111px,
      transparent 113px
    )
    0 -50px no-repeat;
  --mouth: radial-gradient(var(--mouth-color) 90px, transparent 91px) 0 10px
    no-repeat;

  --teeth-size: 35px;
  --teeth-color: #fff;
  --teeth-overlay: radial-gradient(
      350px 100px,
      var(--mouth-color) 85px,
      transparent 87px
    )
    0 -10px no-repeat;
  --teeth: var(--teeth-overlay),
    radial-gradient(80px 60px, var(--teeth-color) 80px, transparent 81px) 0 -15px
      no-repeat;
}

.nico-chan {
  width: var(--canvas-size);
  height: var(--canvas-size);

  background: var(--mouth-overlay), var(--teeth), var(--mouth);
}

作ったパーツを組み合わせる

上で作ったパーツを適当に組み合わせる。すると、 CSS は全体でこんな感じになる。ごちゃごちゃしていて読みにくいが、やっていることは円、楕円の作成と配置だけなので、それほど難しいことはしていない。
また、background-imageプロパティをコンマ区切りで適用するとき、最初に適用した値の結果が常に最前面に表示される2、という動作に注意しなければならない。

:root {
  --canvas-size: 300px;

  --face-inner-color: #ffcc4d;
  --face-outline-color: #ffcc4d;
  --face: radial-gradient(
      circle,
      var(--face-inner-color) 140px,
      var(--face-outline-color) 141px,
      var(--face-outline-color) 149px,
      transparent 150px
    )
    no-repeat;

  --eye-size: 17px;
  --circle-eye: radial-gradient(
    11px 15px,
    #664500 calc(var(--eye-size) - 2px),
    transparent var(--eye-size)
  );
  --left-eye-position: 50px -50px;
  --right-eye-position: -50px -50px;
  --left-eye: var(--circle-eye) var(--left-eye-position) no-repeat;
  --right-eye: var(--circle-eye) var(--right-eye-position) no-repeat;
  --eyes: var(--left-eye), var(--right-eye);

  --mouth-size: 35px;
  --mouth-color: #664500;
  --mouth-overlay: radial-gradient(
      2px 1px,
      var(--face-inner-color) 111px,
      transparent 113px
    )
    0 -50px no-repeat;
  --mouth: radial-gradient(var(--mouth-color) 90px, transparent 91px) 0 10px
    no-repeat;

  --teeth-size: 35px;
  --teeth-color: #fff;
  --teeth-overlay: radial-gradient(
      350px 100px,
      var(--mouth-color) 85px,
      transparent 87px
    )
    0 -10px no-repeat;
  --teeth: var(--teeth-overlay),
    radial-gradient(80px 60px, var(--teeth-color) 80px, transparent 81px) 0 -15px
      no-repeat;
}

.nico-chan {
  width: var(--canvas-size);
  height: var(--canvas-size);

  background: var(--eyes), var(--mouth-overlay), var(--teeth), var(--mouth),
    var(--face);
}

完成

というわけで、完成したスマイルがこちら!

See the Pen Pure CSS Smiley Face by Hakaato (@hakaato) on CodePen.

まとめ

このスマイルを作るうえで使用したプロパティは、実質 3 つだけ(カスタムプロパティを除く)になった。このことからも、連続的な色の変化を様々な形状で表現できることは強力で、スタイルをより柔軟に適用できることがわかる。
また、CSS グラデーションはブラウザによって生成されるので、ズーム表示された場合も割りと綺麗に表示されるのも Good ポイント。

CSS の場合、グラデーションさえあれば、スマイルは作れるのだ。もし道端で、突然スマイルを求められても、慌てず冷静にグラデーションを駆使すれば良い。グッドラック。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした