position: sticky; とページ内リンクの相性

CSSで`position: sticky;`と設定し､ページジャンプを試みた際のものをまとめました｡

## どんな状況か
- 本文中にいくつか見出しがあり､閲覧中の見出しを常にページ上部で留めておきたい｡
- 目次を設け､ページ内ジャンプで任意の見出しへ移動したい

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953314/aa8fc1c9-4bab-1ebd-d61f-bddfafcdcc23.png)

## 実際に記述する

コードも短いので先に全て記載します｡

```html:index.html
<!DOCTYPE html>

<head>
  <meta charset="utf-8">
  <link rel="stylesheet" href="style.css">
</head>

<body>
  <nav>
    <ul>
      <li><a href="#">TOP</a></li>
      <li><a href="#first">First</a></li>
      <li><a href="#second">Second</a></li>
    </ul>
  </nav>
  <h1>ページタイトル</h1>
  <h2 id="first">First</h2>
  <p>素晴らしい本文(sticky要素1)</p>
  <p>素晴らしい本文(sticky要素1)</p>
  <!-- 以下略 -->
  
  <h2 id="second">Second</h2>
  <p>素晴らしい本文(sticky要素2)</p>
  <p>素晴らしい本文(sticky要素2)</p>
  <!-- 以下略 -->
  
</body>
```
```css:style.css
nav {
  position: fixed;
  right: 0;
  z-index: 100;
  background-color: #fff;
}

h2 {
  position: sticky;
  top: 0;
  background-color: #fff;
  border-style: solid;
  border-width: 0 0 .1rem 0;
}
```

表示結果は上の画像｡

## 挙動確認
順番に検証して確認する｡
### TOP から First OR Second へジャンプ

- 結果：飛べる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953314/6fdfa95c-02a7-3e6d-b0cd-5f08d2433efc.png)

### First から Second へジャンプ

- 結果：飛べる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953314/877b69a9-248e-eb0f-b09e-db018fd3dd28.png)

### First OR Second から TOP へジャンプ

- 結果：**飛べない**

### Second から TOP OR First へジャンプ

- 結果：**飛べない**

### 検証結果

`position: sticky;`プロパティが付与された要素へ､同じブロック内からジャンプできない｡

## 上手くいかない理由

同じブロック内(今回は`main`)でその要素より下にスクロールしている場合､同じ`sticky`要素が覆っている状況なためである｡

実際にChromeのデベロッパーモードで要素を消して確認する｡

- `Second`を消す前

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953314/7448ed65-67ff-35ae-19af-eacb9fb0638e.png)

- `Second`を消した後

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953314/82ba652e-bdea-f283-f30f-b07b9bddee4a.png)

隠れている部分に`id`のプロパティを持つ要素が付いてきている｡

勿論､この状態でFirstにジャンプしてもジャンプされているように見えないのは納得できると思う｡

## どう解決するか

### `<section>` タグを使う

[`<section>`](https://developer.mozilla.org/ja/docs/Web/HTML/Element/section)は

> `<section>` は HTML の要素で、文書の自立した一般的なセクション（区間）を表します。そのセクションを表現するより意味的に具体的な要素がない場合に使用します。少数の例外を除いて、セクションには見出しを置いてください。

引用: https://developer.mozilla.org/ja/docs/Web/HTML/Element/section

と記されているので実際に使う｡

```diff_html:index.html
<!-- 前略 -->
<h1>ページタイトル</h1>
+ <section>
    <h2 id="first">First</h2>
    <p>素晴らしい本文(sticky要素1)</p>
    <p>素晴らしい本文(sticky要素1)</p>
    <p>素晴らしい本文(sticky要素1)</p>
    <p>素晴らしい本文(sticky要素1)</p>
    <p>素晴らしい本文(sticky要素1)</p>
    <p>素晴らしい本文(sticky要素1)</p>
    <p>素晴らしい本文(sticky要素1)</p>
    <p>素晴らしい本文(sticky要素1)</p>
    <p>素晴らしい本文(sticky要素1)</p>
    <p>素晴らしい本文(sticky要素1)</p>
    <p>素晴らしい本文(sticky要素1)</p>
    <p>素晴らしい本文(sticky要素1)</p>
    <p>素晴らしい本文(sticky要素1)</p>
    <p>素晴らしい本文(sticky要素1)</p>
+ </section>
<!-- 後略 -->
```
`Second`も同様に記述する｡

#### 結果

- `Second`から`First`にジャンプした結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953314/3ac03ea4-dd5f-4b9d-0207-208e418007df.png)

このようにジャンプした｡

**違う**

### `div` 要素を直前に設けて `id` を付与する

`div`(または`span`)タグを直前に配置して`id`を付与すれば擬似的にジャンプできるのでは､という仮説です｡

```html:index.html
<!-- 前略 -->
<h1>ページタイトル</h1>
  <section>
    <div id="first"></div> <!-- この行を追加 -->
    <h2>First</h2>
    <p>素晴らしい本文(sticky要素1)</p>
    <p>素晴らしい本文(sticky要素1)</p>
    <p>素晴らしい本文(sticky要素1)</p>
    <p>素晴らしい本文(sticky要素1)</p>
    <p>素晴らしい本文(sticky要素1)</p>
    <p>素晴らしい本文(sticky要素1)</p>
    <p>素晴らしい本文(sticky要素1)</p>
    <p>素晴らしい本文(sticky要素1)</p>
    <p>素晴らしい本文(sticky要素1)</p>
    <p>素晴らしい本文(sticky要素1)</p>
    <p>素晴らしい本文(sticky要素1)</p>
    <p>素晴らしい本文(sticky要素1)</p>
    <p>素晴らしい本文(sticky要素1)</p>
    <p>素晴らしい本文(sticky要素1)</p>
  </section>
<!-- 後略 -->
```

#### 結果

- `Second`から`First`にジャンプした結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953314/3994c173-0db0-8c20-d4d1-299590da749c.png)

**成功**

成功したものの､シンプルに実装したとは言えない結果となった｡

## 結論
`div`タグまたは`span`タグを直前に配置して`id`を付与すれば擬似的に成功する｡

可能ならHTMLを殆ど変更せずに実現したいところ｡また分かり次第追記する｡

## 参考

https://developer.mozilla.org/ja/docs/Web/CSS/position

https://caniuse.com/css-sticky