【CSS】Positionのstatic, ralative, absoluteの性質を理解する

# はじめに
CSSのプロパティである**positionの値による配置の変化**をまとめました。
**static, ralative, absolute**の組合せによってどのような変化があるかを見ることで、各値の性質について考えていきます。

各値の定義については下記リンクをご覧ください。ここでは、実装上の変化に焦点を当てて説明します。

公式ドキュメント：https://developer.mozilla.org/ja/docs/Web/CSS/position
【CSS】positionプロパティを使いこなす！relative・abosolute・fixedの使い方：
https://creive.me/archives/13521/

# 理解すべきポイント

要素自体のpositionの値だけでなく、**他要素の値に影響を受けて配置が変化すること**がポイントです。
positionの値の組合せから、**何故その配置になっているのか**を説明できるようになれば、理解したことになると思います。

# 実行環境
Google Chrome 90.0.4430.85

# ソースコード
今後の説明ではコードの変更部分のみで話を進めていきます。
**親子要素両方とも``position: static;``**の場合（デフォルト値）となります。

- index.html

``` html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="parent">
        <div class="child"></div>
    </div>
</body>
</html>
```

- style.css

``` css
body {
    margin: 60px;
    height: 500px;
}

.parent {
    position: static; /*デフォルト値*/
    margin-top: 0;
    margin-left: 0;

    width: 100px;
    height: 100px;
    background-color: aqua;
}

.child {
    position: static; /*デフォルト値*/
    margin-top: 0;
    margin-left: 0;

    width: 50px;
    height: 50px;
    background-color: rgb(156, 189, 65);
}
```

- 実行結果

水色が親要素(parent)、抹茶色が子要素(child)です。
staticは、親要素等に依存した現在の位置となります。bodyにmarginがあるので、60px*60pxのところに親子ともに位置している状況です。


|![default.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403809/0b0b7b07-51d3-afbc-816c-f70e1a6038b5.png)|
|:-:|

# positionの値の組合せ
## 親要素：relative, 子要素：absolute

positionの値について、``.parent``を**relative**、``.child``を**absolute**に変更しました。positionが使われる代表例ですね。

```css
.parent {
    position: relative;
}
/*...*/

.child {
    position: absolute;
    top:10px;
    left:10px;
}
```

まずは、何故下図の配置になっているか考えてみてください。

|![relabs.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403809/a334cedd-ba42-caee-3c70-b580a2c68d84.png)|
|:-:|

では、理由を解説します。

relativeは、**現在の位置を起点**に要素の位置が動きます。``.parent``の現在の位置とは、body要素の左上です。したがって、**``.parent``はbody内部の左上を起点**とします。

absoluteは、**最も近い「relative」(親や先祖の要素)を起点**に要素の位置が動きます。``.child``から最も近いrelativeは``.parent``です。したがって、**``.child``は``.parent``内部の左上を起点**とします。

absoluteを「絶対位置」とだけ覚えていた私は、この説明ができませんでした。**祖先要素におけるrelativeの有無で起点が変わることに注意**したいですね。

## 親要素：absolute, 子要素：relative

次は親子のrelativeとabsoluteを入れ替えました。


```css
body {
    margin: 60px;
    border: 1px solid;
}

.parent {
    position: absolute;
    top:10px;
    left:10px;
}

.child {
    position: relative;
}
```


|![absrel.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403809/72cce153-b694-3942-fa3b-0f26e56ef92c.png)|
|:-:|


見やすさのためにbodyに枠線を入れました。何故``.parent``と``.child``はページ左上に移動したのでしょうか？


では、解説していきます。

``.parent``がabsoluteになったことにより、祖先要素にrelativeがなくなりました。すると、ページ全体が起点となるので、body要素を無視してページ左上に位置しています。

``.child``がrelativeになったことにより、``.child``は**現在の位置が起点**となります。この場合の「現在の位置」は、親要素である``.parent``内部の左上です。そのため、``.parent``と一緒に移動する形となります。

relativeの「現在の位置」とは何かと思うかもしれません。今回の場合は、**「現在の位置」＝直接の親要素の領域**とする解釈でいいと思います。

公式ドキュメントでは「文書の通常のフローに従って配置されます。」と説明されています。
文章の通常のフローとは？と思ったのですが、今回はそこまで深く知らなくても理解できるので割愛します。

### relativeのstaticとの違い
relativeは**staticと同じ起点**になります。
staticとの違いは２点です。

- top,bottomなどを利用して起点からの位置移動が可能なこと。
- absoluteが子孫要素に存在する場合、absoluteの位置に影響を及ぼす。

## 親子両方absolute
ここまでの内容が分かっていれば予想できると思うので割愛します。親子ともに全部ページの左上が起点となります。

## 親子両方relative
基本的にデフォルトの親子両方staticと同じになりますが、staticとの違いは起点からの位置指定ができることです。

## その他
他にstaticも絡めて以下の項目も紹介したかったのですが、書くモチベが途絶えたので省略します。
是非自分の環境でいじってみて理解を深めてください！

- 親要素：static, 子要素：absolute
- 親要素：static, 子要素：relative

## まとめ
-  **static**は、親要素等に依存した現在の位置（文書の通常のフローの配置）となる。
-  **absolute**は、基本ページの左上の位置が起点
    - しかし、**祖先要素にrelative**が存在する場合、起点がrelativeに依存
-  **relative**は、**デフォルトのstaticと基本同じ**（現在の位置が起点）。しかし、**違いが２点**ある。
    - relativeは起点からの位置変更が可能
    -  **子孫要素にabsolute**が存在する場合、absoluteの起点に影響を及ぼす。


## （番外）親子両方absolute。だけど親要素で位置指定なし

```css
.parent {
    position: absolute;
}

.child {
    position: absolute;
    top:10px;
    left:10px;
}
```
|![absabs_notlocate.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403809/c9df5c2d-6059-b7e7-5aa8-3496e7226c08.png)|
|:-:|

これについては、何故**ページの左上**ではなく、**bodyの左上**に配置されるのか分かりませんでした。
``.child``の親要素にrelativeがなくなったので、ページ全体が起点になると推測していました。
しかし、``.parent``がrelativeのときと同じ表示になりました。
``.parent``を位置指定するともちろん両方ともページ全体が起点となります。
もし分かる方がいましたらご教授いただけると幸いです。


# 終わりに
最後まで読んでいただきありがとうございました！
自分で触ってみることが一番なので、是非自身の環境で実行してみてください。
疑問点等ありましたらご質問ください。

# 余談
最後に、今回久々にcssをいじっていて気付いたことがあるので共有します。

CSSとかHTMLのコメントアウトって付けるの面倒臭いですよね。
そんなときに便利なショートカットがあります。

- 「Ctrl + / 」（行コメント）
- 「Shift + Alt + a 」（ブロックコメント）

何を今更と思う方が大半かと思いますが、HTMLやCSSでも適用できるのは盲点でした。。前後に記号をつけるコメントアウトの記法では効果抜群です。