株式会社グローバルゲート公式ブログ

@propertyを使って効率的なCSS管理と独創的なアニメーションを実装する

こんにちは、株式会社グローバルゲートのモーリーです。 
3月は年度末ということもあり、CMS「WebChanger」の組み込みや総合サーバー「GSV」の導入などのご相談を多くいただくようになってきました。ありがとうございます。 
 
IT環境の刷新は節目の時期に限ったことではありません。当社サービスへのご相談やお見積りは随時受け付けておりますのでお気軽にお問い合わせください。 

さて、今回はCSSの@propertyという機能をご紹介したいと思います。 
従来よりCSSに変数を定義できるCSSカスタムプロパティ(CSS変数とも呼ばれる)という機能がありましたが、@propertyはそのCSS変数をよりプログラマブルに扱えるようにしたものです。

@propertyの記述方法

@propertyによって変数を定義するには次のように記述します。 

@property --custom-color { 
 syntax: '<color>'; 
 inherits: false; 
 initial-value: #ff0000; 
}

変数名

必ず--からはじめます

syntax

値の型を定義します。指定できる内容は次の通りです。 

名称
意味
<length>
長さの指定
10px, 2rem
<number>
数値(単位なし)
1, 3.14
<percentage>
パーセント指定
50%
<length-percentage>
長さ or パーセント
20px, 50%
<color>
色指定
red, #ff0000
<image>
画像指定
url(img.jpg)
<url>
URL指定
url(https://example.com)
<integer>
整数のみ
1, 5, 10
<angle>
角度指定
45deg,1rad
<time>
時間指定
1s, 500ms
<resolution>
解像度
96dpi
<transform-function>
transform に適用
scale(1.2)
<custom-ident>
特定のキーワード
light, dark

この中では<length>,<color>,<angle>などの使用頻度が高いでしょう。

inherits

親要素から子要素へ継承されるかどうかをtrue/falseで指定します。 
たとえばinheritsをtrueとした場合、以下のCSSでは.childの文字色はredとなります。

@property --text-color { 
  syntax: '<color>'; 
  inherits: true; 
  initial-value: black; 

 
.parent { 
  --text-color: red; 

 
.child { 
  color: var(--text-color); 
}

一方、inheritsがfalseの場合、.childの背景色はblueです。

@property --bg-color { 
  syntax: '<color>'; 
  inherits: false; 
  initial-value: blue; 

 
.parent { 
  --bg-color: red; 

 
.child { 
  background-color: var(--bg-color); 
}

initial-value

初期値を指定します。 
CSS変数の場合は以下のようにプロパティ適用時にデフォルト値を設定する必要がありますが、@propertyの場合はその必要がありません。

/* CSS変数の場合 */ 
padding: var(--spacing, 10px); 
 
/* @propertyの場合 */ 
/* 以下の場合、initial-valueの値が適用されるのでエラーにならない */ 
padding: var(--spacing);

@propertyのメリット

@propertyによる変数定義は次のようなメリットがあります。

共通の値を変数として一元管理が可能

プログラムの変数と同じく、大本を変更すればすべての値が変更されるという使い方が可能です。 
たとえばベースとなる色を@propertyで設定し、各パーツの配色をベース色からの計算で指定すればWebサイトの大幅な色変更も簡単に対応できます。 

型の制約が可能

変数の値の型を制限できるため、意図せずCSSが効かないというトラブルを避けることができます。 
動的にCSSを設定する際に役立ちます。

CSSのエラーはJavascriptやPHPのようにWebサイト自体が動作しなくなるという致命的なものではありませんが、やはり発生させないことに越したことはありません。 

アニメーションが可能

@propertyによって定義された変数はtransitionやanimationによってアニメーションをさせることができます。 
これはCSS変数ではできません。 
 
複雑なCSSプロパティの一部を変数としてアニメーションをさせることで、記述の大幅な簡略化やこれまでにはできなかった複雑な動きを適用することができます。 

@propertyの注意点

このように便利な@propertyですが、一点だけ注意点があります。

変数の有効範囲(スコープ)を指定することができない

CSS変数は以下のように変数の定義範囲を配下要素のみに制限することができました。

div#main { 
 --mainOnly: 20px; 

/* サイト全体に上記変数を使いたい場合は:root(つまりhtmlにあたる)に定義する */ 
:root { 
 --mainOnly: 20px; 

ですが@propertyはグローバル変数として必ずWebサイト全体で有効となります。 
そのため変数名の重複には特に注意して使用してください。

@propertyの実践的な活用例

それでは実際に@propertyを使ってみましょう。
@propertyを有効に活用する事例をいくつか作成してみました。 

配色の一元管理

デモ

基本となる色を指定し、明度・彩度・色相を調整して色設定を行うことで、基本色を変更することでWebサイトの印象を大きく変えることができます。

/* 次のようにHSLを定義する */ 
@property --colorH { 
    syntax: "<number>"; 
    inherits: true; 
    initial-value: 220; 

 
@property --colorS { 
    syntax: "<percentage>"; 
    inherits: true; 
    initial-value: 60%; 

 
@property --colorL { 
    syntax: "<percentage>"; 
    inherits: true; 
    initial-value: 40%; 

 
/* ナビゲーションの背景 */ 
#navigation { 
    background: linear-gradient(0deg, hsla(var(--colorH), var(--colorS), var(--colorL), 1) 0%, hsla(var(--colorH), calc(var(--colorS) * 1.5), calc(var(--colorL) * 1.2), 1) 100%); 

 
 
/* ボタン */ 
.btn a { 
    display: inline-block; 
    padding: 10px 20px; 
    background: linear-gradient(0deg, hsla(var(--colorH), var(--colorS), var(--colorL), 1) 0%, hsla(var(--colorH), calc(var(--colorS) * 1.5), calc(var(--colorL) * 1.5), 1) 100%); 
    color: #fff; 
    border-radius: 4px; 
    border: 1px solid hsla(var(--colorH), calc(var(--colorS) * 1.25), calc(var(--colorL) * 1.25), 1); 
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.2) inset; 

複数のbox-shadowをアニメーション

デモ

box-shadowは複数の値を重ねることができますが、数が増えれば増えるほど@keyframesを書くことが大変で変更を行いたいときも複雑になります。 
@propertyを活用することで変更も簡単な記述が実現できます。

/* @property使用*/ 
.property02-01 .box { 
    animation: property02-01 1s linear infinite; 
    --offset: 20px; 
    box-shadow: calc(var(--offset) * cos(var(--angle))) calc(var(--offset) * cos(var(--angle) - 90deg)) 10px rgba(255, 0, 0, 0.5), 
        calc(var(--offset) * cos(var(--angle) - 180deg)) calc(var(--offset) * cos(var(--angle) - 270deg)) 10px rgba(0, 255, 0, 0.5), 
        calc(var(--offset) * cos(var(--angle) - 90deg)) calc(var(--offset) * cos(var(--angle) - 180deg)) 10px rgba(0, 0, 255, 0.5) 

 
@property --angle { 
    syntax: "<angle>"; 
    inherits: false; 
    initial-value: 0deg; 

 
@keyframes property02-01 { 
    0% { 
        --angle: 0deg; 
    } 
 
    100% { 
        --angle: 360deg; 
    } 

 
/* @property不使用 keyframesが大変...*/ 
.property02-02 .box { 
    box-shadow: 20px 20px 10px rgba(255, 0, 0, 0.5), -20px 20px 10px rgba(0, 255, 0, 0.5), -20px -20px 10px rgba(0, 0, 255, 0.5); 
    animation: property02-02 1s linear infinite; 

 
@keyframes property02-02 { 
    0% { 
        box-shadow: 20px 20px 10px rgba(255, 0, 0, 0.5), -20px 20px 10px rgba(0, 255, 0, 0.5), -20px -20px 10px rgba(0, 0, 255, 0.5); 
    } 
 
    25% { 
        box-shadow: -20px 20px 10px rgba(255, 0, 0, 0.5), -20px -20px 10px rgba(0, 255, 0, 0.5), 20px -20px 10px rgba(0, 0, 255, 0.5); 
    } 
 
    50% { 
        box-shadow: -20px -20px 10px rgba(255, 0, 0, 0.5), 20px -20px 10px rgba(0, 255, 0, 0.5), 20px 20px 10px rgba(0, 0, 255, 0.5); 
    } 
 
    75% { 
        box-shadow: 20px -20px 10px rgba(255, 0, 0, 0.5), 20px -20px 10px rgba(0, 255, 0, 0.5), -20px 20px 10px rgba(0, 0, 255, 0.5); 
    } 
 
    100% { 
        box-shadow: 20px 20px 10px rgba(255, 0, 0, 0.5), -20px 20px 10px rgba(0, 255, 0, 0.5), -20px -20px 10px rgba(0, 0, 255, 0.5); 
    } 
}

グラデーション背景のアニメーション

デモ

グラデーションの背景はbackground-imageで指定するため、transitionやanimationを適用させることができませんでした。 
従来はbackground-sizeをアニメーションさせて動きを表現していましたが、@propartyによりグラデーション構成要素をアニメーションさせることができ、柔軟な指定が可能となりました。 

 
@property --blue { 
    syntax: "<color>"; 
    inherits: false; 
    initial-value: rgba(63, 94, 251, 1); 

 
@property --pink { 
    syntax: "<color>"; 
    inherits: false; 
    initial-value: rgba(252, 70, 107, 1); 

 
.property01-01 { 
    background: radial-gradient(circle, var(--blue) 0%, var(--pink) 100%); 
    animation: property01-01 4s infinite; 

 
@keyframes property01-01 { 
    0% { 
        --pink: rgba(252, 70, 107, 1); 
        --blue: rgba(63, 94, 251, 1) 
    } 
 
    50% { 
        --blue: rgba(252, 70, 107, 1); 
        --pink: rgba(63, 94, 251, 1) 
    } 
 
    100% { 
        --pink: rgba(252, 70, 107, 1); 
        --blue: rgba(63, 94, 251, 1) 
    } 
}

まとめ

ということで、今回CSSに変数を定義できる@propertyについてご紹介しました。 
CSSは変数や条件分岐などプログラマブルな要素が追加され、動的なCSSの生成や複雑な表現もシンプルに実現できる環境になりつつあります。 
その分覚えることが多くなって大変ですが、当社の制作部でも様々な表現に挑戦していきたいと思います。

【関連記事】

ご相談・お問い合わせ

当社サービスについてのお問い合わせは下記までご連絡下さい。

お電話でのお問い合わせ

06-6121-7581 / 03-6415-8161