動的生成したstyleタグが可能にすること（JavaScriptで要素生成前にCSSを変更）

# はじめに
動的に生成される要素のCSSをあらかじめ変更しておきたい。といった稀なケースの対応方法。

先に方法を書いてしまうと
「JavaScriptで生成したstyleタグにCSSを書いて、htmlのheadタグに追加して、動的生成する要素に適用する」原始的な方法です。

## 稀なケースとは？

例えば「動的生成される要素のCSSを変更したいけど、要素の生成を監視はしない」といったお題があり、以下のような縛りまである場合。

生成する動的要素に対して、
- 新しいclassやidを追加しない
- style属性を使ってCSSを書き込まない
- 外部スタイルシートも修正しない

## JavaScriptでよくある要素のCSS変更方法
JavaScriptを使用したCSS変更の多くが、以下のように要素の取得が前提になっています。
```javascript:JavaScriptでよくある要素のCSS変更
// 要素を取得
var div = document.getElementById('target');
// または下記で取得
// var div = document.querySelector('#target');

// 取得要素のCSSを変更
div.style.backgroundColor = 'red';
```

生成前の要素は取得できずCSSの設定変更はできないので、styleタグ（style要素）を利用することにします。
headタグ内のstyleタグに書いたCSSは、動的要素の出現時にすぐに適用されるので、先にstyleタグを動的生成してしまいます。


# styleタグとCSSの追加方法

動的にstyleタグを追加する方法は以下の３ステップと簡単。

```javascript:styleタグの追加方法
// 1. styleタグを生成
var styleTag = document.createElement('style'); 

// 2. styleタグ内に追加するCSSを記述
styleTag.textContent = '#target {background-color: #f00;}';

// 3. headタグにstyleタグ追加
document.head.appendChild(styleTag);
```
`createElement`でstyleタグを生成して`textContent`にCSSを書いたら、`appendChild`でheadタグ内に追加するだけです。

headタグ内に追加されたら、CSSが適用されます。

追加したstyleタグを削除する場合に備えて`要素名.id = 'id名';`のようにidを付与しておくと便利です。（例えば、 styleTag.id = 'js_style';）


# CSS記述サンプル
```javascript:styleの記述方法
var styleTag = document.createElement('style'); 
document.head.appendChild(styleTag);


// １個追加
styleTag.textContent = '#target {background-color: #0f0 !important;}';


// まとめて複数追加（テンプレートリテラル使用）
styleTag.textContent = `
    #target {fonr-size: 10px;}
    #target {border: solid 3px #0f0;}
`;


// 変数とコメントアウトを使う
var s = 20;
styleTag.textContent = `
    /* CSS書式のコメントアウトも使用できる */
    #target {font-size: ${ s }px;}
    #target {border: solid 1px green;}
`;


// += 演算子で追記する
styleTag.textContent += `
	#target {padding: 10px;}
`;
```
CSSと同じ書式`セレクタ名 {プロパティ名: 値;}`で書けるところが一目瞭然で良いですね。
ショートハンドで書くこともできます。

テンプレートリテラルを使うと

- 改行できる（スタイルシートからのコピペも出来て便利）
- CSS書式のコメントアウトが使える（/* ~ */）
- 変数を使いたいときは `${ 変数名 }` のように書けばOK

のように使い道が広がります。


# サンプル

以下は、動的に生成される要素のCSSをあらかじめ変更するサンプル。

- ボタンを押して1～5個のdivタグを#parent（width300px）内に動的生成
- 動的生成されるdivタグにはクラス（.child）を付与してあり、widthは100pxに設定している
- div.childが#parentに横並びでちょうど300pxに収まるように、動的生成前にwidthを計算して生成したstyleタグに書き込み、上書きする

```html
<!DOCTYPE html>
<html>
<head>
    <title>sample</title>
    <style>
    #parent {
    	width: 300px;
    	height: 30px;
    	background-color: #efefef;
    }

    .child {
    	width: 100px;
    }
    </style>
</head>

<body>
	<p>▼ #parent ▼</p>
	<div id="parent"></div>
	<button id="btn">動的に要素を生成</button>

	<script>
	var btn = document.getElementById('btn');
 
	btn.addEventListener('click', function(){

        // 生成したstyleがあれば削除（リセット）
    	var styleTag = document.getElementById('js_style');
		if(styleTag != null){
			styleTag.remove();
		}


		// 1 ～ 5までランダムな整数を生成
		var num = 0;
		num = Math.floor(Math.random() * 5) + 1;

		// 動的にstyleタグを追加
		var styleTag = document.createElement('style'); // styleタグ生成
		styleTag.id = 'js_style';                       // id付与
        document.head.appendChild(styleTag); 		    // headタグに<style id="js_style">を追加

		// 動的に追加する要素の幅を計算して、あらかじめCSSに設定
		var w = Math.floor(300 / num);
  
		styleTag.textContent = `
			/* styleタグを追加 */
			#parent div.child {
				display: inline-block;
				box-sizing: border-box;
				width: ${ w }px;
				border: solid 1px #000;
			}
		`;


		// 要素を動的に追加（1 ～ 5個）
		var target = document.getElementById('parent');
		target.innerHTML = '';
		for (var i = 0; i < num; i++ ) {
			var elem = document.createElement('div');
			elem.classList.add('child');
			elem.textContent = i + 1 + '個目';
			target.appendChild(elem);
		}
	});
	</script>
</body>
</html>
```

# あとがき
「style要素を生成して追加する」といったトリッキーな事をする機会はまず無く、`MutationObserver`で要素の生成を監視して、CSSを上書きする方法が正攻法かなと思います。そこを敢えて何とかして別の方法はないか？？という試みでしたが、やってみると意外に面白かった。（本来なら設計で稀なケースを回避しておくことが大事かと思います）