app/template/default/Block/developmet_comom_slider_test.twig line 1

Open in your IDE?
  1. {% block main %}
  2. <style>
  3. .slider-wrapper {
  4.   position: relative;
  5.   width: 100%;
  6.   height: 200px;
  7.   overflow: hidden;
  8.   background: #dcdcdc;
  9. }
  10. /* 横スライド */
  11. .slider-track {
  12.   display: flex;
  13.   width: 500%;
  14.   height: 100%;
  15.   transition: transform 0.8s ease;
  16. }
  17. /* 各スライド */
  18. .slide {
  19.   width: 20%;
  20.   height: 100%;
  21.   position: relative;
  22.   overflow: hidden;
  23.   cursor: pointer;
  24. }
  25. /* 縦スライダー */
  26. .vertical-slider {
  27.   position: relative;
  28.   width: 100%;
  29.   height: 100%;
  30.   overflow: hidden;
  31. }
  32. .vertical-track {
  33.   position: absolute;
  34.   width: 100%;
  35.   height: 1000%;
  36.   top: 0;
  37.   left: 0;
  38.   animation: scrollY 6s linear infinite;
  39.   animation-play-state: paused;
  40. }
  41. .slide:hover .vertical-track {
  42.   animation-play-state: running;
  43. }
  44. /* 商品カード */
  45. .item {
  46.   width: 100%;
  47.   height: 10%;
  48.   position: relative;
  49. }
  50. .item a {
  51.   display: block;
  52.   width: 100%;
  53.   height: 100%;
  54.   text-decoration: none;
  55.   color: #fff;
  56.   position: relative;
  57. }
  58. .item img {
  59.   width: 100%;
  60.   height: 100%;
  61.   object-fit: cover;
  62.   display: block;
  63. }
  64. /* 型式名 */
  65. .item p {
  66.   position: absolute;
  67.   bottom: 5px;
  68.   left: 50%;
  69.   transform: translateX(-50%);
  70.   margin: 0;
  71.   padding: 2px 10px;
  72.   background: #222;
  73.   color: #fff;
  74.   font-size: 13px;
  75.   font-weight: bold;
  76.   border-radius: 10px;
  77. }
  78. /* ナビゲーションボタン */
  79. .nav-btn {
  80.   position: absolute;
  81.   top: 50%;
  82.   transform: translateY(-50%);
  83.   background: rgba(34, 34, 34, 0.8);
  84.   color: #fff;
  85.   border: none;
  86.   font-size: 20px;
  87.   width: 35px;
  88.   height: 35px;
  89.   cursor: pointer;
  90.   z-index: 10;
  91.   border-radius: 50%;
  92.   transition: background 0.3s;
  93. }
  94. .nav-btn:hover {
  95.   background: #000;
  96. }
  97. .prev { left: 10px; }
  98. .next { right: 10px; }
  99. /* ドットナビゲーション */
  100. /* ドットナビゲーション(右下に移動) */
  101. .dots {
  102.   position: absolute;
  103.   bottom: 8px;
  104.   right: 12px; /* ← ここを追加! */
  105.   display: flex;
  106.   gap: 6px;
  107.   transform: none; /* ← 中央寄せを解除 */
  108. }
  109. .dot {
  110.   width: 10px;
  111.   height: 10px;
  112.   border-radius: 50%;
  113.   background: #777;
  114.   cursor: pointer;
  115.   transition: background 0.3s;
  116. }
  117. .dot.active {
  118.   background: #222;
  119. }
  120. /* 縦ループ */
  121. @keyframes scrollY {
  122.   0% { transform: translateY(0); }
  123.   100% { transform: translateY(-50%); }
  124. }
  125. </style>
  126. <div class="slider-wrapper" id="sliderWrapper">
  127.   <div class="slider-track" id="sliderTrack">
  128.     <!-- === スライド1 === -->
  129.     <div class="slide">
  130.       <div class="vertical-slider">
  131.         <div class="vertical-track">
  132.           <div class="item"><a href="#"><img src="https://placehold.jp/300x200.png?text=Cat1-1"><p>HMC-25</p></a></div>
  133.           <div class="item"><a href="#"><img src="https://placehold.jp/300x200.png?text=Cat1-2"><p>HMC-50</p></a></div>
  134.           <div class="item"><a href="#"><img src="https://placehold.jp/300x200.png?text=Cat1-3"><p>HMC-75</p></a></div>
  135.           <div class="item"><a href="#"><img src="https://placehold.jp/300x200.png?text=Cat1-4"><p>HMC-100</p></a></div>
  136.           <div class="item"><a href="#"><img src="https://placehold.jp/300x200.png?text=Cat1-5"><p>HMC-150</p></a></div>
  137.           <div class="item"><a href="#"><img src="https://placehold.jp/300x200.png?text=Cat1-1"><p>HMC-25</p></a></div>
  138.         </div>
  139.       </div>
  140.     </div>
  141.     <!-- === スライド2〜5 === -->
  142.     <div class="slide"><div class="vertical-slider"><div class="vertical-track"><div class="item"><a href="#"><img src="https://placehold.jp/300x200.png?text=Cat2-1"><p>HTC-10</p></a></div></div></div></div>
  143.     <div class="slide"><div class="vertical-slider"><div class="vertical-track"><div class="item"><a href="#"><img src="https://placehold.jp/300x200.png?text=Cat3-1"><p>HMC-200</p></a></div></div></div></div>
  144.     <div class="slide"><div class="vertical-slider"><div class="vertical-track"><div class="item"><a href="#"><img src="https://placehold.jp/300x200.png?text=Cat4-1"><p>HMC-300</p></a></div></div></div></div>
  145.     <div class="slide"><div class="vertical-slider"><div class="vertical-track"><div class="item"><a href="#"><img src="https://placehold.jp/300x200.png?text=Cat5-1"><p>HMC-400</p></a></div></div></div></div>
  146.   </div>
  147.   <button class="nav-btn prev" id="prevBtn">&#10094;</button>
  148.   <button class="nav-btn next" id="nextBtn">&#10095;</button>
  149.   <div class="dots" id="dots"></div>
  150. </div>
  151. <script>
  152. const track = document.getElementById('sliderTrack');
  153. const slides = document.querySelectorAll('.slide');
  154. const dotsContainer = document.getElementById('dots');
  155. const wrapper = document.getElementById('sliderWrapper');
  156. let current = 0;
  157. let autoSlide;
  158. let resumeTimeout;
  159. // ドット生成
  160. slides.forEach((_, i) => {
  161.   const dot = document.createElement('div');
  162.   dot.classList.add('dot');
  163.   if (i === 0) dot.classList.add('active');
  164.   dot.addEventListener('click', () => {
  165.     moveTo(i);
  166.     pauseAndResume();
  167.   });
  168.   dotsContainer.appendChild(dot);
  169. });
  170. const dots = document.querySelectorAll('.dot');
  171. // スライド移動
  172. function moveTo(index) {
  173.   current = index;
  174.   track.style.transform = `translateX(-${index * 20}%)`;
  175.   dots.forEach(d => d.classList.remove('active'));
  176.   dots[index].classList.add('active');
  177. }
  178. // ボタン
  179. document.getElementById('nextBtn').onclick = () => {
  180.   current = (current + 1) % slides.length;
  181.   moveTo(current);
  182.   pauseAndResume();
  183. };
  184. document.getElementById('prevBtn').onclick = () => {
  185.   current = (current - 1 + slides.length) % slides.length;
  186.   moveTo(current);
  187.   pauseAndResume();
  188. };
  189. // 自動スライド
  190. function startAutoSlide() {
  191.   stopAutoSlide();
  192.   autoSlide = setInterval(() => {
  193.     current = (current + 1) % slides.length;
  194.     moveTo(current);
  195.   }, 6000);
  196. }
  197. function stopAutoSlide() {
  198.   clearInterval(autoSlide);
  199. }
  200. function pauseAndResume() {
  201.   stopAutoSlide();
  202.   clearTimeout(resumeTimeout);
  203.   resumeTimeout = setTimeout(startAutoSlide, 3000);
  204. }
  205. // ホバー停止
  206. wrapper.addEventListener('mouseenter', stopAutoSlide);
  207. wrapper.addEventListener('mouseleave', startAutoSlide);
  208. // === スワイプ対応 ===
  209. let startX = 0;
  210. let isSwiping = false;
  211. wrapper.addEventListener('touchstart', (e) => {
  212.   startX = e.touches[0].clientX;
  213.   isSwiping = true;
  214.   stopAutoSlide();
  215. });
  216. wrapper.addEventListener('touchmove', (e) => {
  217.   if (!isSwiping) return;
  218.   const diffX = e.touches[0].clientX - startX;
  219.   if (Math.abs(diffX) > 50) {
  220.     if (diffX > 0) {
  221.       current = (current - 1 + slides.length) % slides.length;
  222.     } else {
  223.       current = (current + 1) % slides.length;
  224.     }
  225.     moveTo(current);
  226.     isSwiping = false;
  227.     pauseAndResume();
  228.   }
  229. });
  230. wrapper.addEventListener('touchend', () => {
  231.   isSwiping = false;
  232. });
  233. // 初期起動
  234. startAutoSlide();
  235. </script>
  236. {% endblock %}