相同高度动态 "carousel slides" 不展开父项

Same height dynamic "carousel slides" without expanding parent

我正在尝试在每个“幻灯片”上创建一个带有任意文本的轮播,其中所有幻灯片都保持相同(即最大)的高度。我自己写的,所以我可以逃避任何事情(例如,在 JavaScript 中完成),但我希望它尽可能简单,所以倾向于更多 CSS,少 JS.

我把它全部用作轮播,但无法让每张幻灯片都具有相同的高度。我目前在父容器和 JS 上使用 flexbox 来更改样式,该样式会更改不透明度和宽度,以便一次只显示一张幻灯片,同时保持高度。

HTML:

<div class="testimonial-container"> // the parent — flex ... I'm growing when I shouldn't be
  <div class="testimonial active"> // the child, also flex, because I don't know what's inside; direction: column
    <div class="image-wrap">&nbsp;</div>
    <div class="testimonial-content">“Hi! I'm Jim!” // but I could be 10 lines of text
    </div>
    <div class="reviewer">Jim Jones</div>
    <div class="jobrole">Bad A-- Hombre!</div>
  </div>
  ... // more testimonials
</div>
<div class="testimonial-dots">
  <span class="testimonial-dot active"></span> // I'm a button
  ... // more dots
</div>

CSS:

.testimonial-container {
        max-width: 100%;
        position: relative;
        margin: auto;
        display: flex;     
}

/* hide the testimonial by default */
.testimonial-container div.testimonial {
        opacity: 0;
        width: 0px;
}

/* visible when JS adds "active" class */    
.testimonial-container div.testimonial.active {
        opacity: 1;
        width: 100%;
}  

.testimonial {
        display: flex;
        flex-direction: column;
}

.image-wrap,
.testimonial-content,
.reviewer,
.jobrole {
        padding: 8px 12 px;
        width: 100%;
        text-align: center;
}

脚本:

  let testimonialIndex = 1;
  let testimonials, dots;
  
  window.addEventListener( 'DOMContentLoaded', () => {
    testimonials = document.getElementsByClassName("testimonial");
    dots = document.getElementsByClassName("testimonial-dot");
  
    for ( let i = 0; i < dots.length; i++ ) {
      dots[i].onclick = () => currentTestimonial(i + 1);
    }
  
    showTestimonial(testimonialIndex);
  } );
  
  // dot image controls
  function currentTestimonial(n) {
    showTestimonial(testimonialIndex = n);
  }
  
  function showTestimonial(n) {
    if (n > testimonials.length) {testimonialIndex = 1};
    if (n < 1) {testimonialIndex = testimonials.length};
  
    for ( let i = 0; i < testimonials.length; i++) {
      testimonials[i].classList.remove('active');
    }
    for ( let i = 0; i < dots.length; i++ ) {
      dots[i].className = dots[i].className.replace(" active", "");
    }
  
    const testimonial = testimonials[testimonialIndex-1];
  
    testimonial.classList.add('active');
  
    dots[testimonialIndex-1].className += " active";
  }

加载时没问题(第一张幻灯片的高度正确)。问题是,当我对 select 另一张幻灯片执行 JS 时,父级展开为所有幻灯片堆叠在一起的高度(实际上,远不止于此)。

与所有这些事情一样,这开始于“我将只使用 WordPress 插件”,结束于“嘎!这些不起作用,而且它们臃肿且混乱!我会写我自己的!"

因此,我正在尝试编写一个非常简单且轻量级的 推荐轮播。我从 W3 学校“How TO - Slideshow”开始。这太棒了,几乎让我一路走到了那里,但问题是,它们是推荐书,所以文本是任意长度的,我不希望在幻灯片之间翻转时旋转木马改变高度。

谷歌搜索让我找到 ,除了 jQuery 之外,它看起来很完美。 W3 学校示例基本上切换 display: none。这个 SE 答案让我了解了 flex 模型并使用 width: 0px; opacity: 0; 来隐藏东西。但现在我卡住了。在他的回答中,他在“旋转木马”下方有三个按钮,看起来效果很好。但在我的实现中,当你点击一个按钮时,父级 div 展开并将按钮推离屏幕。

这是一个fiddle;要查看它的实际效果,只需单击其中一个按钮并观察按钮消失(它们现在在屏幕下方 2000 像素处……我不知道那是什么;它甚至不是堆叠的两个推荐的高度彼此叠加,也许是无穷大的某种版本)。

如何阻止该父级扩展?

let testimonialIndex = 1;
  let testimonials, dots;
  
  window.addEventListener( 'DOMContentLoaded', () => {
    testimonials = document.getElementsByClassName("testimonial");
    dots = document.getElementsByClassName("testimonial-dot");
  
    for ( let i = 0; i < dots.length; i++ ) {
      dots[i].onclick = () => currentTestimonial(i + 1);
    }
  
    showTestimonial(testimonialIndex);
  } );
  
  // dot image controls
  function currentTestimonial(n) {
    showTestimonial(testimonialIndex = n);
  }
  
  function showTestimonial(n) {
    if (n > testimonials.length) {testimonialIndex = 1};
    if (n < 1) {testimonialIndex = testimonials.length};
  
    for ( let i = 0; i < testimonials.length; i++) {
      testimonials[i].classList.remove('active');
    }
    for ( let i = 0; i < dots.length; i++ ) {
      dots[i].className = dots[i].className.replace(" active", "");
    }
  
    const testimonial = testimonials[testimonialIndex-1];
  
    testimonial.classList.add('active');
  
    dots[testimonialIndex-1].className += " active";
  }
.testimonial-container {
        max-width: 100%;
        position: relative;
        margin: auto;
        display: flex;     
}

/* hide the testimonial by default */
.testimonial-container div.testimonial {
        opacity: 0;
        width: 0px;
}

.testimonial-container div.testimonial.active {
        opacity: 1;
        width: 100%;
}  

.testimonial {
        display: flex;
        flex-direction: column;
}

.image-wrap,
.testimonial-content,
.reviewer,
.jobrole {
        padding: 8px 12 px;
        width: 100%;
        text-align: center;
}

/** below just for aesthetics */
.image-wrap {
  display: block;
  width: 150px;
  height: 150px;
  margin: 0 auto;
  }
  
  .testimonial-dots {
        text-align: center;
}

.testimonial-dot {
        cursor: pointer;
        height: 15px;
        width: 15px;
        background-color: #bbb;
        border-radius: 50%;
        display: inline-block;
        margin: 0 2.5px;
}

.testimonial-dot.active,
.testimonial-dot:hover {
  background-color: #717171;
}
<div class="testimonial-container">
  <div class="testimonial">
    <div class="image-wrap" style="background-color: #0f0;">&nbsp;</div>
    <div class="testimonial-content">“Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla consectetur a velit ac luctus. Sed mattis finibus massa nec pretium. In mattis finibus pharetra. Fusce aliquam id neque accumsan accumsan. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Cras lacinia quam est, sit amet dignissim augue lacinia eget. Donec sed tempor elit, eu tempus augue. Duis ac elit justo. Ut ex metus, semper a ultricies congue, tincidunt tristique leo. Ut porta sodales fermentum. Vivamus et ante ullamcorper, porta sem at, luctus mauris. Ut fermentum velit quis orci eleifend, sed auctor elit tincidunt. Maecenas in magna et augue tristique cursus. Duis consectetur vel neque a fermentum.”
    </div>
    <div class="reviewer">Jim Jones</div>
    <div class="jobrole">Bad A-- Hombre!</div>
  </div>
  <div class="testimonial active">
    <div class="image-wrap" style="background-color: #00f;">&nbsp;</div>
    <div class="testimonial-content">“I'm verbose!”</div>
    <div class="reviewer">Bob Smith</div>
  </div>
</div>
<!-- Testimonial container -->
<!-- dots/circles -->
<div class="testimonial-dots">
  <span class="testimonial-dot"></span>
  <span class="testimonial-dot active"></span>
</div>

通常当你做一个轮播类型的事情时,你有两个容器。一个容器是视口的宽度,内部容器是内容本身的宽度。然后根据当前选中的项目滑动内容容器left/right。

如果您/想要/按照自己的方式进行,您可以在您的容器上使用类似 height: max-content 的东西,这将限制它不大于内部最大的项目。这是我使用两个容器的解决方案:

// Greatly simplifed your javascript.

const container = document.querySelector('.testimonial-container');
const dotsContainer = document.querySelector('.testimonial-dots');
const dots = [...dotsContainer.children];

// We add an event listener on the parent container to the dots.
dotsContainer.addEventListener('click', ({
  target
}) => {
  // If the item clicked was not a dot, don't do anything
  if (!target.matches('.testimonial-dot')) return;
  const myIndex = dots.indexOf(target);
  // Move the container -100% * the dot index
  const offset = -100 * myIndex;
  container.style.transform = `translateX(${-100 * myIndex}%)`;
  dots.map(d => d.classList.remove('active'));
  target.classList.add('active');
});
.carousel {
  /* hide off-screen items */
  overflow: hidden;
}

.testimonial-container {
  display: flex;
}

.testimonial-container div.testimonial {
  /* make all items bre 100% in width */
  min-width: 100%;
}


/* the rest of the css is untouched */

.image-wrap,
.testimonial-content,
.reviewer,
.jobrole {
  padding: 8px 12 px;
  width: 100%;
  text-align: center;
}


/** below just for aesthetics */

.image-wrap {
  display: block;
  width: 150px;
  height: 150px;
  margin: 0 auto;
}

.testimonial-dots {
  text-align: center;
}

.testimonial-dot {
  cursor: pointer;
  height: 15px;
  width: 15px;
  background-color: #bbb;
  border-radius: 50%;
  display: inline-block;
  margin: 0 2.5px;
}

.testimonial-dot.active,
.testimonial-dot:hover {
  background-color: #717171;
}
<!-- This is the container that contains all the items and only shows the active one. It's like a viewport -->
<div class="carousel">
  <!-- This contains all the items, and the width is equal to each item's width added together. This container gets a translateX applied to it when the active item changes -->
  <div class="testimonial-container">
    <div class="testimonial">
      <div class="image-wrap" style="background-color: #0f0;">&nbsp;</div>
      <div class="testimonial-content">“Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla consectetur a velit ac luctus. Sed mattis finibus massa nec pretium. In mattis finibus pharetra. Fusce aliquam id neque accumsan accumsan. Class aptent taciti sociosqu ad litora torquent
        per conubia nostra, per inceptos himenaeos. Cras lacinia quam est, sit amet dignissim augue lacinia eget. Donec sed tempor elit, eu tempus augue. Duis ac elit justo. Ut ex metus, semper a ultricies congue, tincidunt tristique leo. Ut porta sodales
        fermentum. Vivamus et ante ullamcorper, porta sem at, luctus mauris. Ut fermentum velit quis orci eleifend, sed auctor elit tincidunt. Maecenas in magna et augue tristique cursus. Duis consectetur vel neque a fermentum.”
      </div>
      <div class="reviewer">Jim Jones</div>
      <div class="jobrole">Bad A-- Hombre!</div>
    </div>
    <div class="testimonial active">
      <div class="image-wrap" style="background-color: #00f;">&nbsp;</div>
      <div class="testimonial-content">“I'm verbose!”</div>
      <div class="reviewer">Bob Smith</div>
    </div>
  </div>
  <!-- Testimonial container -->
  <!-- dots/circles -->
  <div class="testimonial-dots">
    <span class="testimonial-dot active"></span>
    <span class="testimonial-dot"></span>
  </div>
</div>

您的问题是您正在更改幻灯片的宽度。然后使所有文本挤压并换行 - 这就是为什么它看起来比彼此堆叠的 2 张幻灯片高得多。当项目处于非活动状态时尝试使用 transform: translateX(-100vw); 以离开屏幕左侧;

否则,我不能推荐 Swiper JS,它是一个用于创建轮播的 vanilla JS 库,非常易于使用,有一个 CDN link,并且它与移动设备兼容。