CSS - 如何在占据12列行的滑块之外放置 swiper 滑块箭头

43
我正在使用 Swiper轮播插件,想要在轮播之外放置导航箭头。基本上,我希望的是与 Airbnb 网站上看起来相同的效果,其中包含图片的轮播占据了整个12列行,但箭头位于其外部。 我正在使用 Bootstrap Twitter CSS 框架,尝试了各种方法,但都没有效果,也不知道如何实现这一点?

以下是CSS:

.swiper-container {
  margin-top: 50px;
  position: relative;
}

.arrow-left {
  position: absolute;
  top: 50%;
  left: 0;
}

.arrow-right {
  position: absolute;
  top: 50%;
  right: 0;
}

HTML长这样:

       <div class="row swiper-container">
          <div class="arrow-left">
            <i class="ion-chevron-left"></i>
          </div>
          <div class="col-md-12 swiper-wrapper">
            @foreach($videos as $video)
              <div class="swiper-slide video-card">
                <header class="card__thumb">
                  <a href="/player/{{ $player->id }}/video/{{ $video->id }}"><img src="{{ $video->getThumbnail() }}"/></a>
                </header>

                <div class="card__body">
                  <div class="card__category">

                  </div>
                  <small>
                    {{ $video->created_at->diffForHumans() }}
                  </small>
                  <span class="video-title">
                    <p>
                      @if($video->title != '')
                        {{ $video->title }}  <i class="ion-arrow-right-c"></i>
                      @else
                        Untitled
                      @endif
                    </p>
                  </span>
                </div>
              </div>
            @endforeach
          </div>
          <div class="arrow-right">
            <i class="ion-chevron-right"></i>
          </div>
        </div>

这是脚本:

var carousel = function carousel() {
  var mySwiper = new Swiper ('.swiper-container', {
    direction: 'horizontal',
    nextButton: '.arrow-left',
    prevButton: '.arrow-right',
    slidesPerView: 4,
    simulateTouch: false,
    spaceBetween: 15,
    breakpoints: {
        1181: {
            slidesPerView: 4
        },
        1180: {
            slidesPerView: 3
        },
        1020: {
            slidesPerView: 2
        },
        700: {
            slidesPerView: 1
        }
    }
  });
};

$(document).ready(function () {
  carousel();
});

是的,我做了那个,但它不起作用,因为箭头的位置不像它们应该的那样。 - Leff
箭头现在的位置在哪里? - Keith
左边的位置正确,但是我看不见右边的。 - Leff
如果你看不到它,那是因为宽度太长了,你需要缩小容器,这样你才能看到箭头。如果容器是100%,那么超出容器的部分将无法看到。 - Keith
所以将页面主体设为 100%,容器设为大约 85% 并加上 margin: auto,那么您应该能够将箭头放置在容器之外但在完整的页面宽度之内。您可以使用负像素将其推出到您想要的位置。 - Keith
显示剩余3条评论
15个回答

67

我刚刚在我的项目中完成了这个操作。您只需要更改导航HTML按钮的位置并将它们放在swiper-container之外即可。为了获得更好的库行为和方法,给它们添加一个新类,并更改JavaScript调用中的元素。

示例:

<div class="swiper-container">
 <div class="swiper-slides"></div>
</div>
<div class="swiper-button-prev-unique"></div>
<div class="swiper-button-next-unique"></div>

let carousel = new Swiper('.swiper-container', {
  navigation: {
    nextEl: '.swiper-button-next-unique',
    prevEl: '.swiper-button-prev-unique'
  }
});

那个完美地运作了,而且你可以通过 CSS 轻松将箭头放在包装器外面。


只要您的页面上只有一个旋转木马,这个功能就可以正常工作。 - ecairol
2
@ecairol 不是不行。您可以设置更多的滑块,并为每个滑块提供独特的类,以便为每个滑块设置不同的箭头。测试起来并不难。 - Ezequiel Alba
这在至少Swiper 10.2.0中似乎不再起作用了。 - undefined

14

给所有的React爱好者们:

import { Swiper as SwiperClass } from 'swiper/types';
import { Swiper, SwiperSlide } from 'swiper/react';

 export const MySwiper = () => {
   const [swiperRef, setSwiperRef] = useState<SwiperClass>();
   
   const theSlides = useMemo(()=> ['slide one', 'slide two'], [])

   const handlePrevious = useCallback(() => {
     swiperRef?.slidePrev();
   }, [swiperRef]);

   const handleNext = useCallback(() => {
     swiperRef?.slideNext();
   }, [swiperRef]);

   return (
     <div>
       <div>
         <button onClick={handlePrevious }>
             previous
         </button>
       </div>
       <Swiper
         onSwiper={setSwiperRef}
       >
         {theSlides.map((slide) => (<SwiperSlide key={slide}>{slide}</SwiperSlide>)
       </Swiper>
       <div>
         <button onClick={handleNext}>
           Next
         </button>
       </div>
     </div>
   );
 };

什么是<SwiperClass> - Sabrina Tolmer
1
抱歉,我忘记添加导入了。SwiperClass是我用于TypeScript类型的别名,它提供了一个Swiper实例。 - PaulHendrickson
这对我有意义,但我无法使其工作。 我想在React上使用自定义滑块控制按钮,放置在Swiper旋转木马的顶部,但只有当我将自己的SliderControl组件放入Swiper组件中时才起作用。 将滑块控件放入Swiper中的另一个问题是,我无法将按钮样式设置为位于旋转木马的顶部,当我尝试绝对定位时,按钮从视图中消失。 有什么想法如何使其工作?@PaulHendrickson?谢谢! - OmarAguinaga
因此,swiperRef对象是Swiper Slide的控件的一个实例,因此该对象可以在任何地方引用,并且您应该能够像handleNext和handlePrevious函数中所做的那样执行swiperRef?.slideNext()或swiperRef?.slidePrev()。 - PaulHendrickson
对我来说完美地运作了。谢谢你。我已经为此努力了几个小时了... - Maria Ramono

5
如果您使用多个轮播图,则需要为swiper-container和分页箭头添加不同的类名。然后创建新的Swiper并将每个箭头绑定到本地轮播图。

let arr_next = $('.template-next') //your arrows class name
let arr_prev = $('.template-prev') //your arrows class name
    
$('.swiper-container--template').each(function (index, element) {
            
            $(this).addClass('swiper' + index);
            arr_next[index].classList.add('template-next' + index);
            arr_prev[index].classList.add('template-prev' + index);

            new Swiper('.swiper' + index, {
                slidesPerView: 2,
                navigation: {
                    nextEl: '.template-next'+index,
                    prevEl: '.template-prev'+index
                },
                slidesPerView: 2,
                //spaceBetween: 100,
                loop: true,
                breakpoints: {
                    961: { slidesPerView: 2 },
                    740: { slidesPerView: 1 },
                },
            });
        });
`


一个提示:如果你已经在创建自定义箭头作为HTML元素,那么你就不需要创建虚构的独特类。只需将引用传递进去(支持选择器或HTML元素对象)- 这甚至可以使用jQuery完成,例如,在示例中调用.get(0)来获取arr_next - jave.web
谢谢,这对我帮助很大!适用于最新的10.3.1版本。 - undefined

3

var swiper = new Swiper('.swiper-container', {
      nextButton: '.swiper-button-next',
        prevButton: '.swiper-button-prev',
        slidesPerView: 3,
        spaceBetween: 10,
        autoplay: 3500,
        autoplayDisableOnInteraction: false,
  loop: true,
        breakpoints: {
            1024: {
                slidesPerView: 3,
                spaceBetween: 40
            },
            768: {
                slidesPerView: 3,
                spaceBetween: 30
            },
            640: {
                slidesPerView: 2,
                spaceBetween: 20
            },
            320: {
                slidesPerView: 1,
                spaceBetween: 10
            }
        }
    });
.container{max-width: 600px;margin: 0 auto;}
.swiper_wrap{padding:0px 50px;height:100%;width: 100%;position: relative;display: block;text-align: left;}
.swiper-button-next{
margin-top: 0px;
position: absolute;
top: 50%;
right: -40px;
width: 45px;
height: 45px;
transform: translateY(-50%);
}
.swiper-button-prev{
  position: absolute;
  top: 50%;
  left: -40px;
  width: 45px;
  height: 45px;
  transform: translateY(-50%);
  margin-top: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/3.4.2/js/swiper.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/3.4.2/css/swiper.min.css" rel="stylesheet"/>
  <div class="container">

<div class="swiper_wrap">
<div class="slider-wrapper">
       <div class="swiper-button-prev"></div>
        <div class="swiper-container">
   <div class="swiper-wrapper">
    <div class="swiper-slide">
     <a href="#">
          <img src="http://redsqdesign.co.uk/wp-content/uploads/2017/02/red-square.png">
     </a>
    </div>
        <div class="swiper-slide">
     <a href="#">
          <img src="http://redsqdesign.co.uk/wp-content/uploads/2017/02/red-square.png">
     </a>
    </div>
        <div class="swiper-slide">
     <a href="#">
          <img src="http://redsqdesign.co.uk/wp-content/uploads/2017/02/red-square.png">
     </a>
    </div>
        <div class="swiper-slide">
     <a href="#">
          <img src="http://redsqdesign.co.uk/wp-content/uploads/2017/02/red-square.png">
     </a>
    </div><div class="swiper-slide">
     <a href="#">
          <img src="http://redsqdesign.co.uk/wp-content/uploads/2017/02/red-square.png">
     </a>
    </div>
   </div>
        <!-- Add Pagination -->
        <div class="swiper-pagination"></div>
        </div>
       <div class="swiper-button-next"></div>
</div>   
</div>
</div>
<script src="http://www.jakse.si/test/jakse/taxi/js/swiper.min.js"></script>

对我来说这个方法可行,和之前的答案一样,但也许看起来更好 :)


2
将以下内容放置在swiper块下方:

.section { 
  .swiper-button-prev {
    left: -20px;
  }
  .swiper-button-next {
    right: -20px;
  }
}
<div class="section">

  <div class="swiper">
    <ul class="swiper-wrapper">
      <li class="swiper-slide">
      </li> 
    </ul>
  </div>
  
  <div class="swiper-button-prev"></div>
  <div class="swiper-button-next"></div> 
    
</div>


2

如果有人感兴趣,我已经找到了一个简单的解决方法
position: fixed; 会覆盖父元素的 overflow:hidden;,但它会使其相对于根元素显示,将 transform 添加到包装器中将使其再次相对于父元素显示。

new Swiper(".my-swiper", {
  navigation: {
    nextEl: ".swiper-button-next",
    prevEl: ".swiper-button-prev",
  }
});
.custom-swiper-wrapper {
  transform: translate(0, 0);
  .swiper-custom-nav {
    position: fixed;
  }
}
<div class="container custom-swiper-wrapper">
  <div class="swiper my-swiper">
    <div class="swiper-wrapper">
      swiper items here
    </div>
    <div class="swiper-button-next swiper-custom-nav"></div>
    <div class="swiper-button-prev swiper-custom-nav"></div>
  </div>
</div>


很抱歉,这在Safari中无法运行。 - Mista K.

1
这是一个通用解决方案。要将箭头移出容器,您需要先从.swiper-container中删除箭头div。
创建另一个更大的容器,其中包含.swiper-container和您移动的箭头。将此更大的容器设置为position:relative,以便参考具有position:absolute的箭头。
确保.swiper-container的宽度更改为小于100%的值(例如90%或95%),以避免与箭头重叠。
如果您希望保持.swiper-container的宽度与整个页面宽度相同,则为更大的容器提供负边距。

1
在包装函数“carousel”中,我们使用Swiper的本地方法slideNext和slidePrev初始化Swiper实例,并明确添加事件监听器到共享父元素的子元素。
            1020: {
                slidesPerView: 2
            },
            700: {
                slidesPerView: 1
            }
        }
    });
    mySwiper.el.parentElement.querySelector(".arrow-left").addEventListener('click',
        () => mySwiper.slideNext());
    mySwiper.el.parentElement.querySelector(".arrow-right").addEventListener('click',
        () => mySwiper.slidePrev());
};

为了使这个功能完全正常工作,.swiper-container、.arrow-right和.arrow-left需要共享一个包装器。在Leff的情况下,“.swiper-container”应该可以很好地工作:
<div class="row swiper-container">
    <div class="arrow-left">

由于这种方法允许我们将选定元素隔离到共享的父容器中,因此可以安全地将其用作可能出现多次的代码块的一部分。


1
如果slidesPerView = 1,则这是有效的:
.swiper-container {
    padding-left: 50px;
    padding-right: 50px;
}

.swiper-slide {
    visibility: hidden;
}

.swiper-slide.swiper-slide-active {
    visibility: visible;
}

0

这是如何实现它的基本示例。你已经很接近了。我稍微修改了代码,使其在片段中可见。

$(document).ready(function () {

var carousel = function carousel() {
  var mySwiper = new Swiper ('.swiper-container', {
    direction: 'horizontal',
    nextButton: '.arrow-left',
    prevButton: '.arrow-right',
    slidesPerView: 4,
    simulateTouch: false,
    spaceBetween: 15,
    breakpoints: {
        1181: {
            slidesPerView: 4
        },
        1180: {
            slidesPerView: 3
        },
        1020: {
            slidesPerView: 2
        },
        700: {
            slidesPerView: 1
        }
    }
  });
};


  carousel();
});
.row.swiper-container {
  margin-top: 50px;
  position: relative;
  width: 70%;
  margin: 0 auto;
}
.arrow-left {
  position: absolute;
  background: gray;
  top: 50%;
  left: -40px;
  width: 20px;
  height: 20px;
  transform: translateY(-50%);
}
.arrow-right {
  position: absolute;
  background: gray;
  top: 50%;
  right: -40px;
  width: 20px;
  height: 20px;
  transform: translateY(-50%);
}

.swiper-wrapper {
  margin: 0 auto;
  height: 200px;
  background: #f00;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/3.x.x/css/swiper.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/3.4.1/js/swiper.jquery.min.js"></script>
<div class="row swiper-container">
  <div class="arrow-left">
    <i class="ion-chevron-left"></i>
  </div>
  <div class="col-md-12 swiper-wrapper">
    <div class="swiper-slide video-card">
      <header class="card__thumb">
        <a href="/player/{{ $player->id }}/video/{{ $video->id }}"><img src="{{ $video->getThumbnail() }}"/></a>
      </header>

      <div class="card__body">
        <div class="card__category">

        </div>
        <small>
                  </small>
        <span class="video-title">
                    <p>

                    </p>
                  </span>
      </div>
    </div>
  </div>
  <div class="arrow-right">
    <i class="ion-chevron-right"></i>
  </div>
</div>


您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Leff
将它设置为100。 - Serg Chernata
我不确定为什么,但我看不到箭头。 - Leff
它是否在某个地方可以进行调试? - Serg Chernata
1
可能是因为 .swiper-container 设置了 overflow: hidden - Patrick Manser

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接