貼り付く見出し
貼り付く見出し
スクロールしてこの見出しが画面上部に貼り付いたときだけ、見出しの下に境界線を出したい。
技として、境界線用の要素をいっこ用意して、それを見出しの裏に忍ばせておく方法がある。見出しが画面上部に貼り付いたときに、下に境界線が出てくる。
貼り付く見出し
貼り付く見出し
どうなってるかというと、背景色を透明にするとこう。
- 見出しの要素に
margin-top: -1px;
をつけることで、境界線の要素を覆い隠して見えなくしておく - sticky の top の値を、見出しの縦幅 + 1px 分にして、 1px 下に貼り付くようにする
- 境界線が躍り出る空間を得るために、外側の包む要素の縦幅は、見出しの縦幅 + 1px 分にしておく
むずいけど、これで、見出しが貼り付いたときに、境界線がちょうど背景色のすぐ下に躍り出る。
<div class="sticky-with-border"> <h3 class="border" inert>貼り付く見出し</h3> <h3 class="title">貼り付く見出し</h3> </div> <style> .sticky-with-border { position: sticky; top: 10px; margin: 33px 0; height: 51px; } .entry .entry-inner .sticky-with-border h3.border { position: sticky; top: 61px; margin: 0; padding: 0 10px; width: fit-content; height: 1px; background-color: black; color: transparent; } .entry .entry-inner .sticky-with-border h3.title { position: sticky; top: 0; margin: -1px 0 0; padding: 0 10px; display: flex; flex-flow: column; justify-content: center; width: fit-content; height: 50px; background-color: #eee; } </style>
境界線の要素を h3 にしてるのは、横幅を合わせるため (なので文字も同じものを入れつつ文字色を透明にしている)。 width: 100%
とかにしたら、空の div とかでも良い。
ちなみに、他の技として animation-timeline: scroll()
とかはあって %
指定で border を出したりはできるけど、張り付いたらすぐに、というのは %
の数字を調整しないといけなくてむずい。 scroll() - CSS: カスケーディングスタイルシート | MDN
追記(2024/1/17): id:susisu から inert 属性をつけておくとよさそうと指摘をもらったのでつけてあります(感謝) HTMLElement: inert プロパティ - Web API | MDN。最初は落書きのつもりで雑に書いてたのであんまり気にしてなかったけど、そういえば属性つけるだけで重複回避できるのだった、と思い出せて助かった。
追記(2024/1/17): 擬似クラスとかないんだろうか……とか思っていたけど、 :stuck
という提案はあったっぽいけど設計規則とそぐわないので却下されてそうと id:mizdra に教えてもらった(感謝) [css-selectors] :stuck pseudo-class feature suggestion · Issue #1656 · w3c/csswg-drafts · GitHub 。 CSS で変えられるものを擬似クラスにしてしまうと無限ループになりうるのはたしかにで面白い。あと position: sticky
もうちょっとなんとかならないかという議論自体は続いていて、その中に今回の記事のような場合も議題としてあるとのことだった [css-position] Meta-issue: Unresolved `sticky` positioning use cases · Issue #11145 · w3c/csswg-drafts · GitHub。