Webパフォーマンス向上のためにCSSグラデーションを活用しよう!

UI開発者 橋本

デザインをもとにページ実装する際、写真やアイコンなど多くの画像を使用することがあると思います。
そんなとき、高解像度対応のため画質が粗くならないように解像度に気を付けたり、表示パフォーマンスを向上させるために画像サイズを圧縮させたりと、1つの画像を書き出すにも手間暇がかかります。

そこで、その画像群を出力せずにCSSで実装できたらどうでしょう。画像を読み込まない分パフォーマンスの向上が期待できますし、どれだけ拡大しても粗くなりません。
今回は、CSSグラデーションを用いたグラデーション・図形の表現方法のご紹介と、画像での実装とサイズを比較した結果をお見せします。

CSSグラデーションについて

グラデーション関数

CSSでグラデーションを表現する際、以下の6つの関数があります。

  • linear-gradient(線形グラデーション)
  • repeating-linear-gradient(繰り返し線形グラデーション)
  • radial-gradient(放射グラデーション)
  • repeating-radial-gradient(繰り返し放射グラデーション)
  • conic-gradient(扇形グラデーション)
  • repeating-conic-gradient(繰り返し扇形グラデーション)

(※conic-gradientに関してはまだモダンブラウザで完全にサポートされておらず現在はEdge、Chrome、Safariのみサポートされています。)

これらの関数は背景にグラデーションを与えるだけではなく、ちょっとした図形を作成するときにも役立ちます。
最近リニューアルされたミツエーリンクスの採用サイトでも使用しているので、ぜひ見つけてみてください。 画像だと思っていたものが実はCSSで実装されていた...!なんて発見があるかもしれません。

グラデーションのカスタマイズ方法

下記のコードは基本の指定です。

Selector {
    background-image: linear-gradient(to top, #000 0 50%, transparent 50% 100%);
}

上記コードは上向きで下半分(0%~50%まで)は黒色、上半分(50%~100%)は透明のグラデーションを指定しています。

  • 第一引数はグラデーションさせる方向(to top or 0deg、to bottom or 180deg、to left or 270deg、to right or 90deg)を指定します
  • 第二引数以降はグラデーションさせたい色と次の色までの長さを%もしくはpxで指定します
  • background-positionbackground-sizeなどと組み合わせて位置やサイズを調整します
  • backgroundだけでなく、borderにも指定が可能です
  • linear-gradient等のグラデーション関数は複数指定が可能です

これらを応用したものが以下になります。

See the Pen CSS GradationBox by hikaru hashimoto (@hashikaru) on CodePen.

3つの模様のパターンのうち2つめと3つめの模様は、1つめに指定しているlinear-gradientを角度を変えて重ねた結果です。縞模様から交差、最終的に幾何学的なデザインになりましたね。
黒い背景に半透明の白いストライプを重ねているので、重ねるごとに色やデザインも複雑にできますし、全体的な模様の色も背景色を変更することで自在に変えられます。
これだけでもいろんなデザインパターンが再現できそうな可能性を感じますね!

画像とCSSグラデーションでの実装のサイズ比較

さて、今回の本題です。
画像ではなくCSSグラデーションで実装するとどれだけサイズが削減されるのでしょうか。
これからいくつかのデザインを用意し、それをCSSグラデーションで実装したものとサイズを比較します。

※前提条件

  • CSSはコード量: 全角=2バイト、半角=1バイトとして換算、改行は2バイト
  • 画像はpng形式、未圧縮

三角形のロゴ風デザイン

三角形が2つ重なったロゴ画像

.triangles {
    display: inline-block;
    position: relative;
    margin-right: 80px;
    width: 250px;
    height: 250px;
    background: linear-gradient(to top left, #71e996 50%, transparent 50%)bottom left / 50% 100% no-repeat,
    linear-gradient(to top right, #71e996 50%, transparent 50%)bottom right / 50% 100% no-repeat;
}

.triangles::before {
    position: absolute;
    bottom: 0;
    right: -80px;
    content: '';
    width: 212.5px;
    height: 212.5px;
    background: linear-gradient(to top left, #009df780 50%, transparent 50%)bottom left / 50% 100% no-repeat,
    linear-gradient(to top right, #009df780 50%, transparent 50%)bottom right / 50% 100% no-repeat;
}
  • 画像:25900バイト(25.9KB)
  • CSS:702バイト

円グラフ

円グラフ

.graph {
    display: inline-block;
    position: relative;
    width: 250px;
    height: 250px;
    border-radius: 50%;
    background-image: conic-gradient(
        #fff 0,
        #fff 0.2%,
        #ff6384 0.2%,
        #ff6384 67%,
        #fff 67%,
        #fff 67.2%,
        #36a2eb 67.2%,
        #36a2eb 78%,
        #fff 78%,
        #fff 78.2%,
        #ffce56 78.2%,
        #ffce56 100%
    );
}
.graph::before {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 125px;
    height: 125px;
    background: #fff;
    border-radius: 50%;
}
  • 画像:10600バイト(10.6KB)
  • CSS:652バイト

Instagramロゴ

Instagramロゴ

.instagram {
    display: inline-block;
    position: relative;
    width: 200px;
    height: 200px;
    background: linear-gradient(135deg, #427eff 0%, #f13f79 70%) no-repeat;
    overflow: hidden;
    border-radius: 44px;
}

.instagram::before {
    content: '';
    position: absolute;
    top: 85px;
    left: -65px;
    width: 240px;
    height: 240px;
    background: radial-gradient(#ffdb2c 10%, rgba(255, 105, 34, 0.65) 55%, rgba(255, 88, 96, 0) 70%);
}

.instagram-icon {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 120px;
    height: 120px;
    border: 10px solid #fff;
    border-radius: 40px;
}

.instagram-icon::before {
    content: '';
    display: block;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 50px;
    height: 50px;
    border: 10px solid #fff;
    border-radius: 50%;
}

.instagram-icon::after {
    content: '';
    display: block;
    position: absolute;
    top: 10%;
    left: 75%;
    width: 15px;
    height: 15px;
    background: #fff;
    border-radius: 50%;
}
  • 画像:64800バイト(64.8KB)
  • CSS:1168バイト

CSSの方が容量が軽く済むと予想はしていましたが、数値として比較すると一目瞭然ですね。
最後のInstagramのアイコンのように、一見複雑そうに見えるアイコンまでCSSグラデーションなら実装できちゃうんです!

下記は今回実装した3つのデザインです。
使い方の参考にしてみてください。

See the Pen CSS Gradation by hikaru hashimoto (@hashikaru) on CodePen.

あとがき

いかがだったでしょうか。パフォーマンス云々に限らず、CSSグラデーションでできることの可能性を感じていただけたなら幸いです。
是非みなさんも身の回りのデザインをすべてCSSで実装するくらいの勢いでグラデーションを使いこなしてみてください。
それでは、良いCSSライフを!