はじめに
「ユーザにcssを切り替えさせる」って個人的には開発側のエゴ丸出しだと思ってます。ユーザがcssの切り替えを迫られることなんてまずないし、それをしたとて感動は知れてますからね。
とはいえ、気になったので実装してみました。
滑らかな変化はちょっとだけ面倒くさい!
用意するもの
- 対象htmlソース
- デフォルトカラーのcss
- 変化後カラーのcss
- css切り換えのjquery
対象htmlソース
ユーザにcssを選択させるソースを以下とします。
<!-- 変更対象のcss -->
<link rel="stylesheet" href="/assets/css/default.css" id="colorStyle">
~~~~~省略~~~~~
<div class="colorsArea">
<span data-color="blue" data-bgclr="#afeeee">ブルー</span>
<span data-color="red" data-bgclr="#ff7f50">レッド</span>
</div>
みんな大好きカスタムデータ属性を設定しています。
これ、内訳は
- data-color:cssファイル名
- data-bgclr:設定対象の背景色カラーコード
です。cssファイル名の方はスッとわかると思いますが、カラーコードについては後述。
デフォルトカラーのcss
次にcssですが、デフォルトのcssに関しては特段言及することはありません。
ただ、通常は色に関する設定も他の設定と同じファイルに記載すると思いますが、動的な色変化を実装する場合は切り分けておいた方がなにかと便利です。ソース編集時の凡ミス予防にもなります。
変化後カラーのcss
さて、変化後のカラーを記述したcssですが、こちらに実際の滑らかな変化の部分を書きます。
これはアニメーションで変化するので、以下のようにしてください。(色は任意のものに変更しましょう)
@keyframes colorChanger {
100% {
background: red;
}
}
.mainWrap{
animation: 1s colorChanger 1;
animation-fill-mode: forwards;
}
css切り換えのjquery
最後にjqueryです。これが一番肝心です。
$('.colorsArea span').on('click', function(){
/* 単純なcssの切り替え */
document.getElementById("colorStyle").href = "/assets/css/" + $(this).data('color') +".css";
/* 背景色をアニメーション後に変更する */
var $clr = $(this).data('bgclr');
setTimeout(function(){
$('.mainWrap').css('background',$clr);
},1000);
});
cssの切り替えに関しては言わずもがなですが、滑らかの変更のポイントはあとのsetTimeout内の処理です。
変更後のcssでアニメーションによる滑らかな色の遷移を行っていますが、実はこれ、100%の状態の「background-color」は「background-color」に適用されないんですね。
cssで指定した「animation-fill-mode: forwards;」はアニメーション100%の状態で維持はしても「background」プロパティに設定したことにはなりません。
だから明示的に「background-color」を書き換えてやる必要があります。
この明示的な変更をしないと何が起きるかというと、アニメーションが走り出した瞬間パッと「background-color」の設定色に変ってしまいます。これでは滑らかもクソもないので、上記の通り、明示的な指定が必要になります。
おわりに
実装時、結構戸惑ったんですが、アニメーションが完了したタイミングで色指定を改めてしてやれば疑似的に次に起こるアニメーションの0%時点の背景色を設定した感じになります。
ヤフーのトップもそうですけど、「カチッ」と変わるのはままありますが、スムーズなのはあまり見ない気がするのでちょっと差別化したいと思った方はどうぞ。