JavaScript 第6回 HTMLのスタイル(ID)はクラス(CLASS)より優先

# はじめに
今回はHTMLのスタイルの変更について整理したいと思います。
というのも、モーダルウィンドウを作りたいと思ったからです。
そのために、スタイルが必要だということがわかってきましたので、スタイルに取り組もうと思います。
クリックしたらウィンドウが開いて、またそれを閉じるみたいな、よく広告が画面にでてくるアレです。
そのためにスタイルが必要なんだなということで、試していきたいと思います。

# 今回実施する内容
HTMLにスタイルシートを設定して、JavaScriptでスタイルの変更を実施します。
HTML要素に記載済みのdiv要素に対して、スタイルの変更をおこないます。
スタイルの設定はクラスの設定よりも優先されるということがわかりましたので、ここにまとめておこうと思います。
![StyleVSClass.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405480/dd8144df-dd4e-be88-2dc8-cf946e70554e.gif)

# ソースコード(Git Hub)
https://github.com/Build-Mount/JS_06_stylevsclass

# 環境
OS: Windows 11 JP (64bit)
Microsoft Edge バージョン 120.0.2210.61 (公式ビルド) (64 ビット)

# 参考
[style](https://developer.mozilla.org/ja/docs/Web/HTML/Element/style)
[HTMLElement: style プロパティ](https://developer.mozilla.org/ja/docs/Web/API/HTMLElement/style)
[class](https://developer.mozilla.org/ja/docs/Web/HTML/Global_attributes/class)
[詳細度](https://developer.mozilla.org/ja/docs/Web/CSS/Specificity)

# 用語
## アロー関数式
関数記載において、functionや関数名などの記載をなくした省略した関数の書き方。
これまで(第5回まで)、アロー関数式は使用してきませんでしたが、今回から使用していこうと思います。

# スタイルの設定
## スタイルの設定概要
スタイルの設定は、大きくstyle属性で設定するもの(ID)と、class属性で設定するもの(CLASS)の2種類が存在します。
style属性もclass属性もどちらもHTML上に記載できますし、JavaScript上で制御することができます。
sytle属性には、直接直接fontや文字サイズなどの装飾を記載します。
class属性には、クラス名を記載し、そのクラスの内容は別に定義し、それを参照します。
|属性|内容|例|
|:--|:--|:--|
|style属性|fontや文字サイズなどの装飾を直接記載する。|style="font:10pt color:red"|
|class属性|クラス名を記載し、クラスを参照する。|class="className"|

これらを両方設定した場合、どちらが優先されるでしょうか？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405480/13e8aed4-e273-2bc7-e1b6-068a6bcea9f4.png)

[詳細度](https://developer.mozilla.org/ja/docs/Web/CSS/Specificity)を参照して、優先度を図にしました。
TYPEはpタグ、h1タグなどですが、今回の対象外のため説明割愛します。
style属性で設定するものは、IDに該当し、class属性で設定するものは、CLASSに該当します。
IDは要素タグごとに一意で割り当て、CLASSは、複数の要素タグに割り当て可能です。
図の上にいくほど優先度が高いです。
したがって、class属性で指定したものよりも、style属性で設定したもののほうが優先されます。
ということは、全体的な統一感ではCLASSで設定し、個別に設定したい場合IDを使用するということだと思います。特に強調したい時などがユースケースと思います。

## JavaScriptでのスタイルの設定
### スタイルの設定
#### スタイルの設定
|要素.style.プロパティ = 値|
|:--|

例えば、
`document.getElementById("idStyle").style.color = "red";`

#### スタイルの削除
|要素.style.プロパティ = null|
|:--|

例えば、
`document.getElementById("idStyle").style.color = null;`

### クラスの設定
#### クラスの追加
|要素.classList.add("クラス名")|
|:--|

例えば、
`document.getElementById("idClass").classList.add("clsColorBlue");`

クラスの削除
|要素.classList.remove("クラス名")|
|:--|

例えば、
`document.getElementById("idClass").classList.remove("clsColorBlue");`

# サンプルの作成
## サンプルコード
```html:stylesheet.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Modal</title>
    <script src="stylesheet.js" defer></script>
    <link rel="stylesheet" href="stylesheet.css" type="text/css">
</head>
<body>
    <div id="idStyle" class="clsStyle">この文字色をスタイルで変更する</div>
    <input type="button" id="btnChangeStyle" value="スタイルで変更">
    <input type="button" id="btnRoleBackStyle" value="スタイルを戻す">

    <div id="idClass" class="clsStyle">この文字色をクラスで変更する</div>
    <input type="button" id="btnChangeClass" value="クラスで変更">
    <input type="button" id="btnRoleBackClass" value="クラスで戻す">

    <div>■クラスよりもスタイル優先</div>
    <div id="idClass2" class="clsStyle">この文字色をスタイルで変更してからクラスで変更する</div>
    <input type="button" id="btnChangeClass2_1" value="スタイルで変更">
    <input type="button" id="btnChangeClass2_2" value="クラスで変更">
    <input type="button" id="btnChangeClass2_3" value="スタイルで戻す">
    <input type="button" id="btnChangeClass2_4" value="クラスで戻す">
</body>
</html>
```

```javascript:stylesheet.js
document.getElementById("btnChangeStyle").addEventListener("click", () => {
  //スタイルで文字色を変更。
  document.getElementById("idStyle").style.color = "red";
}, false);

document.getElementById("btnRoleBackStyle").addEventListener("click", () => {
  //スタイルで文字色を戻す。
  document.getElementById("idStyle").style.color = null;
}, false);


document.getElementById("btnChangeClass").addEventListener("click", () => {
  //クラスで文字色を変更。
  document.getElementById("idClass").classList.add("clsColorBlue");
},false);

document.getElementById("btnRoleBackClass").addEventListener("click", () => {
  //クラスで文字色を戻す。
  document.getElementById("idClass").classList.remove("clsColorBlue");
},false);


document.getElementById("btnChangeClass2_1").addEventListener("click", () => {
  //スタイルで文字色を変更。
  document.getElementById("idClass2").style.color = "red";
},false);

document.getElementById("btnChangeClass2_2").addEventListener("click", () => {
  //スタイル優先のため、クラスで文字色を変更できない。
  document.getElementById("idClass2").classList.add("clsColorBlue");
},false);

document.getElementById("btnChangeClass2_3").addEventListener("click", () => {
  //スタイルで文字色をも戻す。
  document.getElementById("idClass2").style.color = null;
},false);

document.getElementById("btnChangeClass2_4").addEventListener("click", () => {
  //スタイル優先のため、クラスで文字色を変更できない。
  document.getElementById("idClass2").classList.remove("clsColorBlue");
},false);
```

```css:stylesheet.css
.clsStyle {
  text-decoration: underline;
}

.clsColorRed {
  color: red;
}

.clsColorBlue {
  color: blue;
}

.clsColorInitialize {
  color: initial;
}
```

## コードの説明
以下の3つのパートごとに説明します。

### この文字色をスタイルで変更する
style属性を使用して、文字色を赤字に変更して、それを元に戻します。
```html:stylesheet.html抜粋
    <div id="idStyle" class="clsStyle">この文字色をスタイルで変更する</div>
    <input type="button" id="btnChangeStyle" value="スタイルで変更">
    <input type="button" id="btnRoleBackStyle" value="スタイルを戻す">
```
`<div id="idStyle" class="clsStyle">この文字色をスタイルで変更する</div>`
で、`id="idSytle"`としidを付与し、`class="clsStyle"`でclassを設定し、clsStyleは下線を引くようにスタイルを設定しました。
下線を引いておいたのは、ほかのstyle属性やclass属性を設定しても元のclass属性は残ることを確認するためです。
ボタンは「スタイルで変更」と「スタイルで戻す」で、このボタン押下時の動作は、`stylesheet.js`上に記載します。

```javascript:stylesheet.js抜粋
document.getElementById("btnChangeStyle").addEventListener("click", () => {
  //スタイルで文字色を変更。
  document.getElementById("idStyle").style.color = "red";
}, false);

document.getElementById("btnRoleBackStyle").addEventListener("click", () => {
  //スタイルで文字色を戻す。
  document.getElementById("idStyle").style.color = null;
}, false);
```
スタイルで文字色をred(赤色)に設定、および、そのスタイルを削除します。

`stylesheet.css`は特に関連する動きはありません。

### この文字色をクラスで変更する
class属性を使用して、文字色を青地に変更して、それを元に戻します。
```html:stylesheet.html抜粋
    <div id="idClass" class="clsStyle">この文字色をクラスで変更する</div>
    <input type="button" id="btnChangeClass" value="クラスで変更">
    <input type="button" id="btnRoleBackClass" value="クラスで戻す">
```
`<div id="idClass" class="clsStyle">この文字色をクラスで変更する</div>`
で、`id="idClass"`としidを付与し、`class="clsStyle"`でclassを設定し、clsStyleは下線を引くようにスタイルを設定しました。
ボタンは「クラスで変更」と「クラスで戻す」で、このボタン押下時の動作は、`stylesheet.js`上に記載します。

```javascript:stylesheet.js抜粋
document.getElementById("btnChangeClass").addEventListener("click", () => {
  //クラスで文字色を変更。
  document.getElementById("idClass").classList.add("clsColorBlue");
},false);

document.getElementById("btnRoleBackClass").addEventListener("click", () => {
  //クラスで文字色を戻す。
  document.getElementById("idClass").classList.remove("clsColorBlue");
},false);
```
文字色をblue(青色)にするクラスを設定、および、そのクラスを削除します。

```stylesheet.css抜粋
.clsColorBlue {
  color: blue;
}
```
stylesheetで呼び出しているクラスは`color: blue`とします。

### クラスよりもスタイル優先
style属性でスタイルを設定・削除、class属性でクラスを設定・削除します。
```html:stylesheet.html抜粋
    <div>■クラスよりもスタイル優先</div>
    <div id="idClass2" class="clsStyle">この文字色をスタイルで変更してからクラスで変更する</div>
    <input type="button" id="btnChangeClass2_1" value="スタイルで変更">
    <input type="button" id="btnChangeClass2_2" value="クラスで変更">
    <input type="button" id="btnChangeClass2_3" value="スタイルで戻す">
    <input type="button" id="btnChangeClass2_4" value="クラスで戻す">
```
`<div id="idClass2" class="clsStyle">この文字色をスタイルで変更してからクラスで変更する</div>`
で、`id="idClass2"`としidを付与し、`class="clsStyle"`でclassを設定し、clsStyleは下線を引くようにスタイルを設定しました。
下線を引いておいたのは、ほかのstyle属性やclass属性を設定しても元のclass属性は残ることを確認するためです。
ボタンは「スタイルで変更」、「クラスで変更」、「スタイルで戻す」、および、「クラスで戻す」で、このボタン押下時の動作は、`stylesheet.js`上に記載します。

```javascript:stylesheet.js抜粋
document.getElementById("btnChangeClass2_1").addEventListener("click", () => {
  //スタイルで文字色を変更。
  document.getElementById("idClass2").style.color = "red";
},false);

document.getElementById("btnChangeClass2_2").addEventListener("click", () => {
  //スタイル優先のため、クラスで文字色を変更できない。
  document.getElementById("idClass2").classList.add("clsColorBlue");
},false);

document.getElementById("btnChangeClass2_3").addEventListener("click", () => {
  //スタイルで文字色をも戻す。
  document.getElementById("idClass2").style.color = null;
},false);

document.getElementById("btnChangeClass2_4").addEventListener("click", () => {
  //スタイル優先のため、クラスで文字色を変更できない。
  document.getElementById("idClass2").classList.remove("clsColorBlue");
},false);
```

内容は、すでに説明した２つのパートを組み合わせただけですので、`stylesheet.js`
説明は割愛します。
`stylesheet.css`もすでに内容説明済みのため割愛します。

この動作について、**スタイルはクラスよりも優先**ということで、最初の「今回実施する内容」に載せたGIFのように、「スタイルで変更」⇒「クラスで変更」を押下しても、「クラスで変更」が動作していないように見えます。しかし、設定はされており、「スタイルで戻す」を押下すると、「クラスで変更」で設定した青字が表示されます。

# styleにinitialを設定した場合
colorの値などに「initial」を設定することができます。
```
document.getElementById("idStyle").style.color = "initial";
```
この場合、初期化されるわけですが、初期値の黒字に変わります。
この場合、そのあとクラスで青字に変更しても黒字のままです。
「initial」の設定は、初期値を設定するであって、その前の設定を削除するわけではないようです。
「initial」は、「null」の代用にはならないようです。

# おわりに
HTMLのスタイル設定の注意が必要なことをまとめました。
スタイル(ID)とクラス(CLASS)を両方組み合わせて使用すると、想定もれが発生して、思わぬ動作になりそうなため、避けたほうがよさそうだと思いました。
基本は、CLASSで設定して、本当にIDで設定したいときだけIDを使用するような使い方が適切というか、そういう仕様だと理解しました。