現在開発中の新しい 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 の値を少し調整して書き換えるなどの対応が必要となります。