cssに書いていたスタイルをjavascriptで全て適用したい、という場合のお話です。
※背景が伝わらなっていないため追記しました。
例えばjquery-autocomplete.jsはjsだけで動作だけでなくcssもあてるような作りです。
それがよいかはさておき、1ファイルで見た目から機能まで担保します。
そういったことを簡単に実現したい時のノウハウです。
具体的には
hoge.css
fuga.js
test.js
とつくっていたものをcss含め1ファイルにしたい、という場合の話です。
all.js
jsでdomにアクセスしてstyle変数に定義を当てていく、というアプローチが一般的です。
しかしこの方法だといくつか問題がでてきます。
- hoverセレクタが使えない。
- MediaQueryが使えない。
などです。
上記をjavascriptで実装すればよいのですが、
面倒なうえ本来cssなら安全に実装できたところをわざわざバグのリスクを背負うことになります。
そこで別のアプローチです。
cssはstyle要素をレンダリング前に生成し、style要素のcssをjsに適用
ここで一つ問題です。
JavaScriptにはヒアドキュメントがないので下記のように複数行にわけたcssを一行にするか、エスケープ文字列を行末につける必要がでてきます。
.hoge {
background-color: #fff;
}
.hoge:hover {
border: 1px solid #0097cf;
}
このような感じです。
var css = '<style type="text/css">\
.hoge {\
background-color: #fff;\
}\
.hoge:hover {\
border: 1px solid #0097cf;\
}\
</style>';
$(body).append($('css'));
行数が長くなるとけっこうきついと思います。
あとすでに別ファイルでcss定義していた場合は、
ファイルをコピーして編集しなくてはなりません。
handlebarsを使って解決
この問題をhandlenbarsのprecompileをつかって解決します。
handlebarsはテンプレートエンジンです。
HTMLを書いておくとjsにコンパイルしてレンダリングすることが可能になります。
この方法はcssファイルをそのままjsにすることができます。
<style type="text/css">
.hoge {
background-color: #fff;
}
.hoge:hover {
border: 1px solid #0097cf;
}
</style>
precompileはgulp等で行います。
gulp.task('templates', function(){
var src = "./src/css/";
var dest = src+'templates/build';//出力場所
gulp.src(src+'/*.css')
.pipe(handlebars())
.pipe(wrap('Handlebars.template(<%= contents %>)'))
.pipe(declare({
namespace: 'App.css',
noRedeclare: true // Avoid duplicate declarations
}))
.pipe(concat('style.js'))
.pipe(gulp.dest(dest));
});
上記を実行するとApp.css.cssファイル名の変数にcssファイルの文字列が展開されます。
そのため下記のように変数をjquery等にいれるだけでタグを生成することができます。
$("body").append(App.css.style);
あとはgulpなどをつかってstyle.jsとそのほかのjsをcatして一つにまとめます。
このあたりの詳細は別投稿にまとめました。
すると、jsファイルだけでシンプルにcssとjsをまとめることができると思います。
ほかに方法がないわけではもちろんありません。
いかに楽をするかを考えてのアイディアです。