Nuxt.jsで実践的にポートフォリオサイトを作る！ 他サイトのパクリ方入門

# はじめに

この記事は、[HUITアドベントカレンダー2018](https://qiita.com/advent-calendar/2018/huit) 1日目の記事になります

## 対象者
- html, css, jsをそれぞれ一行だけでも書いたことがある
- **他人のサイトをパクる方法を知りたい**
- **Nuxt.jsをとりあえず使ってみたい、流行りに乗りたい**
- 自分のポートフォリオサイトを作りたい


## この記事を読んでできること
- Nuxt.jsのための環境設定
- 他のサイトからのパクリ方がわかる
- 自分のスキルをカード形式で表示するサイトを作る

（正直Nuxt.jsはおまけ程度の扱いです)


## Nuxt.js(Vue.js)とは
Vue.jsのサーバーサイドレンダリング用フレームワークです。
Nuxt.jsにはVue.jsの良さをそのまま使えます。

### Nuxt.js(Vue.js)を使うと何が嬉しいか
- **状態管理変数が楽に使える**
  - フォームへの入力や、ボタンによるon/offなど
  - jqueryなどを使うよりも簡潔でわかりやすいコードが書ける
- SEO対策
  - nuxt generateで静的ページを生成したときでも有効なんですかね？これは不明です
- **ほとんど普通のHTML・CSSのまま書ける**
  - 初心者が混乱しにくい
  - 類似フレームワークのReactはjsxという独自の記法を使うので, HTMLやCSSの書き方が若干特殊
- デフォルトでVue.jsの拡張ライブラリが使えるので簡単にVue.js+αなサイトが作れる




## まずはnuxt.jsプロジェクトを作ろう
nuxt.jsを使うには、node.jsのインストールと、npmコマンドを使えるようにする必要があります。

ここからインストールしましょう。 https://nodejs.org/ja/download/

おそらく、node.jsをインストールすれば、npmコマンドが使えるはずです。
コマンドプロンプト or ターミナル or Powershell or 端末 を開いて、以下を入力しましょう

**ここからは `$`マークから始まるものはターミナルでのコマンドになります。注意：コマンド自体には$は含まないようにしてください。**

Nuxt公式に則って、create-next-appを使います
参考: https://ja.nuxtjs.org/guide/installation/#nuxt-js-を使ったスターターテンプレート

```bash
$ npx create-nuxt-app my-portfolio-site
```

すると、以下のように色々聞かれますが、今回は全てデフォルト（クリックするだけ）でいきます。

```bash
? Project name my-portfolio-site
? Project description My portfolio Nuxt.js project # 微妙に変えましたが、ここは何を書いても問題ありません
? Use a custom server framework none
? Use a custom UI framework none
? Choose rendering mode Universal
? Use axios module no
? Use eslint no
? Use prettier no
? Author name <ユーザ名>
? Choose a package manager npm
```

本当はeslintやprettierを使った方がコードが綺麗になるように指摘してくれるので、入れた方がいいと思います。ただ、最初に作る遊びプロジェクトならない方がnuxt(vue)の文法以外でつまづくのは面倒なのでこれでもいいと思います。

そのままnuxtプロジェクトの作成がはじまります、終わると以下のような表示が出てきます。

```
...

  To get started:

    cd my-portfolio-site
    npm run dev

  To build & start for production:

    cd my-portfolio-site
    npm run build
    npm start
```

では早速、上の To get started: に則って、プロジェクトを起動してみましょう！

```bash

$ cd my-portfolio-site
$ npm run dev
```

```

...

✔ Client
  Compiled successfully in 3.18s

✔ Server
  Compiled successfully in 2.98s

ℹ Waiting for file changes                                           18:21:20

   ╭─────────────────────────────────────────────╮
   │                                             │
   │   Nuxt.js v2.3.4                            │
   │   Running in development mode (universal)   │
   │   Memory usage: 157 MB (RSS: 235 MB)        │
   │                                             │
   │   Listening on: http://localhost:3000       │
   │                                             │
   ╰─────────────────────────────────────────────╯
```

こんな感じで、Listening on: http://localhost:3000 と出てくるので、ブラウザで
http://localhost:3000 を開いてみましょう。

以下のような画面が表示されるはずです！

<img width="1371" alt="スクリーンショット 2018-11-29 18.22.55.png" src="https://qiita-image-store.s3.amazonaws.com/0/164020/9f082757-6d6f-1cfb-925f-85d2c86515b0.png">

これで準備は完了しました。

お好みのエディタから my-portfolio-site プロジェクトを開いて、エディットの準備をしましょう！

#### nuxtトラブルシューティング: 「やたらページが勝手にリロードされる」
nuxt.jsを使っていると、特に同じnuxtページを２つのタブで開いてしまったりした時に起こりやすいです。これが起こったらまずはnuxtページを開いているタブを一つだけ残して、nuxtサーバーを再起動させましょう。（`$ npm run dev` したターミナルでctrl + c (または ctrl + d など）をした後、再度 `$ npm run dev`）


## カスタマイズする
ここからは実際にポートフォリオサイトを作っていきます。先ほどのデフォルトページをカスタマイズしていきます。

でも、**いきなりゼロから書いていくのは難しいです。なので、基本は他のサイトをパクって（参考にして）作ることになる** と思います。ここからはパクリ方を実践的に説明していこうと思います。

## パクるサイトを決める方針
- コンテンツが大きな魅力を握っていないサイト
  - アニメ公式サイトなどを真似しようとすると、イラストがそのサイトの大きな魅力になっている場合もあります。コンテンツが自前で用意できないと微妙なサイトになってしまいがちです 
- css・jsが少ないサイト
  - css・jsが多いとコードの解読が難しく、特にjsは一部のクリティカルなコードが読めないと方針が全崩壊するのでjsが多いサイトならパクるのは諦めた方が良いです。



## パクる手順
1. パクりたいサイトを見つける（適当にネットサーフィンしていれば、いい感じのデザインのサイトが見つかるはずです）
2. パクリたい部分のhtmlをコピペ
3. パクリたい部分のhtmlの　class（クラス） または id でcss・jsファイルを検索
4. 必要に応じて修正

ちなみに、htmlのclass, idとはこれのことです

```html
<p class="vue">クラス名にvueを指定しています</p>
<p id="nuxt">idにnuxtを指定しています</p>
```


## 前準備
pages/index.vueは、自動生成されています。なので今は以下のようになっていると思います。


```pages/index.vue
<template>
  <section class="container">
    <div>
      <logo/>
      <h1 class="title">
        my-portfolio-site
      </h1>
      <h2 class="subtitle">
        My portfolio Nuxt.js project
      </h2>
      <div class="links">
        <a
          href="https://nuxtjs.org/"
          target="_blank"
          class="button--green">Documentation</a>
        <a
          href="https://github.com/nuxt/nuxt.js"
          target="_blank"
          class="button--grey">GitHub</a>
      </div>
    </div>
  </section>
</template>

<script>
import Logo from '~/components/Logo.vue'

export default {
  components: {
    Logo
  }
}
</script>

<style>
/*省略*/
</style>
```

これをまず以下のように編集しましょう。


```pages/index.vue
<template>
</template>

<script>

export default {
  components: {
  }
}
</script>

<style>
</style>
```

localhost:3000 で何も表示されなくなればOKです。


## 実装1: 自分のスキルをカード形式で表示
ここからは実際にあるサイトをもとにパクっていきます。

### 1-1. パクりたいサイトを見つける

このサイトからパクりました。ありがとうございます。
https://nsuzuki7713.github.io/portfolio/

この方は[githubにもコードを公開している](https://github.com/nsuzuki7713/portfolio)ので、ある程度許していただけるという判断です。

さっそくパクります。

## 1-2. パクリたい部分のhtmlをコピペ
デベロッパーツールを開きます。safariだと以下の図のようになります。左側に出ているスキルカードをパクります。

  - Chrome: https://saruwakakun.com/html-css/basic/chrome-dev-tool
  - Safari: https://engineershareinfo.com/2018/01/08/how-to-use-safari-web-developer-tool/
  - Firefox: https://aipon.net/blog-css/ の「初心者でも簡単に『CSS』を確認する方法」のセクション


<img width="1371" alt="スクリーンショット 2018-11-29 17.37.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/164020/43abb39a-3299-adbd-8943-c783b11f9f5b.png">

<img width="1527" alt="スクリーンショット 2018-11-29 17.38.40.png" src="https://qiita-image-store.s3.amazonaws.com/0/164020/05cce072-b336-63e9-5078-f73f8f2271c9.png">

開発者ツールの「リソース」タブを開くと、上の図のようにソースコードが普通のテキストとして表示されます。
上図のように普通に選択してコピペします。

元のコードからコピペすると、以下のような感じになりました。あまり大胆にQiitaに貼ることはできないので、だいぶ省略します

```html
      <section class="section" id="skill">
        <div class="inner">
          <!-- 省略 -->
          <div class="card-wrapper">
            
            <div class="card">
              <div class="skill-desc">
                <h3 class="skill-desc-title"><i class="fas fa-desktop"></I>スキルのタイトル</h3>
                <p>説明文</p>
                <table class="table table-borderless">
                  <thead>
                    <tr>
                      <th scope="col">技術</th>
                      <th scope="col">経験年数</th>
                      <th scope="col">スキル</th>
                    </tr>
                  </thead>
                  <tbody>
                    <tr>
                      <th scope="row">技術名1</th>
                      <td>xx年</td>
                      <td><span class="rating"><p class="rate rate4"></p></span></td>
                    </tr>
                    <tr>
                      <th scope="row">技術名2</th>
                      <td>xx年</td>
                      <td><span class="rating"><p class="rate rate4"></p></span></td>
                    </tr>
                  </tbody>
                </table>
              </div>
            </div>
          </div>
        </div>
      </section> 
```

これをpages/index.vueに書いてみましょう

```pages/index.vue
<template>
  <section class="section" id="skill">
    <div class="inner">
      <div class="card-wrapper">
        <div class="card">
          <div class="skill-desc">
            <h3 class="skill-desc-title"><i class="fas fa-desktop"></I>スキルのタイトル</h3>
            <p>説明文</p>
            <table class="table table-borderless">
              <thead>
                <tr>
                  <th scope="col">技術</th>
                  <th scope="col">経験年数</th>
                  <th scope="col">スキル</th>
                </tr>
              </thead>
              <tbody>
                <tr>
                  <th scope="row">技術名1</th>
                  <td>xx年</td>
                  <td><span class="rating"><p class="rate rate4"></p></span></td>
                </tr>
                <tr>
                  <th scope="row">技術名2</th>
                  <td>xx年</td>
                  <td><span class="rating"><p class="rate rate4"></p></span></td>
                </tr>
              </tbody>
            </table>
          </div>
        </div>
      </div>
    </div>
  </section>
</template>

<script>

export default {
  components: {
  }
}
</script>

<style>

</style>
```

以下のようなページができました。

<img width="1470" alt="スクリーンショット 2018-11-30 20.06.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/164020/a79d8324-ed15-84c2-9b62-1cf7f2fc046b.png">


コピペしたままのコードの通りに書くと、htmlにスキル紹介のテキストをベタ書きすることになり、汚いのですが、さっさと作るためにここではコピペを整理するだけにします。


### 1-3. パクリたい部分のhtmlの class(クラス) または id でcss・jsファイルを検索

さて、htmlがコピペできたので、htmlの一番外側のタグのclass or idで検索をかけましょう。

htmlの一番外側のタグは、以下のようになっています。

```html
<section class="section" id="skill">
```

なぜ一番外側のタグかというと、cssは一番外側のタグの情報を使ってスタイルを設定することが多いからです。

例

```css
#skill .card-wrapper {
  width: 80%;
  /* 中略 */
}
```

cssでは、idの場合は `#skill` のように `#` をつけます。
classの場合は `.section` のように `.` をつけます。これも覚えておきましょう

今回の場合、`<section class="section" id="skill">` のclass または idを使って、cssの検索ワードを決めます.
 classはsectionという汎用的な言葉を使っているので、より部分的な意味のid=skillを使って検索しましょう。

スタイルシートだけでも結構ファイルがあってどこにあるかわかりづらいですが、なんとなくいっぱい書かれていそうな「style.css」を探してみます。（今回は動きのないサイトからパクるので、jsを使っていなさそうという判断でjsは検索しません）

すると、ヒットしました。このかたまりをコピペしてみましょう。

<img width="1535" alt="スクリーンショット 2018-11-29 17.52.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/164020/07e75f99-884b-6dcc-31da-9ef0684c0919.png">



二つの部分に別れているので注意しましょう。

```css
#skill .card-wrapper {
  width: 80%;
  /* 中略 */
}

/* 中略 */

#skill .rate5:after {
  width: 100px;
}
```

```css
/*media Queries 767
----------------------------------------------------*/

/* 中略 */
  #contact .contact-list ul {
    width: 100%;
  }
```

これらのcssを追加します。

```pages/index.vue
<style>

#skill .card-wrapper {
  width: 80%;
  /* 中略 */
}/* この閉じかっこがくるまでコピペ

/* 中略 */

#skill .rate5:after {
  width: 100px;
}

/*media Queries 767
----------------------------------------------------*/

/* 中略 */
  #contact .contact-list ul {
    width: 100%;
  }

</style>
```

すると、以下のように見えるはずです。

<img width="1515" alt="スクリーンショット 2018-11-30 20.40.23.png" src="https://qiita-image-store.s3.amazonaws.com/0/164020/227efef2-2b52-e4b3-77f9-402751668152.png">


とりあえずcssはつきましたが、なぜかずれてしまっています。（（元サイトの方だとうまく行っているので、コピペ範囲ミスです。）修正してみましょう。


## 1-4. 必要に応じて修正
さて、ここからが本番です。コピペしただけではうまく動かないことが多いです。

### どのようにして修正すべき箇所を見つけるか
僕は以下のステップで修正しています

1. ページを見て直したいところを見つける
2. デベロッパーツールを使って、直したいところとhtmlタグの対応を調べる
3. htmlタグのclass, idから、対応するcss・jsを調べる（本記事ではcssのみ）

では、早速実践してみます。

### 1. ページを見て直したいところを見つける
今回は、上のスクショから分かるように、「スキルのタイトル」と「説明文」が中央にずれてしまっている部分を直したいところとします。

### 2. デベロッパーツールを使って、直したいところとhtmlタグの対応を調べる
デベロッパーツールを開くと、右にhtml要素が出てきます。これを展開していって、直したいところとhtmlタグの対応を見つけます。

<img width="1458" alt="スクリーンショット 2018-12-01 20.27.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/164020/bd37145a-fd3a-2f6c-3ffa-6a3a2ed57486.png">

これをみると、どうやら以下のhtmlタグの要素の幅が不必要に大きいことがわかります。

```html
<div class="skill-desc"></div>
```

### 3. htmlタグのclass, idから、対応するcss・jsを調べる

上のhtmlのclass名を元にcssを検索します。
エディタの検索で「skill-desc」のcssを探すと、以下のようにヒットすると思います。


```pages/index.vue
   #skill .skill-desc {
     flex-basis: calc(100% - 75px - 30px);
     text-align: center;
   }
```

flex-basisがあやしそうなので、pages/index.vue から、一行削除します。

```diff
   #skill .skill-desc {
-    flex-basis: calc(100% - 75px - 30px);
     text-align: center;
   }
```

<img width="1583" alt="スクリーンショット 2018-12-01 16.28.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/164020/ec62b8aa-a01b-19ed-bf7a-c895b8ae90ee.png">

とりあえず揃いました。

こんな感じで修正していきます。ここからは、デベロッパーツールの説明はなしにしますが、手順は基本的に同じです。

## 修正２

上で少し良くはなりましたが、ちょっと「説明文」の文字が下にくっつきすぎです。（元サイトの方だとうまく行っているので、コピペ範囲ミスです。）

html部分を見てみます。

```pages/index.vue
          <div class="skill-desc">
            <h3 class="skill-desc-title"><i class="fas fa-desktop"></I>スキルのタイトル</h3>
            <p>説明文</p>
            <table class="table table-borderless">
              <thead>
              <tr>
                <th scope="col">技術</th>
                <th scope="col">経験年数</th>
                <th scope="col">スキル</th>
              </tr>
              </thead>
              <tbody>
              <tr>
                <th scope="row">技術名1</th>
                <td>xx年</td>
                <td><span class="rating"><p class="rate rate4"></p></span></td>
              </tr>
              <tr>
                <th scope="row">技術名2</th>
                <td>xx年</td>
                <td><span class="rating"><p class="rate rate4"></p></span></td>
              </tr>
              </tbody>
            </table>
          </div>
```

これを見ると、以下のように、説明文の下にはtableがあることがわかります。

```html
<p>説明文</p>
<table class="table table-borderless">
```

この場合、pタグに対してcssのmargin-bottomをつけるか、tableタグに対してmargin-topをつけるという選択肢が思いつきます。（marginとは余白のことです。）

ここでは、tableに対してmargin-topをつけることにします。

pages/index.vue

```diff 
   .table{
     text-align: center;
+    margin-top: 20px;
   }

```

こんな感じになります。

<img width="1494" alt="スクリーンショット 2018-11-30 21.52.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/164020/49dc1883-06a4-5136-2e83-c5ba4bba85ea.png">

これでとりあえずましになりましたね。パクリは結構こういう微妙な修正が必要になることも多いです。（基本、完全にパクれていないのが原因）

## 修正３　数を増やす
しかし、ここで安心はできません・・・スキルカードは、一つでは物足りないですよね？４つほど追加してみましょう。

```pages/index.vue
<template>
  <section class="section" id="skill">
    <div class="inner">
      <div class="card-wrapper">
        <div class="card">
          <div class="skill-desc">
            <h3 class="skill-desc-title"><i class="fas fa-desktop"></I>スキルのタイトル</h3>
            <p>説明文</p>
            <table class="table table-borderless">
              <thead>
              <tr>
                <th scope="col">技術</th>
                <th scope="col">経験年数</th>
                <th scope="col">スキル</th>
              </tr>
              </thead>
              <tbody>
              <tr>
                <th scope="row">技術名1</th>
                <td>xx年</td>
                <td><span class="rating"><p class="rate rate4"></p></span></td>
              </tr>
              <tr>
                <th scope="row">技術名2</th>
                <td>xx年</td>
                <td><span class="rating"><p class="rate rate4"></p></span></td>
              </tr>
              </tbody>
            </table>
          </div>
        </div>
        <div class="card">
          <div class="skill-desc">
            <h3 class="skill-desc-title"><i class="fas fa-desktop"></I>スキルのタイトル</h3>
            <p>説明文</p>
            <table class="table table-borderless">
              <thead>
              <tr>
                <th scope="col">技術</th>
                <th scope="col">経験年数</th>
                <th scope="col">スキル</th>
              </tr>
              </thead>
              <tbody>
              <tr>
                <th scope="row">技術名1</th>
                <td>xx年</td>
                <td><span class="rating"><p class="rate rate4"></p></span></td>
              </tr>
              <tr>
                <th scope="row">技術名2</th>
                <td>xx年</td>
                <td><span class="rating"><p class="rate rate4"></p></span></td>
              </tr>
              </tbody>
            </table>
          </div>
        </div>

```

<img width="1306" alt="スクリーンショット 2018-12-01 16.52.26.png" src="https://qiita-image-store.s3.amazonaws.com/0/164020/3843ec63-1996-1ca5-7ec9-640523866e68.png">

なんか配置がおかしいですね。
ここでT字型になっていますが、どうやら１個目のカードだけ、一列全部を使ってしまう設定になっているようです。
cssってこんなこともできるんですね。。。　（というのも、パクリ元サイト様ではそういう仕様になっていたのです）

どうやら、cardクラス全体にかかっている設定のようなので、cardクラスの記述を探してみると、以下のような`first-child`というのが見つかりました。そして`flex-basis: 100%;`という記述。なんか横100%みたいな雰囲気がします。

pages/index.vue の以下の部分を削除してみましょう。（コードを「first-child」で検索してみましょう）

```diff
-  #skill .card:first-child {
-    flex-basis: 100%;
-  }
-
```

<img width="1345" alt="スクリーンショット 2018-12-01 16.56.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/164020/3c6e1d7d-3a8a-9d0c-459f-7fea40d059fd.png">

いい感じになりました！

プログラミングではよくある話ですが、リストなどは0, 1, 2個の３パターンくらいを早めに試すのがオススメです。

だいぶいい感じになってきました。でも、まだ汚いですね。


## 修正４　中央揃えにする

なんかカードの中身が左に寄っているようです。カードの中身を中央揃えにしたいですよね。でもカードの中身ってどのタグなのでしょうか？デベロッパーツールで確認してみましょう。

<img width="1515" alt="スクリーンショット 2018-12-01 17.30.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/164020/7a3dc53e-a402-420c-4a57-5ad4247e180b.png">

ここが原因のようですね。

```pages/index.vue
<div class="skill-desc">
 <!-- 省略 -->
</div>
```

中央揃えにする場合は、CSSで基本的に３通りありますが、ここでは重要な２通りを説明します。

- margin: 0 autoを使う場合（上下に0, 左右にauto）
- text-align: center

以下、この二つの説明になりますが、「インライン要素」と「ブロック要素」という言葉に注意して読んでください。

### 選択肢1: margin: 0 auto
`margin: 0 auto` は、上下に0, 左右にautoのmarginを設定するというcssになります。今書いているコードにも、いくつかすでにふくまれています。 **marignは、ブロック要素（divなど）に効くcssです。** これを使うと、周りの要素と均等な余白になるように余白が設定されて、いい感じに中央揃えになります。> 

- 使い所: **「ブロック要素自体が左などに寄っている」とき**


### 選択肢2: text-align: center
`text-align: center` は、インライン要素を中央揃えするcssになります。
**`text-align` は、インライン要素（span, p, imgなど）に効くcssです。** インライン要素は幅を持たないのですが、親の（ネストが一つ上の）ブロック要素の幅の中で中央揃えされます。ブロック要素は幅を持っていて、その幅の中で中央揃えされるのです。

- 使い所: **「親のブロック要素は中央揃えされているが、テキストが左などに寄っている」とき**


### ではどっちを使うのか
さて、今回は、上の二つのうちどれを使えばいいかというと、`margin: 0 auto`です。なぜかというと、「ブロック要素自体が左に寄っている」からです。（上のデベロッパーツールのスクショを見たらなんとなくわかると思います。）

というわけで、以下のように編集します

```diff
  #skill .skill-desc {
    text-align: center;
+    margin: 0 auto;
  }

```

<img width="1529" alt="スクリーンショット 2018-12-01 17.36.40.png" src="https://qiita-image-store.s3.amazonaws.com/0/164020/ed5ea7a9-4db2-fe91-6799-fc66540f4b61.png">


いい感じになりました！

また、微妙にtableがずれているので、修正します。

```diff
  .table{
    text-align: center;
    margin-top: 20px;
+    margin-left: auto;
+    margin-right: auto;
  }
```

これで大体いい感じになってきたと思います！


## 修正５　際立たせる
配置はいい感じになってきましたが、あんまり、カードっぽくないです。背景色をつけてみましょう。各カードはcardクラスに囲まれているので、cardクラスにcssをつけていきます。
background-colorにお好みの色をつければ、カードっぽくなります！

```diff
  #skill .card {
    flex-basis: 46%;
    margin-bottom: 50px;
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -ms-flex-wrap: nowrap;
    flex-wrap: nowrap;
    -webkit-box-pack: justify;
    -ms-flex-pack: justify;
    justify-content: space-between;
+   background-color: #F5F5F5;
  }

```

<img width="972" alt="スクリーンショット 2018-12-01 17.43.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/164020/d17577f8-8799-6d71-0fdd-1fd53eabbced.png">

だいぶそれっぽくなったかと思います！

まだ若干修正したいところもありますが、この記事はここで終わりとさせていただきます。

この記事を読んで他サイトのパクリ方を身につけることができたと思う方はぜひいいねをください。

最後までお疲れ様でした！