使元素与动态调整大小的图像宽度相同?

18
我有一个带标题的响应式幻灯片布局。
我试图让标题与图像宽度相同。问题在于,图像在垂直方向上缩放以适应浏览器大小,我的标题获取的是缩放前的图像宽度。 Fiddle

#big_container {
  display:block;
 position:relative;
 width:100%;
 padding-bottom:40%;
 white-space:nowrap;
 overflow-x:scroll;
 overflow-y:hidden;
}
    
#big_container>div {
 position:absolute;
 top:0;
 right:0;
 bottom:0;
 left:0;
}

.little_container {
 display:inline-block;
 height:100%;
 width:100%;
 text-align:center;
}

#big_container figure {
  display:inline-block;
 height:100%;
 margin:0;
}

figure img {
 max-height:calc(100% - 40px); /* subtract height of caption */
}

figcaption {
 display:block;
 width:100%;
 text-align:left;
 box-sizing:border-box;
 margin:0;
 padding:10px;
 line-height:20px;
 background-color:#ddd;
}
<div id="big_container">
  <div>

  <div class="little_container">
      <figure>
        <img src="http://placekitten.com/500/440">
        <figcaption>
          have a kitty!!1
        </figcaption>
      </figure>
  </div>
  
  <div class="little_container">
      <figure>
        <img src="http://placekitten.com/450/400">
        <figcaption>
          moar kitty!
        </figcaption>
      </figure>
  </div>
  
  <div class="little_container">
      <figure>
        <img src="http://placekitten.com/300/440">
        <figcaption>
          too many kitty..
        </figcaption>
      </figure>
  </div>
  
  </div>
</div>

如何创建一个基于流体图片宽度缩放的标题?
我希望得到一个纯CSS的解决方案。

更新
我尝试过部分在Chrome和Opera中工作,但表现出一些奇怪的行为。 我没有找到任何关于这个问题的错误报告,但我不禁想知道这是否可以被认为是浏览器中的一个错误。


为了更加清晰,以下是我确切需求的简要概述:
  • 标题元素必须与图像宽度相同(最好能够将标题文本左对齐或右对齐到图像边缘)
  • 图像不能被裁剪或拉伸
  • 图像和标题都必须适应其容器(可能是流体的),尽可能利用更多空间。
  • 上述规则应适用于任何尺寸的图像
  • 仅使用CSS(与旧浏览器兼容性不是主要问题,但这是一个优点)
HTML标记可以更改。

更改从一张图片到另一张图片的代码在哪里? - Sumner Evans
1
@jsve 我打算稍后添加一些JavaScript来处理这个问题。我希望使用纯CSS进行布局的原因是,当JavaScript被禁用时,所有图像仍然可以以类似于JavaScript工作时的方式查看。 - gandalf3
看起来字幕的长度实际上与字幕文本强制它们的长度一样长(与缩放前图像的大小无关)。父元素<figure>设置为display:inline-block;,因此它会扩展到最宽的子元素的尺寸...当图像非常小的时候,它就是字幕。如果将字幕更改为单个字符,您会明白我的意思,我想。https://jsfiddle.net/0xmtq77z/1/在文本比图像更宽的情况下,你希望发生什么?你想让文本换行还是被修剪或其他操作? - ryantdecker
昨晚我在谷歌上搜索这个问题是否是 Firefox 的 bug,但并没有花很多时间,也没有找到什么有用的信息。不过我想知道这是否与 figure 和 figcaption 元素相关,但这并没有任何根据。无论如何,这很有趣。 - ryantdecker
你是想要类似这样的效果吗?https://jsfiddle.net/brettdewoody/96jxj5cq/ - Brett DeWoody
显示剩余4条评论
5个回答

5

更新

根据您设置的确切要求,这个问题不能仅使用 CSS 解决。

以下是我能想到的最好解决方案。

演示1(文本高度固定,图像完全可见)
演示2(半透明的可缩放文本在图像顶部,带有动画效果)

我主要使用了一个隐藏的 img 来填补空间,然后使用 background-image 进行最大宽度/高度比例缩放。

我添加了内联样式 background-image,以便可以在 HTML 中处理内容。

为了使其更完美,需要使用脚本来计算标题内容并调整图像/标题的缩小/高度。

片段演示1

html, body {
  margin: 0;
  white-space: nowrap;
  overflow-y: hidden;
}
.container {
  display: inline-block;
  white-space: normal;
  width: 100%;
}
.wrap {
  margin: 0 auto;
  display: table;
}
.image {
  display: table-cell;
  background-position: center bottom;
  background-repeat: no-repeat;
  background-size: contain; 
}
.image img {
  visibility: hidden;
  max-width: 100vw;
  min-width: 100%;
  height: calc(100vh - 80px);
}
.caption {
  display: table-caption;
  caption-side: bottom;
  height: 40px;
  line-height: 22px;
  padding: 8px;
  background-color: #ddd;
  overflow: hidden;
}
.right {
  text-align: right; 
}
<div class="container">
  <div class="wrap">
    <div class="image" style="background-image: url('http://placekitten.com/450/300')">
      <img src="http://placekitten.com/450/300">
    </div>
    <div class="caption right">
      moar kitty!
      moar kitty!
      moar kitty!
    </div>
  </div>
</div>

<div class="container">
  <div class="wrap">
    <div class="image" style="background-image: url('http://placekitten.com/500/440')">
      <img src="http://placekitten.com/500/440">
    </div>
    <div class="caption">
      have a kitty!!1
      have a kitty!!1
      have a kitty!!1
      have a kitty!!1
      have a kitty!!1
      have a kitty!!1
      have a kitty!!1
    </div>
  </div>
</div>

<div class="container">
  <div class="wrap">
    <div class="image" style="background-image: url('http://placekitten.com/300/440')">
      <img src="http://placekitten.com/300/440">
    </div>
    <div class="caption">
      too many kitty..
      too many kitty..
      too many kitty..
    </div>
  </div>
</div>

片段示例2

html, body {
  margin: 0;
  white-space: nowrap;
  overflow-y: hidden;
}
.container {
  position: absolute;
  height: 100%;
  display: inline-block;
  white-space: normal;
  width: 100%;
  background: white;
  opacity: 0;
}
.wrap {
  margin: 0 auto;
  display: table;
}
.image {
  display: table-cell;
  background-position: center bottom;
  background-repeat: no-repeat;
  background-size: contain; 
}
.image img {
  visibility: hidden;
  max-width: 100vw;
  min-width: 100%;
  height: 100vh;
}

.caption-wrap {
  display: table-caption;
  caption-side: bottom;
  position: relative;
}
.caption {
  position: absolute;  
  left: 0;
  right: 0;
  bottom: 100%;
  height: auto;
  line-height: 22px;
  padding: 8px;
  background-color: rgba(0,0,0,0.6);
  color: white;
}
.right {
  text-align: right; 
}
.center {
  text-align: center; 
}

.container:nth-child(3) {
  animation: xfade 12s 0s infinite;
}
.container:nth-child(2) {
  animation: xfade 12s 4s infinite;
}
.container:nth-child(1) {
  animation: xfade 12s 8s infinite;
}

@keyframes xfade{
  17% {
    opacity:1;
  }
  45% {
    opacity:0;
  }
  92% {
    opacity:0;
  }
}
<div class="container">
  <div class="wrap">
    <div class="image" style="background-image: url('http://placekitten.com/450/300')">
      <img src="http://placekitten.com/450/300">
    </div>
    <div class="caption-wrap">
      <div class="caption right">
        moar kitty!
        text .. right aligned
      </div>
    </div>
  </div>
</div>

<div class="container">
  <div class="wrap">
    <div class="image" style="background-image: url('http://placekitten.com/500/440')">
      <img src="http://placekitten.com/500/440">
    </div>
    <div class="caption-wrap">
      <div class="caption">
        have a kitty!!1
        have a kitty!!1
        text .. left aligned
      </div>
    </div>
  </div>
</div>

<div class="container">
  <div class="wrap">
    <div class="image" style="background-image: url('http://placekitten.com/300/440')">
      <img src="http://placekitten.com/300/440">
    </div>
    <div class="caption-wrap">
      <div class="caption center">
        text .. centered
      </div>
    </div>
  </div>
</div>


3
请给出您的评论,让我有机会纠正/澄清什么以及为什么。请注意,不要改变原意。 - Asons
有趣...我不太明白设置背景图像和img元素的目的是什么。至少对我来说,两者之间的切换没有任何变化。 - gandalf3
@gandalf3 隐藏的 img 使标题与图片宽度匹配,需要 background-image 来正确缩放图片。如果您删除 background-image 并使 img 可见,然后调整浏览器的宽度,使其小于图像的宽度,则图像将被压缩并失去其比例。在 此 fiddle 上调整宽度就可以看到。 - Asons

2

尝试使用border属性。

#big_container {
  display: block;
  position: relative;
  width: 100%;
  padding-bottom: 40%;
  white-space: nowrap;
  overflow-x: scroll;
  overflow-y: hidden;
}
#big_container>div {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}
.little_container {
  display: inline-block;
  height: 100%;
  width: 100%;
  text-align: center;
}
#big_container figure {
  display: block;
  height: 100%;
  margin: 0;
}
/* 
     set `border` to `45px` as background for `figacption`
     set `border-left`, `border-right`, `border-top` to `0px`  
*/
img {
  max-height: calc(100% - 40px);
  border: 45px solid #ddd;
  border-left: 0px;
  border-right: 0px;
  border-top: 0px;
}
/*
     set `figcaption` elements
     set `top` to `-50px` to center `content`
     in vertical middle of `border`,
     set `width` to `calc(100% / 3)` : number of `figure` elements
     set `left` to `calc(100% / 3)` : position `content` at 
     horizontal center of `:after` , `border`
*/
figcaption {
  top: -50px;
  display: block;
  position: relative;
  background-color: transparent;
  padding: 10px;
  line-height: 20px;
  box-sizing: border-box;
  width: calc(100% / 3);
  left: calc(100% / 3);
}
<div id="big_container">
  <div>
    <div class="little_container">
      <figure">
        <img src="http://placekitten.com/500/440" />
        <figcaption>have a kitty!!1</figcaption>
      </figure>
    </div>

    <div class="little_container">
      <figure>
        <img src="http://placekitten.com/450/400" />
        <figcaption>moar kitty!</figcaption>
      </figure>
    </div>

    <div class="little_container">
      <figure>
        <img src="http://placekitten.com/300/440" />
        <figcaption>too many kitty..</figcaption>
      </figure>
    </div>

  </div>
</div>

jsfiddle https://jsfiddle.net/601a5uqv/11/ 和 plnkr http://plnkr.co/edit/kHnA3GUTiGu3jm4tE8l4?p=preview 是两个常用的在线代码编辑器,可用于演示、分享和调试 HTML、CSS 和 JavaScript 代码。


太棒了,谢谢!这基本上做到了我想要的,尽管我不喜欢标题内容在CSS中的方式。我会尽可能地等待更干净/可扩展的解决方案,但如果一切都失败了,你的创造力也值得一份赏金 ;) - gandalf3
在figcaption中是否需要widthleft语句? - Py.
@Py. widthleft用于将figcaption元素文本相对于水平定位的多个figcaption元素数量居中。可能可以设置多种不同方式以实现预期结果。 - guest271314
@gandalf3 在 figcaption 元素中添加 overflow:hiddentext-overflow:elissis https://jsfiddle.net/601a5uqv/18/ - guest271314
正如您之前要求的那样,如果您想检查,我已经进行了相当大的更新。 - Asons

1
在这个fiddle中,我使用不同的display规则以及使用vh单位进行计算,达到了所需的效果。我去掉了多余的标记和CSS,但这应该是一个很好的起点,你可以使用和建立它。
代码:

#big_container {
  white-space: nowrap;
}
.little_container {
  display: inline-block;
  width: 100%;
}
figure {
  display: table;
  margin: 0 auto;
}
img {
  height: calc(100vh - 40px);
}
figcaption {
  display: table-caption;
  caption-side: bottom;
  background-color: #ddd;
  padding: 10px;
  line-height: 20px;
}
<div id="big_container">

  <div class="little_container">
    <figure>
      <img src="http://placekitten.com/500/440">
      <figcaption>
        have a kitty!!1
      </figcaption>
    </figure>
  </div>

  <div class="little_container">
    <figure>
      <img src="http://placekitten.com/450/400">
      <figcaption>
        moar kitty!
      </figcaption>
    </figure>
  </div>

  <div class="little_container">
    <figure>
      <img src="http://placekitten.com/300/440">
      <figcaption>
        too many kitty..
      </figcaption>
    </figure>
  </div>

</div>


0

这似乎是使用flexbox的好选择。它们在所有现代浏览器中都可以使用(http://caniuse.com/#feat=flexbox),在IE 10/11中需要一些特殊的CSS,如下所述。

Fiddle(由于某种原因,在Fiddle上标题在IE中会拉伸,但在浏览器中可以正常工作。)

#big_container {
  position:absolute;
  top:0;
  right:0;
  bottom:0;
  left:0;
  padding-bottom: 40px;
  display: flex;
  flex-flow: horizontal;
  align-items: flex-start;
  justify-items: space-around;
  flex-wrap: no-wrap;

  /* For IE 10, 11 */
  display: -ms-flexbox;
  flex-direction: row;
  -ms-flex-wrap: nowrap;
}

.little_container {
  display:inline-block;
  height:100%;
  min-width: 100vw;
  text-align:center;
  display: flex;
  flex-flow: vertical;
  align-items: center;
  justify-content:center;
  flex-direction: column;

  /* For IE 10, 11 */
  display: -ms-flexbox;
  -ms-flex-wrap: nowrap;
  -ms-flex-direction: column;
  -ms-flex-pack: start;
  -ms-flex-align: center;
}


figure {
  width: -moz-min-content;
  width: -webkit-min-content;
  position: relative;
  text-align:center;
  display: flex;
  flex-direction: column;
  flex-wrap: no-wrap;
  align-items: stretch;
  justify-content:center;
  margin:auto;

  /* For IE 10, 11 */
  display: -ms-flexbox;
  -ms-flex-direction: row;
  -ms-flex-wrap: wrap;
  -ms-flex-pack: center;
  -ms-flex-align: center;
  -ms-flex-line-pack: center;
}

figure img {

  display:block;
  text-align:left;
  box-sizing: border-box;
  margin:0;
  max-height:calc(100% - 40px); /* subtract height of caption */
  -ms-flex: 0 0 calc(100%-40);
  display: block;

}

figcaption {
  display:block;
  text-align:left;
  box-sizing: border-box;
  margin:0;
  padding:10px;
  line-height:20px;
  background-color:#ddd;
  -ms-flex: 1 1 60%;
  max-width: 100%;

}

我移除了包裹小元素的 #big_container 中额外的 <div>,因为它似乎是不必要的。

<div id="big_container">

  <div class="little_container">
      <figure>
        <img src="http://placekitten.com/500/440">
        <figcaption>
          I has kitty!!
        </figcaption>
      </figure>
  </div>

  <div class="little_container">
      <figure>
        <img src="http://placekitten.com/450/400">
        <figcaption>
          moar kitty!
        </figcaption>
      </figure>
  </div>

  <div class="little_container">
      <figure>
        <img src="http://placekitten.com/300/440">
        <figcaption>
          I has too many kitty. but I still need moar. Oh! No!!!!! I cannot get enuf!
        </figcaption>
      </figure>
  </div>
</div>

此外,如果您还不知道它们,请了解CSS视口单位vw和vh。http://caniuse.com/#feat=viewport-units

我喜欢标题在添加更多文本时会自动扩展。有没有办法让图像+标题尽可能地缩放并填充容器,而不改变图像的纵横比?经过一段时间的尝试,我想出了这个,但标题溢出了,而不是使图像变小。顺便说一句,绝对定位的 div 是为了创建一个具有固定纵横比的容器而设置的(来自这个答案),但可以忽略此问题。 - gandalf3
2
我认为是没有的。纯CSS不提供任何方法来确定内容的大小。如果你使用JavaScript,你可以计算出标题的长度。通过这个你可以大致了解标题所占据的行数,然后相应地调整图像的尺寸。但即便如此,这也会很复杂,因为当你调整图像的高度时,横向可容纳字母的空间将变得更小。 - J. Nilles
@J.Nilles 非常好的解释了字幕文本调整大小的问题,谢谢。 - Asons

0

有一个非常少人知道的 CSS 属性,它可以满足你的需求:min-content。它的作用是:

  • 使用 内在值,即它会自适应其内容。
  • 自动减小容器的宽度,以便图像完美地适合其中。
  • 如果文本内容需要在容器内换行,则应该换行。

阅读这篇文章:使用 CSS Min-Content 从内而外设计

有一件事我不太喜欢,那就是前缀:

width: -moz-min-content;
width: -webkit-min-content;
width: min-content;

我添加了一些重置并注释了哪些样式是:

  • 可选的
  • 推荐的
  • 必需的

重要的CSS

  figure {
     height: 100%;
     width: -moz-min-content;
     /* REQUIRED */
     width: -webkit-min-content;
     /* REQUIRED */
     width: min-content;
     /* REQUIRED */
  }

演示:https://plnkr.co/edit/6e1hYkK6lB2KVS3uvQy2?p=preview

奖励:https://plnkr.co/edit/gahMFQScxQtkweo1G2jD?p=preview

我已经将字幕变长,并添加了以下CSS,以展示如何包装您的字幕而不会突破或扩展figcaption。

CSS奖励

figcaption * {
  white-space: pre-wrap;
  /* RECOMMENDED */
}

虽然不是必需的,但我认为在不久的将来,您可能希望获得自动换行的字幕。 我已经审查了其他文件:

  • LGSon的方案实际上会扩展图像和figcaption,但很容易使用我的解决方案来修复。

  • guest271314的方案扩展文本溢出,由于它不是一个容器类元素,我不确定什么可以解决这个问题。

  • Ryan Litte的方案扩展了figcaption,我相信我的解决方案也可以解决这个问题。


也许你可以放一个类似的模拟器或其他工具来测试。在我看到的stackoverflow代码片段中,这似乎无法产生所需的输出。 - Py.
不错,尽管在Edge/IE中min-content不起作用,如果你调整大小,标题不会随之改变。 - Asons
奇怪..对我来说,在FireFox中演示无法工作。奖金在FF 43中有效,但在FF 45中无法工作!? - gandalf3
@gandalf3 好的,两个问题都已经解决了。我不得不移除绝对定位的图层,在每个方向上都拉伸到0。 - zer00ne
谢谢你向我介绍了 min-content 关键字!不过,我无法让它与缩放以适应容器内的图像一起工作。这有可能吗? - gandalf3
显示剩余4条评论

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