モノトーンの伝説日記

Apex Legends, Splatoon, Programming, and so on...

また Webkit (Safari) の position: sticky のバグっぽい挙動を発見してしまったようだ

 ハハハ。さすがに草。

1. 条件によって挙動が異なる。

 まず、全体の内容として、table 要素のセルを position: sticky で固定させる、という話。ちなみに、Chrome は今から説明するすべてのパターンで正しい(期待する)動作になります。

2. table > tr > th/td 構造

 table 直下のフラット構造になります。コードにすると次の通り。

<table>
  <tr>
    <th>Header 1</th>
    <th>Header 2</th>
    <th class="cell-sticky cell-sticky-top">Header 3</th>
  </tr>
  <tr>
    <td>Cell 1</td>
    <td>Cell 2</td>
    <td>Cell 3</td>
  </tr>
  <tr>
    <td>Footer 1</td>
    <td>Footer 2</td>
    <td class="cell-sticky cell-sticky-bottom">
      <ul class="cell-flex">
        <li>1</li>
        <li>2</li>
        <li>3</li>
      </ul>
    </td>
  </tr>
</table>

 THE シンプルな実装ですが、これは Chrome, Safari ともに期待する動作になる。

3. table > thead/tbody > tr > th/td 構造

 2 の Header を thead 内に移動、それ以外を tbody 内に移動する。

<table>
  <thead>
    <tr>
      <th>Header 1</th>
      <th>Header 2</th>
      <th class="cell-sticky cell-sticky-top">Header 3</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Cell 1</td>
      <td>Cell 2</td>
      <td>Cell 3</td>
    </tr>
    <tr>
      <td>Footer 1</td>
      <td>Footer 2</td>
      <td class="cell-sticky cell-sticky-bottom">
        <ul class="cell-flex">
          <li>1</li>
          <li>2</li>
          <li>3</li>
        </ul>
      </td>
    </tr>
  </tbody>
</table>

 言わずもがな Chrome はちゃんと張り付く。

 Safari はページ上端からのスクロールの場合、正しく動作する。Mobile Safari の場合、ページ下端からのスクロールの場合、env(safe-area-inset-bottom)考慮しない位置(=0px) に張り付くようになり、PC Safari の場合、全く張り付かない。

4. table > thead/tbody/tfoot > tr > th/td 構造

 3 の Footer を tfoot 内に移動する。

<table>
  <thead>
    <tr>
      <th>Header 1</th>
      <th>Header 2</th>
      <th class="cell-sticky cell-sticky-top">Header 3</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Cell 1</td>
      <td>Cell 2</td>
      <td>Cell 3</td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <td>Footer 1</td>
      <td>Footer 2</td>
      <td class="cell-sticky cell-sticky-bottom">
        <ul class="cell-flex">
          <li>1</li>
          <li>2</li>
          <li>3</li>
        </ul>
      </td>
    </tr>
  </tfoot>
</table>

 しつこいようですが Chrome はちゃんと張り付く。

 Safari は全く張り付かない。

まとめ

 自分の場合、4 番目の構造でこのバグを踏んでテストコード書いてみたけど、まさか tfoot が悪さしているなんてね… 一番 sticky で使いたい table 構造でまさかこんな不具合(しかも safe-area 無視する挙動のパターンもある!)とか…

 最初、flex が cell 内にあるから正しく張り付かないのかなぁ? って予想してたんですが、flex は全く関係なく… 単純な構造ですらテストがきちんと行われていないようでした……

 一応確認に使ったテストコードが以下にあるので、Debug View で iPhone で開いてもらえばいいかと。

https://codepen.io/mntone/pen/LYLPjgZ

 まあ報告めんどくさいし、しないと思います…w

PS Mobile SafariiOS 14.7.1 w/iPhone 12 mini、SafariSafari 14.1.2 (16611.3.10.1.6) w/macOS Big Sur 11.5.2