position: sticky をエミュレートしてみた

エミュレートしてみました。動作確認は適当です。
https://gist.github.com/abicky/7c351a6ed1170d9a8c5f#file-sticky-js

Webkit 系のブラウザ(というかスマートフォンの主要ブラウザ)のみを意識して実装しています。
この JS をロードすると、次のような position: sticky を

#header {
  position: sticky;
  top: 0;
}

#header {
  position: sticky;
  bottom: 20px;
}

次のように記述することで実現できます。

document.addEventListener('DOMContentLoaded', function() {
  sticky(document.getElementById('header'), { top: 0 });
  sticky(document.getElementById('footer'), { bottom: 20 });
});

特徴

  • jQuery 不要
  • 動的にコンテンツの高さが変わっても大丈夫(Ajax で取得した内容を追加するとか、画像の読み込みが完了するとか)
    • 60 FPS で毎回オフセットを計算したり要素の高さを計算しているのでその分パフォーマンス面が微妙かも

デモ

デモページ

ソース↓

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=320,user-scalable=no">
  <style>
    body {
      margin: 0;
      padding: 0;
      height: 3000px;
    }
    #parent {
      margin-top: 600px;
      border: solid black 1px;
      width: 320px;
    }
    #header {
      color: white;
      background: red;
    }
    #footer {
      color: white;
      background: blue;
    }
    .box {
      width: 320px;
      height: 100px;
      border: solid black 1px;
    }
  </style>
</head>
<body>
下にスクロールしてください
<div id="parent">
  <div id="header" class="box">Header</div>
  <div class="box">1</div>
  <div class="box">2</div>
  <div class="box">3</div>
  <div class="box">4</div>
  <div class="box">5</div>
  <div class="box" style="display: none;">6</div>
  <div class="box" style="display: none;">7</div>
  <div class="box" style="display: none;">8</div>
  <div class="box" style="display: none;">9</div>
  <div class="box" style="display: none;">10</div>
  <div id="footer" class="box">Footer</div>
</div>
<script src="https://rawgit.com/abicky/7c351a6ed1170d9a8c5f/raw/de61d7947118a28ca5abbc206b425157adad5240/sticky.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
  // 動的に parent element の高さを変える(auto pager で要素が追加されるケースとか)
  setTimeout(function() {
    var boxes = document.getElementsByClassName('box');
    for (var i = boxes.length - 1; i >= 0; --i) {
      boxes[i].style.display = 'block';
    }
  }, 1000);

  sticky(document.getElementById('header'), { top: 10 });
  sticky(document.getElementById('footer'), { bottom: 10 });
});
</script>
</body>
</html>

似たような JS

早く position: sticky が主要ブラウザで使えるようになるといいですね!!