在图像顶部带有文本的滑动响应图像

Posted

技术标签:

【中文标题】在图像顶部带有文本的滑动响应图像【英文标题】:Swiper Responsive images with Text on top of image 【发布时间】:2019-06-21 00:44:17 【问题描述】:

我正在使用 Swiper 创建一些图像滑块,并且我试图将滑块包含在 2 个 flexbox 容器中,以便我的图像具有响应性。

我想在图像顶部添加一些文本,与图像的左上角对齐,这就是一切出错的地方。

我相信我正在处理与Why don't flex items shrink past content size? 非常相似的 Flexbox“问题”,在这种情况下,父 DIV 会保持原始图像的宽度。问题是一旦我将图像包装在<div class="img-wrapper"> 中,帖子中的修复似乎就不起作用了。事实上,我已经花了很多时间进行研究,但似乎没有什么能让它按我想要的方式工作。

这个问题是CSS object-fit: contain; is keeping original image width in layout 的一个分支

注意:在新窗口中打开以下代码 sn-p 以查看问题。

var swiper = new Swiper('.swiper-container', 
  slidesPerView: 1,
  spaceBetween: 50,
  // init: false,
  pagination: 
    el: '.swiper-pagination',
    clickable: true,
  ,
);
img 
  object-fit: contain;
  min-width: 0;
  height: 100%;
  max-width: 100%;


.img-num 
  float: left;
  position: absolute;
  padding-left: 10px;
  text-shadow: 1px 1px 2px black, 0 0 1em blue, 0 0 0.2em blue;
  color: white;
  font: 1.5em Georgia, serif;



.img-wrapper 
  border-style: solid;
  border-width: thin;
  height: 100%;
  object-fit: contain;
  min-width: 0;


html,
body 
  margin: 0;
  height: 100%;


body 
  background: #eee;
  font-family: Helvetica Neue, Helvetica, Arial, sans-serif;
  font-size: 14px;
  color: #000;
  margin: 0;
  padding: 0;


.page 
  height: 100%;
  display: flex;


.main-container 
  flex: 1 1 0;
  display: flex;
  min-width: 0;
  flex-direction: column;


.half-containers 
  flex: 0 1 50%;
  overflow: auto;
  box-sizing: border-box;
  border: 0.5px solid red;
  display: flex;


.page-header 
  flex: 0 0 auto;
  background-color: #dcdcdc;


.page-footer 
  flex: 0 0 auto;
  background-color: #dcdcdc;


.swiper-container 
  width: 100%;
  height: 100%;


.swiper-slide 
  text-align: center;
  font-size: 18px;
  background: #fff;
  /* Center slide text vertically */
  display: -webkit-box;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;
  -webkit-box-pack: center;
  -ms-flex-pack: center;
  -webkit-justify-content: center;
  justify-content: center;
  -webkit-box-align: center;
  -ms-flex-align: center;
  -webkit-align-items: center;
  align-items: center;
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" rel="stylesheet" />

<link href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/4.4.6/css/swiper.css" rel="stylesheet" />
<div class="page">
  <div class="main-container">
    <div class="page-header">
      This is a header
    </div>
    <div class="half-containers">
      <!-- Swiper -->
      <div class="swiper-container">
        <div class="swiper-wrapper">
          <div class="swiper-slide">
            <div class="img-wrapper">
              <div class="img-num">1</div>
              <img src='https://i.imgur.com/mSPw98T.jpg' />
            </div>
          </div>
          <div class="swiper-slide">
            <div class="img-wrapper">
              <div class="img-num">2</div>
              <img src='https://i.imgur.com/mSPw98T.jpg' />
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="half-containers">
      <!-- Swiper -->
      <div class="swiper-container">
        <div class="swiper-wrapper">
          <div class="swiper-slide">
            <div class="img-wrapper">
              <div class="img-num">3</div>
              <img src='https://i.imgur.com/mSPw98T.jpg' />
            </div>
          </div>
          <div class="swiper-slide">
            <div class="img-wrapper">
              <div class="img-num">4</div>
              <img src='https://i.imgur.com/mSPw98T.jpg' />
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="page-footer">
      This is a footer
    </div>
  </div>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/4.4.6/js/swiper.js"></script>

【问题讨论】:

【参考方案1】:

首先,object-fit 的使用在应用于div 而不是应用于图像时是没有用的1。在这种情况下,即使在图像中使用它也是无用的,因为图像不会失真。 object-fit 仅在比率丢失时才适用,以便再次恢复。

所以你会遇到同样的问题没有:

var swiper = new Swiper('.swiper-container', 
  slidesPerView: 1,
  spaceBetween: 50,
  // init: false,
  pagination: 
    el: '.swiper-pagination',
    clickable: true,
  ,
);
img 
  height: 100%;
  max-width: 100%;


.img-num 
  float: left;
  position: absolute;
  padding-left: 10px;
  text-shadow: 1px 1px 2px black, 0 0 1em blue, 0 0 0.2em blue;
  color: white;
  font: 1.5em Georgia, serif;



.img-wrapper 
  border-style: solid;
  border-width: thin;
  height: 100%;


html,
body 
  margin: 0;
  height: 100%;


body 
  background: #eee;
  font-family: Helvetica Neue, Helvetica, Arial, sans-serif;
  font-size: 14px;
  color: #000;
  margin: 0;
  padding: 0;


.page 
  height: 100%;
  display: flex;


.main-container 
  flex: 1 1 0;
  display: flex;
  min-width: 0;
  flex-direction: column;


.half-containers 
  flex: 0 1 50%;
  overflow: auto;
  box-sizing: border-box;
  border: 0.5px solid red;
  display: flex;


.page-header 
  flex: 0 0 auto;
  background-color: #dcdcdc;


.page-footer 
  flex: 0 0 auto;
  background-color: #dcdcdc;


.swiper-container 
  width: 100%;
  height: 100%;


.swiper-slide 
  text-align: center;
  font-size: 18px;
  background: #fff;
  /* Center slide text vertically */
  display: flex;
  justify-content: center;
  align-items: center;
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" rel="stylesheet" />

<link href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/4.4.6/css/swiper.css" rel="stylesheet" />
<div class="page">
  <div class="main-container">
    <div class="page-header">
      This is a header
    </div>
    <div class="half-containers">
      <!-- Swiper -->
      <div class="swiper-container">
        <div class="swiper-wrapper">
          <div class="swiper-slide">
            <div class="img-wrapper">
              <div class="img-num">1</div>
              <img src='https://i.imgur.com/mSPw98T.jpg' />
            </div>
          </div>
          <div class="swiper-slide">
            <div class="img-wrapper">
              <div class="img-num">2</div>
              <img src='https://i.imgur.com/mSPw98T.jpg' />
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="half-containers">
      <!-- Swiper -->
      <div class="swiper-container">
        <div class="swiper-wrapper">
          <div class="swiper-slide">
            <div class="img-wrapper">
              <div class="img-num">3</div>
              <img src='https://i.imgur.com/mSPw98T.jpg' />
            </div>
          </div>
          <div class="swiper-slide">
            <div class="img-wrapper">
              <div class="img-num">4</div>
              <img src='https://i.imgur.com/mSPw98T.jpg' />
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="page-footer">
      This is a footer
    </div>
  </div>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/4.4.6/js/swiper.js"></script>

现在您面临的问题是图像包装器的大小首先考虑图像宽度,然后图像在该包装器内调整大小。它有点复杂,但如果你从图像中删除height:100%,你会得到这个:

var swiper = new Swiper('.swiper-container', 
  slidesPerView: 1,
  spaceBetween: 50,
  // init: false,
  pagination: 
    el: '.swiper-pagination',
    clickable: true,
  ,
);
img 
  /*height: 100%;*/
  max-width: 100%;


.img-num 
  float: left;
  position: absolute;
  padding-left: 10px;
  text-shadow: 1px 1px 2px black, 0 0 1em blue, 0 0 0.2em blue;
  color: white;
  font: 1.5em Georgia, serif;



.img-wrapper 
  border-style: solid;
  border-width: thin;
  height: 100%;


html,
body 
  margin: 0;
  height: 100%;


body 
  background: #eee;
  font-family: Helvetica Neue, Helvetica, Arial, sans-serif;
  font-size: 14px;
  color: #000;
  margin: 0;
  padding: 0;


.page 
  height: 100%;
  display: flex;


.main-container 
  flex: 1 1 0;
  display: flex;
  min-width: 0;
  flex-direction: column;


.half-containers 
  flex: 0 1 50%;
  overflow: auto;
  box-sizing: border-box;
  border: 0.5px solid red;
  display: flex;


.page-header 
  flex: 0 0 auto;
  background-color: #dcdcdc;


.page-footer 
  flex: 0 0 auto;
  background-color: #dcdcdc;


.swiper-container 
  width: 100%;
  height: 100%;


.swiper-slide 
  text-align: center;
  font-size: 18px;
  background: #fff;
  /* Center slide text vertically */
  display: flex;
  justify-content: center;
  align-items: center;
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" rel="stylesheet" />

<link href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/4.4.6/css/swiper.css" rel="stylesheet" />
<div class="page">
  <div class="main-container">
    <div class="page-header">
      This is a header
    </div>
    <div class="half-containers">
      <!-- Swiper -->
      <div class="swiper-container">
        <div class="swiper-wrapper">
          <div class="swiper-slide">
            <div class="img-wrapper">
              <div class="img-num">1</div>
              <img src='https://i.imgur.com/mSPw98T.jpg' />
            </div>
          </div>
          <div class="swiper-slide">
            <div class="img-wrapper">
              <div class="img-num">2</div>
              <img src='https://i.imgur.com/mSPw98T.jpg' />
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="half-containers">
      <!-- Swiper -->
      <div class="swiper-container">
        <div class="swiper-wrapper">
          <div class="swiper-slide">
            <div class="img-wrapper">
              <div class="img-num">3</div>
              <img src='https://i.imgur.com/mSPw98T.jpg' />
            </div>
          </div>
          <div class="swiper-slide">
            <div class="img-wrapper">
              <div class="img-num">4</div>
              <img src='https://i.imgur.com/mSPw98T.jpg' />
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="page-footer">
      This is a footer
    </div>
  </div>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/4.4.6/js/swiper.js"></script>

考虑到宽度,这实际上是您想要的,但高度很大,因此图像溢出。通过添加height:100%,您将减少高度和宽度,因为the image will try to keep its ratio。当然,包装器不会再次调整大小,因为会有一个循环,因此它会停留在那个大小。

一个简单的解决方法是简单地制作图像包装器position: absolute;。它的高度已经定义为100%,它的宽度将缩小以适应图像宽度。无需调整top/left,因为它已经居中而不使用absolute,因此它将保持居中:

var swiper = new Swiper('.swiper-container', 
  slidesPerView: 1,
  spaceBetween: 50,
  // init: false,
  pagination: 
    el: '.swiper-pagination',
    clickable: true,
  ,
);
img 
  height: 100%;
  max-width: 100%;


.img-num 
  top:0;
  left:0;
  position: absolute;
  padding-left: 10px;
  text-shadow: 1px 1px 2px black, 0 0 1em blue, 0 0 0.2em blue;
  color: white;
  font: 1.5em Georgia, serif;



.img-wrapper 
  border-style: solid;
  border-width: thin;
  height: 100%;
  position: absolute;


html,
body 
  margin: 0;
  height: 100%;


body 
  background: #eee;
  font-family: Helvetica Neue, Helvetica, Arial, sans-serif;
  font-size: 14px;
  color: #000;
  margin: 0;
  padding: 0;


.page 
  height: 100%;
  display: flex;


.main-container 
  flex: 1 1 0;
  display: flex;
  min-width: 0;
  flex-direction: column;


.half-containers 
  flex: 0 1 50%;
  overflow: auto;
  box-sizing: border-box;
  border: 0.5px solid red;
  display: flex;


.page-header 
  flex: 0 0 auto;
  background-color: #dcdcdc;


.page-footer 
  flex: 0 0 auto;
  background-color: #dcdcdc;


.swiper-container 
  width: 100%;
  height: 100%;


.swiper-slide 
  text-align: center;
  font-size: 18px;
  background: #fff;
  /* Center slide text vertically */
  display: flex;
  justify-content: center;
  align-items: center;
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" rel="stylesheet" />

<link href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/4.4.6/css/swiper.css" rel="stylesheet" />
<div class="page">
  <div class="main-container">
    <div class="page-header">
      This is a header
    </div>
    <div class="half-containers">
      <!-- Swiper -->
      <div class="swiper-container">
        <div class="swiper-wrapper">
          <div class="swiper-slide">
            <div class="img-wrapper">
              <div class="img-num">1</div>
              <img src='https://i.imgur.com/mSPw98T.jpg' />
            </div>
          </div>
          <div class="swiper-slide">
            <div class="img-wrapper">
              <div class="img-num">2</div>
              <img src='https://i.imgur.com/mSPw98T.jpg' />
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="half-containers">
      <!-- Swiper -->
      <div class="swiper-container">
        <div class="swiper-wrapper">
          <div class="swiper-slide">
            <div class="img-wrapper">
              <div class="img-num">3</div>
              <img src='https://i.imgur.com/mSPw98T.jpg' />
            </div>
          </div>
          <div class="swiper-slide">
            <div class="img-wrapper">
              <div class="img-num">4</div>
              <img src='https://i.imgur.com/mSPw98T.jpg' />
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="page-footer">
      This is a footer
    </div>
  </div>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/4.4.6/js/swiper.js"></script>

1object-fit 属性指定替换元素的内容应如何适应由其使用高度建立的框,以及宽度。ref

div 不是被替换的元素。替换的元素是 canvasimgiframe 等元素 (https://html.spec.whatwg.org/multipage/rendering.html#replaced-elements)

更新

以上似乎只适用于 Chrome,所以我会考虑一个小的 JS hack 来纠正其他浏览器上元素的宽度:

var swiper = new Swiper('.swiper-container', 
  slidesPerView: 1,
  spaceBetween: 50,
  // init: false,
  pagination: 
    el: '.swiper-pagination',
    clickable: true,
  ,
);
$('.img-wrapper').each(function() 
  $(this).width($(this).find('img').width())
)
$( window ).resize(function() 
  $('.img-wrapper').each(function() 
    $(this).css('width','100%').width($(this).find('img').width())
  )
);
img 
  height: 100%;
  max-width: 100%;
  object-fit:cover;


.img-num 
  top:0;
  left:0;
  position: absolute;
  padding-left: 10px;
  text-shadow: 1px 1px 2px black, 0 0 1em blue, 0 0 0.2em blue;
  color: white;
  font: 1.5em Georgia, serif;



.img-wrapper 
  border-style: solid;
  border-width: thin;
  height: 100%;
  position: absolute;
  max-width:100%;


html,
body 
  margin: 0;
  height: 100%;


body 
  background: #eee;
  font-family: Helvetica Neue, Helvetica, Arial, sans-serif;
  font-size: 14px;
  color: #000;
  margin: 0;
  padding: 0;


.page 
  height: 100%;
  display: flex;


.main-container 
  flex: 1 1 0;
  display: flex;
  min-width: 0;
  flex-direction: column;


.half-containers 
  flex: 0 1 50%;
  overflow: auto;
  box-sizing: border-box;
  border: 0.5px solid red;
  display: flex;


.page-header 
  flex: 0 0 auto;
  background-color: #dcdcdc;


.page-footer 
  flex: 0 0 auto;
  background-color: #dcdcdc;


.swiper-container 
  width: 100%;
  height: 100%;


.swiper-slide 
  text-align: center;
  font-size: 18px;
  background: #fff;
  /* Center slide text vertically */
  display: flex;
  justify-content: center;
  align-items: center;
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" rel="stylesheet" />

<link href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/4.4.6/css/swiper.css" rel="stylesheet" />
<div class="page">
  <div class="main-container">
    <div class="page-header">
      This is a header
    </div>
    <div class="half-containers">
      <!-- Swiper -->
      <div class="swiper-container">
        <div class="swiper-wrapper">
          <div class="swiper-slide">
            <div class="img-wrapper">
              <div class="img-num">1</div>
              <img src='https://i.imgur.com/mSPw98T.jpg' />
            </div>
          </div>
          <div class="swiper-slide">
            <div class="img-wrapper">
              <div class="img-num">2</div>
              <img src='https://i.imgur.com/mSPw98T.jpg' />
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="half-containers">
      <!-- Swiper -->
      <div class="swiper-container">
        <div class="swiper-wrapper">
          <div class="swiper-slide">
            <div class="img-wrapper">
              <div class="img-num">3</div>
              <img src='https://i.imgur.com/mSPw98T.jpg' />
            </div>
          </div>
          <div class="swiper-slide">
            <div class="img-wrapper">
              <div class="img-num">4</div>
              <img src='https://i.imgur.com/mSPw98T.jpg' />
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="page-footer">
      This is a footer
    </div>
  </div>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/4.4.6/js/swiper.js"></script>

【讨论】:

谢谢,谢谢,谢谢。你让我大部分时间完成了我的项目的前端(我的技能很糟糕),然后回到完成后端工作的有趣部分! 拍得好。看起来这在 FireFox 上不起作用...i.imgur.com/1u1WpQM.png @dangel hmm ... 将尝试修复

以上是关于在图像顶部带有文本的滑动响应图像的主要内容,如果未能解决你的问题,请参考以下文章

是否可以有一个带有顶部文本的背景图像的按钮?

当滚动超出工作表中的限制时,防止在 ScrollView 顶部的图像上方填充

在 React Native iOS 中的图像顶部呈现具有透明背景的文本框

带有图像和文本的 HTML 标头 - 将文本与底部对齐?

制作一个保持在图像顶部相同位置的响应按钮

在按钮顶部拉伸图像以推动视图控制器