position:sticky;について

##position: sticky;とは
スクロールに応じて要素を固定表示にすることができます。
他のpositionプロパティ(static, relative, absolute, fixed)の違いは、DOMのフローで閉めるスペースです。

staticとrelativeはドキュメントのフローで自然なスペースを保ちますが、absoluteとfixedの場合本来配置されるべきスペースは取り除かれ、フロートしているような振る舞いをし、周りの要素はabsoluteとfixedがそこに存在しないかのような挙動をとります。

stickyはこれらの両方の特性を持ったプロパティといえます。

<p class="codepen" data-height="265" data-theme-id="default" data-default-tab="html,result" data-user="arichel_unt" data-slug-hash="oNgwvGN" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="oNgwvGN">
  <span>See the Pen <a href="https://codepen.io/arichel_unt/pen/oNgwvGN">
  oNgwvGN</a> by arichel (<a href="https://codepen.io/arichel_unt">@arichel_unt</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>
CSSのstickyには、sticky itemとsticky containerという2つの主要部分が必要となります。

###sticky item
sticky itemとは、position: sticky;でスタイルを定義した要素です。ビューポートのポジションが定義したポジションと一致すると、その要素はフロートします。
###sticky container
sticky containerとは、sticky itemをラップする親要素です。これはsticky itemがフロートすることができる最大のエリアになります。
position: sticky;で要素を定義すると、自動的に親要素がsticky containerとして定義されます。sticky containerはsticky itemの範囲であり、アイテムはsticky containerから出ることはできません。
headerをフロートさせて使う場合は、headerのフロートの終着地点までラップする要素をsticky containerとなるよう指定する必要があります。
#要素の位置関係による挙動の違い
stickyにより固定させる要素のDOM上の位置関係によって、挙動の違いが生まれます。
###同じブロック内にある兄弟要素
stickyが２つ、同じsticky containerの中に存在する場合、sticky要素が覆いかぶさるように表示されます。
bodyをsticky containerとした、各セクションがsticky itemのデモです。
<p class="codepen" data-height="265" data-theme-id="default" data-default-tab="html,result" data-user="arichel_unt" data-slug-hash="WNbOzBB" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="WNbOzBB">
  <span>See the Pen <a href="https://codepen.io/arichel_unt/pen/WNbOzBB">
  WNbOzBB</a> by arichel (<a href="https://codepen.io/arichel_unt">@arichel_unt</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
###異なるブロックにある場合
1つ目のsitcky itemを2つ目のsticky itemが上に押し上げているように表示されます。
sticky itemはsticky containerの中でしかフロートができないので、1つ目のsticky itemのフロートが切れた瞬間に2つ目のsticky itemが到着するのでこのように見えます。
各セクション内のh2タグをsticky itemとしたデモです。
<p class="codepen" data-height="265" data-theme-id="default" data-default-tab="html,result" data-user="arichel_unt" data-slug-hash="dyPReeq" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="dyPReeq">
  <span>See the Pen <a href="https://codepen.io/arichel_unt/pen/dyPReeq">
  dyPReeq</a> by arichel (<a href="https://codepen.io/arichel_unt">@arichel_unt</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
##問題点
position: sticky;を定義した要素がコンテナの内側にある唯一の要素の場合、うまく機能しません。
その要素のコンテナが要素を貼り付けることができる唯一のエリアだからです。その要素は兄弟要素上でしかフロートできないため、唯一の要素である場合にはフロートすることができなくなります。
また同じ理由として、position: sticky;を指定した要素より、親要素の方が高さが短い場合も、意図したフロートの挙動にはならないので注意が必要です。
これを回避する方法は、heightを指定する事です。
<p class="codepen" data-height="265" data-theme-id="default" data-default-tab="html,result" data-user="arichel_unt" data-slug-hash="vYEZRwR" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="vYEZRwR">
  <span>See the Pen <a href="https://codepen.io/arichel_unt/pen/vYEZRwR">
  vYEZRwR</a> by arichel (<a href="https://codepen.io/arichel_unt">@arichel_unt</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>

そのほか

- 先祖要素にoverflow:hidden;もしくはoverflow:auto;がかかっていると効かない
- overflow:scroll;で高さの指定がないと効かない(高さの指定があると効く)



ブラウザ・サポートは[こちら](https://caniuse.com/#feat=css-sticky)をご覧ください。