実現したいこと
画面をスクロールするとカードが1枚ずつ現れ、カードが重なっていくようなアニメーションを作りたいです。
最終的な完成系は画像をご覧ください。参考サイトのURLも記載いたします。
URL:https://scroll-driven-animations.style/demos/stacking-cards/css/
発生している問題・分からないこと
参考先サイトのコードを使用してもいいと考えたのですが、ブラウザによっては動かない可能性が出てきたので一旦、自作で作成してみました。CSSのposition:stickyで再現してみました。
カード1とカード2に関して、画面内に入ってきたらopacityとscaleの値がスクロール量に応じて変わるようにしています。
カード4はカード3をstickyさせるために用意したダミーのカードです。
それぞれのカードのstickyする位置をずらしてカードが重なっているように見せています。
ですが、参考先のサイトのようにすべてのカードが出たらカードがstickyした状態で画面が下にスクロールしてほしいのにカード3だけがstickyせずにスクロールするような形になってしまっているのでそこを改善したいです。
該当のソースコード
HTML,CSS,JavaScript
1/*============================================================== 2HTML 3==============================================================*/ 4<ul id="cards" class="p-home-about__list"> 5 <li class="p-home-about__card card1"></li> 6 <li class="p-home-about__card card2"> </li> 7 <li class="p-home-about__card card3"></li> 8 <li class="p-home-about__card card4"></li> 9</ul> 10 11 12/*============================================================== 13スタッキングカードアニメーションのCSSカスタマイズ 14==============================================================*/ 15.p-home-about__card { 16 cursor: pointer; 17 background: #fff; 18 border-radius: 20px; 19 box-shadow: 0px 0px 40px 0px rgba(11, 39, 94, 0.1); 20 width: 305px; 21 height: 600px; 22 padding: rem(24); 23 margin: 0 auto; 24 transform: scale(1); 25 opacity: 1; 26 transition: 27 transform 0.1s linear, 28 opacity 0.1s linear; /* 滑らかに変化 */ 29 will-change: transform, opacity; /* ハードウェアアクセラレーション */ 30 position: sticky; 31 top: calc(50% - 300px); 32 33 @include responsive(lg2) { 34 width: 845px; 35 height: 712px; 36 padding: rem(40) rem(44); 37 margin: 0 auto; 38 top: calc(50% - 356px); /* 712pxのカード高さの半分を引く */ 39 } 40 41 &.card1 { 42 top: calc(50% - 300px); 43 44 @include responsive(lg2) { 45 top: calc(50% - 356px); /* 712pxのカード高さの半分を引く */ 46 } 47 } 48 &.card2 { 49 top: calc(50% - 244px); 50 51 @include responsive(lg2) { 52 top: calc(50% - 287px); /* 712pxのカード高さの半分を引く */ 53 } 54 } 55 &.card3 { 56 top: calc(50% - 188px); 57 58 @include responsive(lg2) { 59 top: calc(50% - 218px); /* 712pxのカード高さの半分を引く */ 60 } 61 } 62 63 &.card4 { 64 box-shadow: none; 65 opacity: 0 !important; 66 } 67} 68 69 70/*============================================================== 71JavaScript 72==============================================================*/ 73$(document).ready(function () { 74 const $cards = $(".p-home-about__card"); // カード要素 75 const cardOffset = 0.8; // カードが画面内80%に入るタイミングで発火 76 77 // スクロール時の処理 78 $(window).on("scroll", function () { 79 const windowHeight = $(window).height(); // 画面の高さ 80 const scrollTop = $(window).scrollTop(); // 現在のスクロール位置 81 82 $cards.each(function (index) { 83 const $card = $(this); 84 const cardTop = $card.offset().top; // カードの上端位置 85 86 // card3は何も変更しない 87 if ($card.hasClass("card3")) { 88 $card.css({ 89 transform: "scale(1)", 90 opacity: 1, 91 }); 92 return; // 処理をスキップ 93 } 94 95 // カードの中央がビューポート内に入ったかチェック 96 const startPoint = cardTop - windowHeight * cardOffset; 97 const endPoint = 98 cardTop + $card.outerHeight() - windowHeight * cardOffset; 99 100 if (scrollTop >= startPoint && scrollTop <= endPoint) { 101 // 進捗率の計算(0 ~ 1 の間でスムーズに変化) 102 const progress = (scrollTop - startPoint) / (endPoint - startPoint); 103 const scaleValue = 1 - progress * (index === 0 ? 0.2 : 0.1); // scaleの変化 104 const opacityValue = 1 - progress * (index === 0 ? 0.3 : 0.2); // opacityの変化 105 106 // スタイルを適用(スムーズに変化) 107 $card.css({ 108 transform: `scale(${scaleValue})`, 109 opacity: opacityValue, 110 }); 111 } else if (scrollTop < startPoint) { 112 // 初期値にリセット(画面外の時) 113 $card.css({ 114 transform: "scale(1)", 115 opacity: 1, 116 }); 117 } 118 }); 119 }); 120}); 121
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
ネットでカードスタッキングのアニメーションの方法を調べてみましたが、どれもうまくいかず自作した結果がこれです。
補足
特になし
