現在開発中の新しい WordPress テーマの機能として、ページを下方にスクロールすると背景カラーが徐々に変化するギミックを考えてみたので、ご紹介します。
INDEX
CSS のみで実現する方法
要件から少しはずれますが、まずは CSS のみで簡単に実現する方法をご紹介します。
CSS のみで実現するには、ページの背景要素に CSS グラデーション(linear-gradient)を指定するのみです。
めちゃくちゃ単純です。。
See the Pen Change Background Color by Scrolling with Pure CSS by digistate (@digistate) on CodePen.
ただ、上記の CSS のみの方法の場合は、スクロールするほどのコンテンツがない場合は、当然ですが一見でページ全体が単純にグラデーションがかかった見た目になってしまいます。
また、グラデーションに利用する背景カラーの数だけカラーコードを個別に用意する必要があります。
これでは要件を満たせません。
そこで、JavaScript を利用してスクロール量に対して背景カラーを動的に変更する方法を考えてみます。
JavaScript で実現する方法
JavaScript の場合、スクロールのイベントリスナーを利用して、スクロール量に応じて元の背景カラーを基準にして対象要素の背景カラー( background-color )を少しずつ動的に書き換えることができます。
正確には、HEX 値や RGB 値ではなく 色相(hue)のみを変化させることで色が遷移しています。
See the Pen Change Background Color by Scrolling with JavaScript by digistate (@digistate) on CodePen.
対象要素の取得
まず、背景要素から背景カラーを取得します。
サンプルでは .container という要素を想定しています。
const container = document.querySelector('.container');
RGB形式のコード(文字列)を配列に変換
getComputedStyle で取得されるカラーコードは hex 値ではなくrgba 形式の文字列なので、これを余分な文字列(rgba)を削除して RGB(Red, Green, Blue) 形式の色空間としての配列(Red, Green, Blue)に変換します。
let bgColor = getComputedStyle(container);
bgColor = bgColor.backgroundColor.replace(/[()rgba ]/g,"").split(",");
RGB形式の配列をHSL形式の配列に変換
背景カラーの遷移は、色相(Hue)の変化によって表現するため、得られた RGB 形式のカラーコード(配列)から、HSL(Hue, Saturation, Luminance) 形式の色空間にさらに変換する関数を用意します。
rgbToHsl = (r, g, b) => {
// Make r, g, and b fractions of 1
r /= 255;
g /= 255;
b /= 255;
// Find greatest and smallest channel values
let cmin = Math.min(r,g,b),
cmax = Math.max(r,g,b),
delta = cmax - cmin,
h = 0,
s = 0,
l = 0;
// Calculate hue
// No difference
if (delta == 0)
h = 0;
// Red is max
else if (cmax == r)
h = ((g - b) / delta) % 6;
// Green is max
else if (cmax == g)
h = (b - r) / delta + 2;
// Blue is max
else
h = (r - g) / delta + 4;
h = Math.round(h * 60);
// Make negative hues positive behind 360°
if (h < 0)
h += 360;
// Calculate lightness
l = (cmax + cmin) / 2;
// Calculate saturation
s = delta == 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));
// Multiply l and s by 100
s = +(s * 100).toFixed(1);
l = +(l * 100).toFixed(1);
return [h, s, l];
}
この関数を利用して、RGB形式の配列をHSL形式の配列に変換します。
const hsl = rgbToHsl( bgColor[0], bgColor[1], bgColor[2] );
スクロール量に応じて色相(Hue)を変更
あとは、スクロールのイベントリスナーでスクロール量を取得し、基準となる値を算出して色相(Hue)となる数値を変更したものを対象要素の background-color に HSL 形式でセットします。
window.addEventListener( 'scroll', () => {
let y = ( window.scrollY || window.pageYOffset ) / 100;
y = y < 0 ? 0 : y; // Sarari でのエラスティック(マイナス方向への)スクロール対策
// スクロール量を元に適度な Hue 値を求める
const hue = hsl[0] + y * 10,
[ h, s, l ] = [ hue, hsl[1], hsl[2] ];
// 対象要素の background-color を HSL 形式で Hue だけ変更
container.style.backgroundColor = `hsl(${h}, ${s}%, ${l}%)`
} );
背景カラーが #ffffff (白)または #000000 (黒)の場合は、Hue 値を変更しても変化がないため、その場合は RGB の値を少し調整して書き換えるなどの対応が必要となります。

