jQueryを使わずしてスムーススクロール

##はじめに
jQueryを使わずにスムーススクロールを実装してみました。

##コード
さっそくコードを記載します。

```js

const links = document.querySelectorAll('a[href^="#"]');

links.forEach((link) => {
  link.addEventListener('click', (e) => {
    e.preventDefault();

    const linkId = link.getAttribute('href');
    const linkDom = document.querySelector(linkId);

    const linkPosition = linkDom.getBoundingClientRect().top;
    const currentPosition = window.pageYOffset;
    const position = linkPosition + currentPosition;

    window.scroll({
      top: position,
      behavior: 'smooth',
    });
  });
});

```
<br>
##簡単に解説

まず、href属性値のうち、「#」に前方一致するa要素群を取得します。

```js
const links = document.querySelectorAll('a[href^="#"]');
```
<br>
それぞれのa要素に対してクリックイベントリスナーを登録します。

```js
links.forEach((link) => {
  link.addEventListener('click', (e) => {
    // 処理
  });
});

```
<br>

preventDefault()メソッドは、既定のイベントをキャンセルします。
これによって、リンクをクリックした際に、瞬時にリンク先へ移動するのを防いでくれます。

```js

    e.preventDefault();
```
<br>
a要素のhref属性値を取得し(linkId)、その属性値をidに持つ要素を取得します(linkDom)。
これを基に、画面の表示領域の左上を0とした時のlinkDomのy座標を取得します(linkPosition)。
また、現在のスクロール位置のy座標を取得します(currentPosition)。

linkPositionとcurrentPositionを足し合わせると、リンク先のy座標の絶対値となります(position)。

```js

    const linkId = link.getAttribute('href');
    const linkDom = document.querySelector(linkId);

    const linkPosition = linkDom.getBoundingClientRect().top;
    const currentPosition = window.pageYOffset;
    const position = linkPosition + currentPosition;
```
<br>
最後に、window.scrollを使ってスクロールさせます。
topには絶対位置を指定する必要があるので、上記の処理(positionの算出)が必要です。
そして、オプションのbehaviorを'smooth'に指定することでスムーススクロールが実現します。

```js

    window.scroll({
      top: position,
      behavior: 'smooth',
    });
```

##おまけ

ついでに、クラスを使って表現し直してみました。

```main.js

class SmoothScroll {
  constructor() {
    this.DOM = {};
    this.DOM.links = document.querySelectorAll('a[href^="#"]');
    this._init();
  }
  _init() {
    this.DOM.links.forEach((link) => {
      link.addEventListener('click', (e) => {
        e.preventDefault();
        this._performScroll(link);
      });
    });
  }
  _performScroll(link) {
    const linkId = link.getAttribute('href');
    const linkDom = document.querySelector(linkId);

    const linkPosition = linkDom.getBoundingClientRect().top;
    const currentPosition = window.pageYOffset;
    const position = linkPosition + currentPosition;

    window.scroll({
      top: position,
      behavior: 'smooth',
    });
  }
}

const ss = new SmoothScroll();
```
<br>
HTML、CSSのサンプルも載せておきます。

```index.html

<body>
    <header class="header">
      <ul class="header-items">
        <li class="header-item"><a href="#title1">Title1</a></li>
        <li class="header-item"><a href="#title2">Title2</a></li>
        <li class="header-item"><a href="#title3">Title3</a></li>
        <li class="header-item"><a href="#title4">Title4</a></li>
      </ul>
    </header>
    <main>
      <section class="section" id="title1">
        <h2 class="title">Title1</h2>
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit,</p>
      </section>
      <section class="section" id="title2">
        <h2 class="title">Title2</h2>
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit,</p>
      </section>
      <section class="section" id="title3">
        <h2 class="title">Title3</h2>
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit,</p>
      </section>
      <section class="section" id="title4">
        <h2 class="title">Title4</h2>
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit,</p>
      </section>
    </main>
    <script src="main.js"></script>
  </body>

```

<br>

```style.css

html, body, h2, ul
 {
  margin: 0;
  padding: 0;
  border: 0;
}

ul {
  list-style: none;
}

main {
  margin-top: 70px;
}

.header {
  position: fixed;
  top: 0;
  right: 0;
  left: 0;
  z-index: 20;
  background-color: lightgray;
}

.header-items {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  padding: 0 40px;
}

.header-item {
  margin: 0 auto;
}

.header-item > a {
  text-decoration: none;
  height: 70px;
  line-height: 70px;
  display: inline-block;
  padding: 0 20px;
}

.title {
  text-align: center;
}

.section {
  padding: 40px;
  text-align: center;
  height: 100vh;
  border: 1px solid #000;
  background-color: lightcyan;
}

```
<br>
見た目はこんな感じ。
![htmlExample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/507401/2449118f-baf9-04d7-70f2-921e693c493c.png)



##まとめ
jQueryを使わなくても意外と簡単に実装可能でした。