content-visibility について

# content-visibility について

指定した要素の子孫要素をレンダリングするかを制御するもの

## 値は３つある

| 値      | 概要                                                                                                                                         |
| ------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| visible | 無効。子孫要素を通常通りレンダリングする                                                                                                     |
| hidden  | 子孫要素の内容のレンダリングをスキップする                                                                                                   |
| auto    | レイアウト・スタイル・ペイントの封じ込めを ON にして、viewport 外の場合はレンダリングをスキップし、viewport 内の場合はレンダリングを開始する |

## content-visibility: visible

これは通常通りのレンダリングを行う状態。
説明は割愛。

## content-visibility: hidden

これは指定した要素の `子孫要素` を非表示にする。

他の要素を消す CSS と何が違うの？

| 値      | 概要                                                                                                                                         |
| ------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
|display:none|指定した要素を非表示にしてレンダリング状態を破棄するので、再表示したい時は一から再レンダリングする必要があり、コストは重い|
|visibility: hidden|指定した要素を非表示にしてレンダリング状態は維持し、要素の表示スペースも維持する。再表示したい場合はレンダリング状態は維持してるのでコストが軽い|
|content-visibility: hidden|レンダリング状態を維持したまま、子孫要素を非表示にして表示スペースも非表示にする。レンダリング状態は維持してるので再表示もコストが軽い。(子孫要素を非表示にするだけで自分自身に指定された with, margin などは維持する)|


## content-visibility: auto

レイアウト・スタイル・ペイントの封じ込めを ON にして、viewport 外の場合はレンダリングをスキップし、viewport 内の場合はレンダリングを開始する。なんかいい感じ。

### レイアウト・スタイル・ペイントの封じ込めを ON とは？

css contain というのが関係しています。

css contain とはブラウザに指定した要素は ○○ な状態の要素だから子要素などは解析せずにレンダリングの最適化しちゃってくださいと伝える感じのもの。

### containってなに？

| 値     | 説明                                                                                                                                        |
| ------ | ------------------------------------------------------------------------------------------------------------------------------------------- |
| size   | 指定した要素のサイズが子孫要素の影響を受けないことを宣言する。                                                                              |
| layout | 指定した要素が親兄弟要素のレイアウトに影響を与えないことを宣言する                                                                          |
| style  | 指定した要素の子孫要素以外にも影響をあたえる CSS プロパティを子孫要素に適用させないようにしたり、子孫要素の中だけで完結させることを宣言する |
| paint  | 指定した要素の外側に子要素がはみ出さない事を宣言します                                                                                      |

#### size

これを指定した場合、サイズも同時に指定する必要があります。

サイズを指定しない場合は高さ０幅０になるので、事前に子要素の高さ、幅を計算した上で高さ、幅を設定してあげるとよいでしょう。

#### layout

これを指定した場合、position:absolute, position:fixed が設定されている子要素が layout を設定した要素を基準点にします。また float を設定した要素も layout を指定した要素の内で break されます。高さを指定して子要素がはみ出した場合は表示される。

#### style

あんまり利用したことないプロパティが影響するみたい
https://drafts.csswg.org/css-contain/#containment-style

#### paint

layout とほぼ同じ状態になる。高さを指定して子要素がはみ出した場合は非表示になる。

### 改めて、レイアウト・スタイル・ペイントの封じ込めを ON とは？

つまり、`contain: layout style paint` を指定した状態ということになる。

且、viewport 外の要素に関しては size も指定している状態になります。

なので最初に記載した通り、適切に設定することでレンダリングをスキップすることができるようになるので、レンダリングしなくなった分パフォーマンスが向上するわけです。

### 要素のサイズを事前に確保しておこう

content-visibility: auto を設定することでレンダリングのパフォーマンスが向上することはわかりましたが、auto を設定することで画面外の要素は size を指定した状態になります。

つまりそのままにしておくと、高さ０幅０の状態になってしまいます。

その状態で viewport 内に要素が入った場合、子孫要素が表示状態に切り替わりますが、高さ０だった部分にコンテンツが入るので、ページがガタガタしてしまいます。

それを防ぐために width, height を事前に設定するか contain-intrinsic-size を指定する必要があります。

#### contain-intrinsic-size？

content-visibility を指定した要素の自然なサイズを指定します。

##### width, height の指定とは何が違うの？

width, height の指定は表示領域を指定するものですが、
`contain-intrinsic-size` は `contain:size` を指定した要素に適用するサイズといえるでしょう。

width, height は viewport 内でも外でも同じサイズですが、
`content-visibility: auto`に対して`contain-intrinsic-size`を指定した場合、viewport 外にある時のサイズを指定し、viewport 内にある時は無視されるわけです。

##### 自然なサイズとは？

`contain:size;`を指定した block 要素にテキストを流し込んだ場合、幅は 100%、高さはテキストの量によって決まります。このような要素に大して`content-visibility: 100px 100px;`を指定した場合、高さは 100px を確保しますが、幅は 100%のままになります。

`contain:size;`を指定し、`width: max-content;` も指定した block 要素に`content-visibility: 100px 100px;`を指定した場合、幅も高さも 100px になります。

`contain:size;`を指定し、`width:200px;`と`height:150px;`を指定した block 要素に`content-visibility: 100px 100px;`を指定した場合、幅は 200px に高さは 150px なります。

これが自然なサイズの正体です（投げやり）

参考資料：
https://wicg.github.io/display-locking/sample-code/contain-intrinsic-size-examples.html

## まとめ

content-visibility を適切に設定するとパフォーマンスがよくなるのでいい感じです。
他のブラウザでも実装されるといいですね。