ProgateでHTML&CSS&JavaScript完全に理解した(笑)

2019年8月某日、僕は愕然としていた。Pythonを使うと聞いて応募したアルバイト、時給も良いし、交通費も出るしで喜び勇んで職場へ向かったのだが...
バイト先「ちょっとこのWebページ、いい感じにしてくれない?」
僕「Pythonしか書いたことないので、時間かかるかも知れません。」
バイト先「大丈夫、JavaScriptなんてPythonみたいなものだし。」
僕(流石にそれは違うのでは...?)
僕「HTMLもCSSもJavaScriptも触ったことないですよ?」
バイト先「まあ、腕試しだと思ってさ。明後日までによろしく」
僕「明後日ですか!?流石に間に合わない気がするんですが、それにいい感じってどんな感じですか!?」
バイト先「なんかこう、モダンな感じ! じゃ、よろしく!!」
僕(無茶振りすぎるだろ...。これか、最近流行りの異世界転生ってやつは。「転生したらフロントエンドエンジニアでした」とか、「私、能力はPythonって言ったよね!」そういうやつなのか!?)
とは言え、背に腹は変えられない。ここでバイト代がでなければ困る。
だが今、持っている知識は、

 * HTML:なんかWebのガワ作るやつ
 * CSS:なんか色つけるやつ
 * JavaScript:なんか動かすやつ

くらいしかない。詰んだかもしれない。
そうだ、Progateだ。あれで基礎固めすれば、とりあえず動かせるものが作れるはずだ。
猛暑まっただ中、蝉の声を聞きながら、Webの世界へと足を踏み出した。

# はじめに
これまでPythonしか書いたことがなかった筆者がProgateでフロントエンドを**完全に理解(笑)**し、その後、谷底に突き落とされるまでを描いたポエムです。

完全に理解したという言葉をご存知でしょうか?
エンジニアの世界では、何かの初歩をマスターし、ある種の万能感に満たされている状態を指すことが多いです。
完全に理解できるほど単純なことしか学んでいないがゆえの帰結なのですが、ここから歩みを進めることが難しかったりします。
これはちょうど、MMMORPGのキャラクタークリエイトが終わった瞬間に似ています。この瞬間が最も期待感と幸福感が高いかもしれません。
下のツイートが参考になると思います。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">エンジニア用語の「完全に理解した」「何も分からない」「チョットデキル」は「ダニング・クルーガー効果」で簡単に説明ができます。これは一種の認知バイアスで能力の低い段階では自分の能力の低さを認識できないためです（過大評価しがち）。その反面で能力が高くなると過少評価しがちです。 <a href="https://t.co/LGaJ4E5hWo">pic.twitter.com/LGaJ4E5hWo</a></p>&mdash; おちゃめ (@ochame_nako) <a href="https://twitter.com/ochame_nako/status/1115270046794653696?ref_src=twsrc%5Etfw">April 8, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

Progateを何周もしてしまう人がいるのも、こうした心理が働くからかも知れません。私はProgateを批判したいわけではありません。Web系知識の取っ掛かりとしては非常に分かりやすくまとめられていると思っています。
ですが、この先にこそ、本当の面白いが待っているとも思います。ぜひ、一緒にめくるめく天国と地獄のフロントエンドロードに足を踏み入れましょう!

この記事の目的は以下の3つです。
1. ProgateのHTML&CSS&JavaScriptで習得できる内容を紹介して、未履修の方にProgateをやるモチベーションを高めてもらう
2. Progateは終わったが、次に何をすべきかわからない方に、次に取り組むと良い内容を紹介する
3. 現役フロントエンドエンジニアの方からのアドバイスを期待する(助けてください、何でもしますから!!!)

記事は「Progateで完全に理解した」と「何もわからない」の2段構成になっています。
前半を読めばProgateで何が得られるのか大雑把に把握できます。
後半ではProgate後にやると良いことや、知識不足で失敗したことなどをまとめました。

# Progateで完全に理解した(笑)
この章ではProgateを通して学んだことを紹介していきます。すでに学んだ方は読む必要がないと思われますので、**何もわからない**まで飛ばしていただければと思います。

## HTML&CSS完全に理解した(笑)
[ProgateのHTML&CSS](https://prog-8.com/languages/html)で学べる内容についてまとめました。

### HTML
HTMLとはHyperText Markup Languageの略で、ウェブページの内容や構造を記述する言語です。
HTMLは要素(タグ)と属性の大きく分けて2つの構造から成り立ちます。タグで表示したい内容を囲みながら、見た目を変えたい部分に属性を指定します。
例えばtestという文字を表示するには次のようにします。

```html
<div id="hoge">
  test
</div>
```
この例ではdivが要素で、idのhogeが属性です。

ブラウザで表示できるようなHTMLファイルにするには次のようにします。

```html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width" />
    <title>test page</title>
  </head>
  <body>
    <div id="hoge">
      test
    </div>
  </body>
</html>
```
この内容をindex.htmlなどに保存してブラウザで開けば、下の画像のように表示されます。
![Screenshot from 2019-11-02 10-36-12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397153/2022ab3e-7c1b-fa4c-07a5-10d1131dde10.png)
2行目移行の`<html>`内がHTMLの内容です。それぞれの要素について説明します。
`<html>`:HTMLの内容を記述していく要素です。`<html>`は全ての要素の基点となる要素なので、ルート要素とも呼ばれています。HTMLでの全ての要素はこの<html>タグ内に書かなければいけません。
`<head>`:HTMLファイルに関する情報(メタデータ)を記述する要素です。ここにはファイルの文字コードやページタイトル、CSSやJavaScriptへのパスなどを記述します。
`<body>`:HTMLファイル内のコンテツを入れる要素です。ファイル内にひとつだけ書くことができます。
`<div>`:要素のレイアウトを指定するための要素です。要素を囲ってひとまとめにしたり、大きさや色を変える時に使います。
他にも段落や見出しなど様々な要素があります。[詳しくはこちら](https://tombomemo.com/quick-start-html/)で説明します。

### CSS
CSSとはCascading Style Sheetsの略でスタイルシートとも呼ばれます。HTMLがウェブページの構造を作る言語であるのに対し、 CSSはウェブページの見た目を整える役割を持っています。
CSSはセレクタ、プロパティ、プロパティの値の3つで成り立ちます。

```css
セレクタ {
    プロパティ: 値;
}
```

例えばdiv要素の文字色を赤に変えるには次のようにします。

```css
div {
  color: red;
}
```
#### 代表的なCSSプロパティ
代表的なCSSプロパティに関して軽く説明します。

##### padding&margin
paddingは要素から要素の境界(border)までの余白を指定できます。下の例ではオレンジ色の点線が境界(border)です。
<p class="codepen" data-height="265" data-theme-id="default" data-default-tab="css,result" data-user="tombo_gokuraku" data-slug-hash="vYYaxRe" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="padding.css">
  <span>See the Pen <a href="https://codepen.io/tombo_gokuraku/pen/vYYaxRe">
  padding.css</a> by tombo gokuraku  (<a href="https://codepen.io/tombo_gokuraku">@tombo_gokuraku</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
paddingは値の指定方法が4つあり、値が1つなら4辺全てに同じ値、2つなら上下|左右、3つなら上|左右|下、4つなら上|右|下|左(時計回り)に指定できます。
またpadding-top,padding-bottom,padding-left,padding-rightなどを使うと個別に設定することもできます。
 
marginは要素の境界(border)から要素の外側までの余白を設定できます。marginを設定することで、下の例のようにオレンジ色境界線に対して、緑色の要素の外側までの余白が指定できます。
<p class="codepen" data-height="265" data-theme-id="default" data-default-tab="css,result" data-user="tombo_gokuraku" data-slug-hash="NWWBpBe" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="margin.css">
  <span>See the Pen <a href="https://codepen.io/tombo_gokuraku/pen/NWWBpBe">
  margin.css</a> by tombo gokuraku  (<a href="https://codepen.io/tombo_gokuraku">@tombo_gokuraku</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
指定方法はpaddingの場合と同じです。またpaddingと同じようにmargin-top,margin-bottom,margin-left,margin-rightのように個別に指定することができます。

##### height&width
heightとwidthで要素の高さと幅を指定できます。指定できる値の単位はpx,em,%,autoの4種類です。%は親要素に対する割合で大きさが決まります。autoはwidthに指定した場合は親要素いっぱいに広がります。heightに指定した場合は要素内のコンテンツを表示するのに最適な高さになります。
<p class="codepen" data-height="265" data-theme-id="default" data-default-tab="css,result" data-user="tombo_gokuraku" data-slug-hash="gOOjLwq" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="height_width.css">
  <span>See the Pen <a href="https://codepen.io/tombo_gokuraku/pen/gOOjLwq">
  height_width.css</a> by tombo gokuraku  (<a href="https://codepen.io/tombo_gokuraku">@tombo_gokuraku</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

##### color
colorで文字の色を設定できます。`color: #ff0000;`のように16進数のカラーコードで色を指定します。よく使われる色に関してはredやblueなどの文字列で指定することができます。
<p class="codepen" data-height="265" data-theme-id="default" data-default-tab="css,result" data-user="tombo_gokuraku" data-slug-hash="rNNKKRd" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="color.css">
  <span>See the Pen <a href="https://codepen.io/tombo_gokuraku/pen/rNNKKRd">
  color.css</a> by tombo gokuraku  (<a href="https://codepen.io/tombo_gokuraku">@tombo_gokuraku</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

#### CSSセレクタ
CSSではHTMLで書いた属性をCSSセレクタで指定することができます。以下はその一例です。

```css
div {
  /* div要素を指定 */
}

div.hoge {
  /* div要素でありクラス('hoge')を持っている要素を指定 */
}

div#hoge {
  /* div要素でありID('hoge')を持っている要素を指定 */
}

div,p {
  /* div要素とp要素を指定 */
}

div p {
  /* div要素を祖先に持つp要素を指定 */
}

```

HTML&CSSのレッスンを全て終えると下のようなWebサイトが作れるようになります! ぜひこの完成形を目指して完走してください。
![progate_product.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397153/ad7ff4f4-7b21-d2cc-90bf-1d507117ea10.gif)

## JavaScript完全に理解した(笑)
[ProgateのJavaScript](https://prog-8.com/languages/es6)で学べる内容についてまとめました。
### JavaScriptとは?
JavaScriptとはWebページに動きをつけるためのプログラミング言語です。JavaScriptを使うことで地図やカレンダー、ゲームなどユーザーの入力に応じて動的に変化するページを作ることができます。

### JavaScriptの書き方
簡単にJavaScriptの書き方を説明します。

#### 文はセミコロンで区切る
JavaScriptは、文ごとに処理していき、文は;で区切られます。処理が1行のみの場合は;を省略することもできますが、書き忘れや処理の追加時に書き足すことを考えると、普段から書いておく方が無難です。

#### コメントアウト
JavaScriptでのコメントアウトは次のように書きます。

```javascript
// 1行のコメントアウト
/* 複数行の
   コメントアウト
*/
```

#### 変数
JavaScriptでは定数をconst,変数をletで宣言します。

```javascript
const immutableValue = 'hoge';
let mutableValue = 3;
```

#### 制御文
主な制御文(if,for,while)を説明します。
条件分岐させたい時はifを使います。

```javascript
if(条件式) {
  実行する文
}
```
一致しなかった場合の処理はelseを使って書きます。

```javascript
let name = '千尋'
if(name === '千') {
  console.log(`${name}!`);
}else{
  console.log(`フン。 ${name}というのかい? 贅沢な名だねぇ。`);
  name = '千';
  console.log(`今からおまえの名前は${name}だ。いいかい、${name}だよ。分かったら返事をするんだ、${name}！！`);
}
```
繰り返し処理はforかwhileを用います。繰り返しの回数が分かっている場合はforを使います。

```javascript
for (初期化式; 条件式; 増分式) {
    実行する文;
}
```

条件を満たすまで繰り返したい場合はwhileを使います。

```javascript
while (条件式) {
    実行する文;
}
```

#### 関数
関数は一連の手続きをひとまとめにする機能です。JavaScriptには関数の宣言方法が3通りあります。

```javascript
// 通常の関数宣言
function normalFunction() {
  return 'normal function'
}

// 関数式を使った関数宣言
const functionExpression = function() {
  return 'function expression'
}

// Arrow Function
const arrowFunction () => {
  return 'arrow function'
}
```
通常の関数宣言は他のプログラミング言語と同じように`normalFunction()`のように呼び出すことができます。
関数式では`function()`のように関数名を省略して宣言できます。このような関数のことを匿名関数(または無名関数)といいます。名前を持たないため、`functionExpression()`のように代入した変数を使って関数を呼び出します。
Arrow Functionは`function`すら省略して関数を書く方法で、さらに他の関数宣言にはない特徴を持っています。JavaScriptは`this`を使って呼び出し元のオブジェクトを参照することができますが、普通の関数の場合はどこから呼び出されたかによって、`this`の値が変化します。一方でArrow Functionは呼び出し方に依らず、常に`this`が静的に決まるという性質を持っています。

#### 配列
配列とは値に順序をつけて格納できるオブジェクトです。 配列に格納した値を要素、要素の位置をインデックス（index）と呼びます。 インデックスは0から始まる連番となります。JavaScriptでは`[]`を使って配列を作ることができます。

```javascript
let numbers = [1,2,3,4,5]

//indexを指定して配列にアクセス
console.log(numbers[0]) //1

//lengthプロパティで配列の長さがわかる
console.log(numbers.length); //5

//push()で末尾に要素を追加、pop()で末尾から要素を削除
numbers.push(6)
console.log(numbers); //[1,2,3,4,5,6]
lonsole.log(numbers.pop()); //6
```

# 何もわからない
ここからはProgate修了後から実際にコーディングしていく過程で苦しんだこと、早く知っておけば良かったことなどについてまとめました。

## HTML何もわからない
「Progate終わったし、もう何も怖くない!」

### 何だこのタグ?俺は聞いてねえぞ?(`<table>`,`<form>`)
「何だこのタグ? Progateには出てこなかったぞ。『これゼミでやったやつだ!』って言えないじゃん!!」
HTML「いつからHTMLをマスターしたと錯覚していた」

意外と使うのにProgateでは紹介されないタグについて紹介します。

#### `<table>`
`<table>`は表を作ることのできる要素です。例えば下のように書きます。

<p class="codepen" data-height="265" data-theme-id="default" data-default-tab="html,result" data-user="tombo_gokuraku" data-slug-hash="QWwvaME" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="table-example">
  <span>See the Pen <a href="https://codepen.io/tombo_gokuraku/pen/QWwvaME">
  table-example</a> by tombo gokuraku  (<a href="https://codepen.io/tombo_gokuraku">@tombo_gokuraku</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

要素は上から順に次のような役割を持っています。
`<table>`:表を作成する要素
`<caption>`:キャプションをつける要素
`<tr>`:表の行データを格納する要素
`<th>`:表のヘッダーを作る要素
`<td>`:表のデータを格納する要素

表の罫線を追加するには次のようにborderを追加します。border-collapseを設定すると隣接する境界が折り畳まれて、境界線が1本になります。

```css
table, th, td {
  border: 1px solid black;
  border-collapse: collapse;
}
```

#### `<form>`
`form`はログイン画面やアンケート入力など、ユーザーからの入力をサーバーに送信するために使います。

<p class="codepen" data-height="265" data-theme-id="default" data-default-tab="css,result" data-user="tombo_gokuraku" data-slug-hash="QWwvaVd" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="form-example">
  <span>See the Pen <a href="https://codepen.io/tombo_gokuraku/pen/QWwvaVd">
  form-example</a> by tombo gokuraku  (<a href="https://codepen.io/tombo_gokuraku">@tombo_gokuraku</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

`action`にはフォーム経由で送信された情報を処理するためのURIを指定します。
`method`にはフォームを送信する際にブラウザが使用するHTTPメソッドを指定します。
`<form>`中の`<input>`には`<label>`を使ってラベルを貼ることができます。予め`<input>`にidを指定して、`<label>`内の`for`属性に`<input>`のidを指定すると、ラベリングできます。

### タグをちゃんと閉じなくても表示されるという恐怖(Linter/Validator)
「タグ閉じてなかったり、抜けてたりしても表示されちゃうのだが?」
HTML「所詮はマークアップ言語ですから...」

HTMLは良くも悪くもブラウザ(のHTMLパーサー)が優秀なため、壊れたHTMLでも問題なく開けてしまいます。見た目にはなんの問題もないのに、いざコーディングを始めてみたら、タグが対応していなかったり、抜けてたり、なんてことがあります~~(そういうコードのリファクタリングをしなければならない時は発狂します)~~。
例えば先程の表を作るコードは`<tr>`を適当に抜いたり、タグを閉じなかったりしてもうまく表示されます。

<p class="codepen" data-height="265" data-theme-id="default" data-default-tab="html,result" data-user="tombo_gokuraku" data-slug-hash="qBEmGRz" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="broken-html">
  <span>See the Pen <a href="https://codepen.io/tombo_gokuraku/pen/qBEmGRz">
  broken-html</a> by tombo gokuraku  (<a href="https://codepen.io/tombo_gokuraku">@tombo_gokuraku</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

この手のコードを書かないために、LinterやValidatorが使えます。
[W3CのMarkup Validation Service](https://validator.w3.org/)を使うと手軽にHTMLのvalidationができます。上のコードをバリデーションすると下のような結果がでてきます。
![validator.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397153/e5ff84a8-3b2f-b34b-a897-bc5e26a22654.png)

あるいはエディタにLinterというコードを解析してバグを検出するプログラムを導入するのもありです。[VSCodeで使えるhtmlhint](https://marketplace.visualstudio.com/items?itemName=mkaufman.HTMLHint)などがオススメです。

## CSS何もわからない
「CSSなんて、色つけて、レイアウトして終わりっしょ」
そう思っていた時期が僕にもありました...。

### なぜ俺のイカしたスタイルが適応されないのか？(CSSの優先順位)
「なぜだ!?なぜ俺のイカしたスタイルが適応されないんだ!?」
CSS「お前には伝えていなかったが、CSSには優先順位があるのだよ」

Progateではあまり触れられていませんが、CSSにはスタイル適応に優先順位があります。
例えば下のようにp要素の色を設定したとします。最後の`p{color:black;}`で文字色を黒にしようとしていますが、反映されていません。
<p class="codepen" data-height="265" data-theme-id="default" data-default-tab="css,result" data-user="tombo_gokuraku" data-slug-hash="xxbRjro" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="css-specificity-example">
  <span>See the Pen <a href="https://codepen.io/tombo_gokuraku/pen/xxbRjro">
  css-specificity-example</a> by tombo gokuraku  (<a href="https://codepen.io/tombo_gokuraku">@tombo_gokuraku</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
ここでは`p.item`と`#highlight`のCSSが優先されています。
大雑把に書けばCSSには次のような優先順位があります。

```css
div#highlight.container > div#highlight > #highlight > div.container > .container > div > *
```
全称セレクタが最も優先順位が低く、IDやクラスを指定するごとに優先順位が高くなっていきます。
より正確にはCSSセレクタにはSpecificityと呼ばれる数値が設定されていて、タイプ(要素の指定)で+1、クラスの指定で+10、IDの指定で+100のようにセレクタの数と種類に応じて数値が計算されます。Specificityが高ければ高いほどより優先的にCSSが適応されます。
詳しくは[こちらのドキュメント](https://drafts.csswg.org/selectors-3/#specificity)をご覧ください。


### CSSって入れ子にできないの?(SASS)
「HTMLは入れ子で書いていくのに、なんでCSSは入れ子じゃないんだ?」
SASS「CSSを入れ子で書きたいと聞いて」

SASSは**S**yntactically **A**wesome **S**tyle **S**heetの略でCSSを入れ子にしたり、変数を定義したりできます。
SASSはコンパイルしてCSSに変換することで、通常のブラウザでも読み込めるようになります。
本来は開発環境を構築しなければなりませんが、[CodePen](https://codepen.io/)などのサービスで手軽に試すことができます。
例えば先程のCSSは下のように書いていました。

```css
div.container {
  background-color: #eee;
  color: black;
}

.item {
  color: blue;
}

#highlight {
  color:red;
}
```

これをSASS(SCSS記法)で書き直すと下のようになります。
<p class="codepen" data-height="265" data-theme-id="default" data-default-tab="css,result" data-user="tombo_gokuraku" data-slug-hash="PowbeyK" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="scss-example">
  <span>See the Pen <a href="https://codepen.io/tombo_gokuraku/pen/PowbeyK">
  scss-example</a> by tombo gokuraku  (<a href="https://codepen.io/tombo_gokuraku">@tombo_gokuraku</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

上の例ではクラスやIDの指定部分を入れ子にしたり、背景色の値を`$material-gray-200: #eee;`のように変数化したりしています。

SASSにはSASS記法とSCSS記法の2種類があります。SCSS記法は{}や;を使ってCSSっぽくスタイリングする方法で、SASS記法は{}や;を使わずにインデントのみで、階層関係を記述する記法です。

SASSは他にも`@extend`でスタイルを継承したり、`@mixin`で引数を受け取ってスタイルを展開したりできます。
SASSの[インストールはこちら](https://sass-lang.com/install)、[使い方はこちら](https://sass-lang.com/guide)が参考になります。困った時は[ドキュメント](https://sass-lang.com/documentation)も使えます。
サクッと学ぶなら[Progate](https://prog-8.com/languages/sass)もオススメです。

### CSSの名前ってどうしたらいいの?(BEM)
「.container.component.wrapperとかいうすごくバカっぽいクラスを書き始めちゃったんだがどうしたらいい?」
BEM「Block-Element-Modifierの規則で名付ければ一貫性が出るで」

BEMはBlock-Element-Modifierの略で、CSSの命名規則の1つです。クラス名をBlock__Element--Modifierのようにつけて、親子関係や強調表示などをクラス名で表します。Blockは基本となる大きな塊、ElementはBlock直下の子要素、Modifierは選択されている要素や強調したい要素などを表します。
例えばBEMではHTMLを以下のように書きます。

```html
<div class="block">
  <div class="block__element">hoge</div>
  <div class="block__element--modifier">piyo</div>
  <div class="block__element">foo</div>
</div>
```

これを装飾するCSSは次のようになります。

```css
.block {
  background-color: #eee; 
}

.block__element {
  font-size: 18px;
  color: #212121;
}

.block__element--modifier {
  font-size: 18px;
  color: #C62828;
}
```

BEMを使って書くと、クラス名からHTMLの構造が想像できるようになります。要素を別の要素に変更した場合もスタイルが適応できるのもメリットの1つです。
さらにSASSを使うとクラス名を省略することができます。上のCSSをSCSSで書き直すと下のようになります。

```scss
$material-gray-200: #eee;
$material-gray-900: #212121;
$primary: #C62828;

.block {
  background-color: $material-gray-200;
  
  %__element {
    font-size: 18px;
  }
  
  &__element{
    @extend %__element;
    color: $material-gray-900;
    
    &--modifier {
      @extend %__element;
      color: $primary;
    }
  }
}
```

SCSSで書くと、入れ子の中で`&`を使うだけで、blockやelementなどのクラス名を省略できます。BEMで冗長になりがちなクラス名が省略できるのは大きなメリットです。
また変数定義`$`やプレースホールダー`%`を使って、要所要所でCSSを使い回せるのもSCSSの良いところです。

[BEMの概要をつかむにはこちらの記事](https://qiita.com/Takuan_Oishii/items/0f0d2c5dc33a9b2d9cb1)、[チュートリアルはこちら](https://en.bem.info/methodology/quick-start/)が参考になります。

### そもそもCSSにスコープがないのが問題なんじゃないの?(styled-components)
「SASSとBEMで再利用性の高いHTMLとCSSが書けるのは分かったけどさ、やたらクラス名長くなるし、ElementとかBlockの名前を工夫しないと、他と衝突するんだけど? そもそもなんでCSSってグローバルスコープなわけ? こういうのがだるいから[人類はオブジェクト指向を生み出した](https://tombomemo.com/why-make-it-object-oriented-review/)んじゃなかったの?」
styled-components「気づいてしまったか...」

styled-componentsはCSS in JSと呼ばれるものの1つで、JavaScriptの中にスタイルを書くことができます。Webページの要素をコンポーネントと呼ばれる特定の機能を実現する単位に区切ることで、スタイルが適応される範囲をコンポーネント内に限定することができます。これによって複雑な命名の問題を解消することができます。
styled-componentsは通常、React(後述します)などのフレームワークと一緒に用いられます。
例えばカードコンポーネントのスタイルは次のように書きます。
<p class="codepen" data-height="265" data-theme-id="default" data-default-tab="js,result" data-user="tombo_gokuraku" data-slug-hash="LYEWOzO" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="react-example">
  <span>See the Pen <a href="https://codepen.io/tombo_gokuraku/pen/LYEWOzO">
  react-example</a> by tombo gokuraku  (<a href="https://codepen.io/tombo_gokuraku">@tombo_gokuraku</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

前半のTitle, Card変数を宣言している部分にstyled-componentsが使われています。

```javascript
const Title = styled.h1`
  font-size: 1.5em;
  text-align: center;
  color: Black;
`;
```

上のように書くことで、render関数内で`<Title>`と書くだけで、スタイル済みのh1要素を出力させることができます。
コンポーネント単位で管理することで、命名の煩雑さが避けられると同時に、再利用性も向上します。

[styled-componentsの公式チュートリアルはこちら](https://www.styled-components.com/docs/basics)、[styled-componentsを使ったCSSの設計はこちら](https://qiita.com/taneba/items/4547830b461d11a69a20)が参考になります。

## JavaScript何もわからない
「ProgateやったらWebページヌルヌル動かせるようになるだろ」
そう思っていた時期がワイにもありました...。

### DOMって何ぞ?
「Progateやったのに、ページ内の要素ヌルヌル動かせないんだが?」
DOM「まずはDOMを理解せよ」

Progateでは主にProgateが用意したコンソール上にJavaScriptを書いて実行することでJavaScriptの学習を進めていきます。最後の方にNode.jsを使った開発環境構築が説明されますが、これだけではWeb上の要素を自由に動かすことはできません。そこで必要になってくるのがDOMに対する理解です。

DOMとはDocument Object Modelの略で、HTMLの要素をJavaScriptからアクセスできるようにツリー状に再構成したもののことです。
DOMを扱えるようになると下のように動きがあるページを作るのが簡単になります。

<p class="codepen" data-height="265" data-theme-id="default" data-default-tab="js,result" data-user="tombo_gokuraku" data-slug-hash="bGNqaEE" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="dom-example">
  <span>See the Pen <a href="https://codepen.io/tombo_gokuraku/pen/bGNqaEE">
  dom-example</a> by tombo gokuraku  (<a href="https://codepen.io/tombo_gokuraku">@tombo_gokuraku</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

このコードは1秒毎にFlexboxのCSSを書き換えて、配置を変更しています。
JavaScriptでは`document.querySelector()`を使うことで、CSSを使ってDOMにアクセスできます。
`querySelector()`は`Element`を返すので、`Element.style`や`Element.innerText`などを使って、要素のスタイルや要素の内容にアクセスし、書き換えられます。

DOM操作やJavaScriptのクラス、非同期処理(コールバック/Promise/Async)、Event等の概念を理解するためにオススメなのが、[jsprimer](https://jsprimer.net/)です。JavaScriptの初歩からTodoアプリの作成まで網羅しているので、これをやっておけば大抵のJavaScriptは書けるようになります。

### jQueryはオワコン?
「DOMを扱う時によくjQueryのコードが出てくるけど、ググってると"jQueryはオワコンだ"とか、"いいや、まだ世界中で使われてる"とか、出てきて賛否両論なんだけど、どっちなの?」
jQuery「昔はお前のような冒険者だった。膝に矢を受けてしまってな...」

ここは私自身も判断がつかなかったところです。オワコンと言うには未だに多くのサイトで使われていますし、かと言って新規開発で使いたいライブラリではない、そんな印象を受けました。肯定派、否定派それぞれの意見をまとめてみました。

#### 肯定派
1. 簡単に書けるのでサクッとWebサイトが作れる
2. 多くのサイトでまだ現役で使われている
3. 学習コストが低い

#### 否定派
1. SPA作るのはほぼ無理
2. 宣言的UIにならない
3. Vanilla JavaScriptでほぼ同じ内容が書ける

肯定派の方がJavaScriptに求めているのが、CSSでは書けないアニメーションやちょっとした状態の保存や書き換え、サーバーとの通信といったタスクであるのに対し、否定派の方が求めているのはSPAの開発や高度な状態遷移、コンポーネント化による再利用性の向上などであると予想しています。お互いに開発したい対象や求めている機能が違うので、意見の食い違いが発生しているのではと考えています。
一方で、ここからは私見なのですが、jQueryが提供している手軽にリッチな見た目のWebページを作れるという機能は今後、NoCode(後述します)で提供される可能性が高く、そうなった時は正真正銘、jQueryはお役御免になると考えています。

jQueryに関する議論は[こちらの記事(主にコメント欄)](https://dev.to/ben/anybody-still-working-with-jquery-l0)を参考にしました。
jQueryで書かれたコードをVanilla JavaScriptにしたい時は[こちらのサイト](http://youmightnotneedjquery.com/)が参考になります。

### まだ生DOM触ってんの? 時代はフレームワークだぜ(React)
「イベントのコールバックで死にそう。どこでaddEventListenerしたっけ? そもそもこのDOM、いつどこで書き換えた? もう嫌だ、俺はUI1つまともに書けない、俺はこんなにも無力だ。」
React「チカラガホシイカ?」

ReactはFacebookが作成したUser Interface用のJavaScriptライブラリです。Reactの一番の特徴は宣言的UIです。
宣言的UIの説明するために、まず宣言的の対義語である命令的について説明します。
命令的とは"何をするか"を記述していく方法で、最終的な結果が前回の実行結果に依存する状態をいいます。
例えばボタンを押すと文字の色が変わるコードを命令的に書いてみます。

<p class="codepen" data-height="265" data-theme-id="default" data-default-tab="js,result" data-user="tombo_gokuraku" data-slug-hash="wvBJbzq" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="imperative-ui">
  <span>See the Pen <a href="https://codepen.io/tombo_gokuraku/pen/wvBJbzq">
  imperative-ui</a> by tombo gokuraku  (<a href="https://codepen.io/tombo_gokuraku">@tombo_gokuraku</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

命令的UIでは`if(this.classList.contains('red'))`のように、まずボタンが以前どのような状態であったかを確認します。
その上でボタンの状態に合わせて、`this.classList.remove('red');`のようにDOMそのものを操作して、状態を変更します。

逆に宣言的とは"状態に対する反応"を記述していく方法で、最終的な結果が前回の結果に依存しません。
上の例をReactを使って宣言的に書くと次のようになります。

<p class="codepen" data-height="265" data-theme-id="default" data-default-tab="js,result" data-user="tombo_gokuraku" data-slug-hash="RwNpzrx" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="declarative-ui">
  <span>See the Pen <a href="https://codepen.io/tombo_gokuraku/pen/RwNpzrx">
  declarative-ui</a> by tombo gokuraku  (<a href="https://codepen.io/tombo_gokuraku">@tombo_gokuraku</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

Reactを使った例ではDOMを直接変更することはなく、`render()`内で現在の状態に基づいて描画するように宣言するだけです。こうすることで、状態を"いつ"変更したかを考えなくて済むようになります。
さらに状態自体もDOMで管理するのではなく、クラスで管理しています。これによって、どこで状態を変更したかも探しやすくなりました。命令的にDOMを直接変更する場合は、どこからでも変更できていました。Reactのようにコンポーネントの中に状態とそれを変更する関数を閉じ込めることによって、デバッグが楽になり、再利用性も高まりました。

宣言的UIは[こちらの記事](https://qiita.com/erukiti/items/fb7bcbd9d79696579d06)を参考にしました。

Reactを学ぶにはまずは[公式の日本語チュートリアル](https://ja.reactjs.org/tutorial/tutorial.html)や[レファレンス](https://ja.reactjs.org/docs/getting-started.html)などが参考になります。
また[公式のExample](https://ja.reactjs.org/community/examples.html)がReactでプロダクトを作るときの助けになります。
jQuery使いの方がざっくりとReactの利点が分かる記事[(Reactを使うとなぜjQueryが要らなくなるのか)](https://qiita.com/naruto/items/fdb61bc743395f8d8faf)もあります。

## NoCodeの登場でフロントエンドエンジニアの存在意義が何もわからない
NoCode「コーディングなんかしなくても、俺がいればデザインがそのままコードになるよw」
「そんな、俺は何のために今までコードを書いてきたんだ!? これまでの時間を返せ!」

NoCodeとはコーディング無しでウェブサイトやアプリなどを作成できるツールの総称です。
以下はその一例です。

**Webサイト構築系**

 - [Webflow](https://webflow.com/)
 - [STUDIO](https://studio.design/)

**アプリ作成系**

 - [Glide](https://www.glideapps.com/)
 - [.bubble](https://bubble.io/)

**iPaaS(サービス同士の接続)系**

 - [IFTTT](https://ifttt.com/)
 - [Zapier](https://zapier.com/)

他にも多くのNoCodeツールがあります。[こちらのサイト](https://www.nocode.tech/)にそれぞれの分野ごとにNoCodeツールがまとめられています。

Webflowで作られたイケてるサイトがあったので、ここでご紹介します。
[Happy Hues](https://www.happyhues.co/)というサイトで、デザイン用のカラーテンプレートが紹介されています。単純にカラーパレットを紹介するだけでなく、UIコンポーネントのどこでどの色を使ったら良いかまで載っています。サイトは左のナビゲーションドロワーでパレットが選択でき、ボタンを押せばカラーをコピーできます。
![ezgif.com-video-to-gif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397153/244afe23-4ccd-e5dd-e5e1-6fbd7846242d.gif)

「このレベルのサイトがコーディング無しで作れるなら、俺、要らなくない?」

**NoCodeとどう向き合うか**
ここからは私見ですが、NoCodeがフロントエンドエンジニアを置き換えるとか、プログラミングが不要になるといった対立構造を生むのかと言われるとそうとも言い切れないと考えています。NoCodeによってデザインがすぐに製品になるというメリットが得られる一方で、サービス側で提供されている以上の機能を実現することはできないというデメリットも一緒に引き受ける必要がでてきます。
大切なのはNoCodeと戦うのではなく、NoCodeのもつメリットをいかに活かすかを考えることだと思います。NoCodeを使えば、手軽に早くモックが作れるのでアイディアが市場で通用するものなのか、低コストで試すことができます。以前は、市場の反応をみるために早く動くもの開発することが求められていましたが、今後はNoCodeで手っ取り早くテストが行えるようになるかもしれません。
さらにこれまでプログラミングという障壁のためにサービス開発に参入できなかった層が、市場に参入できるようになったり、本来であれば、何人ものエンジニアを雇い、何ヶ月もかけて作っていたサービスを個人が数週間でローンチできるものになったりするかもしれません。
つまり、NoCodeが**サービス、アプリ開発の大衆化をもたらしてくれる**という可能性もみることができます。

# 終わりに
フロントエンドについて学び始めてまだ4ヶ月ですが、ちょっと調べただけでも様々な技術があって、そこがフロントエンドの良さであり、悪さでもあると思いました。これまでPythonで適当なクローラーやロボットの制御プログラムを書いていた自分としては、この4ヶ月間はまさに激動の4ヶ月でした。
最初はフロントエンド技術全体を俯瞰してみるつもりで調べ始めたのですが、まんまとドツボにはまり、最近は自分でアプリを作ってみたいと思うようになりました。この出会いに関してはバイト先に感謝したいです。
まだまだフロントエンド初心者なので記事内に書かれていることが間違っていたり、語弊を生む記述になっている可能性が多々あります。よろしければ、コメント等で教えていただけると助かります。「〇〇がない!やり直し!!」等のコメントも受け付けています(笑)。