【问题标题】:Make element same width as dynamically sized image?使元素与动态大小的图像宽度相同?
【发布时间】:2016-02-08 20:20:59
【问题描述】:

我有一个响应式幻灯片式布局,每张图片下方都有标题。

我正在尝试使标题与图像的宽度相同。问题是图像被缩放以垂直适应浏览器,而我的标题是在缩放之前获取图像的宽度。

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 解决方案。

更新
事实证明我的上述尝试partially works in chrome and opera, but exhibits some odd behavior。 我没有找到任何关于该主题的错误报告,但我不禁想知道这是否可能被视为浏览器中的错误。


为清楚起见,以下是我的确切要求的简要概述:

  • 标题元素必须与图像的宽度相同(如果能够将标题文本左对齐或右对齐到图像的边缘,那就太好了)
  • 不得裁剪或拉伸图像
  • 图片和标题必须都适合它们的容器(可能是流动的),并使用尽可能多的空间。
  • 以上规则应适用于任何尺寸的图像
  • 仅 CSS(与旧浏览器的兼容性不是主要问题,但这是一个优点)

html 标记可以改变。

【问题讨论】:

  • 从一个图像更改为另一个图像的代码在哪里?
  • @jsve 我打算稍后添加一些 javascript 来处理。我希望在纯 css 中进行布局的原因是,当禁用 javascript 时,所有图像仍然可以以与 javascript 工作时类似的方式查看。
  • 看起来标题实际上与标题文本强制它们一样长(与缩放前的图像大小无关)。父元素&lt;figure&gt; 设置为display:inline-block;,因此它扩展为最宽的子元素的大小......当图像非常小时,这是标题。如果您将标题更改为单个字符,您会明白我的意思,我想。 jsfiddle.net/0xmtq77z/1在文字比图片宽的情况下,你想怎么办?您想要文本换行、修剪还是...?
  • @ryantdecker caption still seems larger than the image for me..? (firefox)至于文本,修剪很好。我可能会在.little_container 上设置一个最小宽度,如果图像非常瘦,则允许标题更大,但对于我的使用,假设标题永远不会比图像长是可以接受的。
  • hmmm - 抱歉,我只在 chrome 中查看 - 似乎两者的行为不一致。

标签: html css


【解决方案1】:

更新

根据您为此问题设置的确切要求,仅使用 CSS 无法解决。

这是我能想到的最好的。

Fiddle demo 1(文本高度固定,图像完全可见)
Fiddle demo 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>

【讨论】:

  • 投反对票的人,请发表评论,以便我有机会更正/澄清什么/为什么。
  • 有趣..我不太明白背景图片+img元素设置的目的是什么。至少对我来说,两者之间的切换没有任何改变
  • @gandalf3 隐藏的img 使标题匹配图像的宽度,需要background-image 才能正确缩放图像。如果您删除background-image 并使img 可见,然后调整浏览器的宽度使其小于图像的宽度,则图像将被挤压并失去其比例。调整this fiddle 的宽度,你会看到。
【解决方案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

【讨论】:

  • 太棒了,谢谢!这几乎可以满足我的要求,尽管我不能说我对 css 中的字幕内容和所有内容感到满意。我会尽可能地坚持一个更干净/可扩展的解决方案,但如果全部否则失败,你应该因为纯粹的创造力而获得赏金;)
  • figcaption 中是否需要 widthleft 语句?
  • @Py。 width , left 用于将 figcaption 元素的文本相对于水平定位的 figcaption 元素的数量居中。可能可以设置几种不同的方式来实现预期的结果。
  • @gandalf3 添加 overflow:hiddentext-overflow:elissisfigcaption 元素 jsfiddle.net/601a5uqv/18
  • 正如你之前要求的小提琴,如果你想检查一下,我做了相当多的更新。
【解决方案3】:

在这个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>

【讨论】:

    【解决方案4】:

    有一个鲜为人知的 CSS 属性可以满足您的需求:min-content。它的作用是:

    • 使用intrinsic value,这意味着它会适应它的内容。
    • 自动减小容器的宽度,使图像完全适合其中。
    • 如果文本内容需要在容器内换行,则应该这样做。

    阅读这篇文章:Design From the Inside Out With 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 sn-p 中产生所需的输出。
    • 不错,虽然 min-content 在 Edge/IE 中不起作用,而且如果您调整大小,标题也不起作用。
    • 奇怪.. 对我来说,该演示不适用于 FF。奖励在 FF 43 中有效,但在 FF 45 中无效!?
    • @gandalf3 好的,两者都是固定的,我必须删除在每个方向上拉伸为 0 的绝对定位层。
    • 感谢您向我介绍min-content 关键字!我无法让它与缩放以适合容器内部的图像一起使用..这可能吗?
    【解决方案5】:

    这似乎很适合弹性盒。它们可以在所有现代浏览器 (http://caniuse.com/#feat=flexbox) 和 IE 10/11 中使用,如下所述。

    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 中取出了额外的&lt;div&gt;,用于包裹较小的物品,因为它似乎没有必要。

    <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

    【讨论】:

    • 我喜欢当添加更多文本时标题会根据需要扩展。有没有办法让图像+标题在不改变图像纵横比的情况下放大并尽可能多地填充容器?在玩了一段时间后,我想出了this,但标题溢出而不是使图像更小。顺便说一句,绝对定位的div是制作具有固定纵横比的容器的设置的一部分(来自this answer),但是这个问题可以忽略。
    • 我认为没有。纯 CSS 不给你任何方法来确定内容的大小。如果您使用 Javascript,您可以计算出标题的长度。这样您就可以很好地了解标题将占用多少行,然后您可以相应地调整图像的大小。但即使这样也会很复杂,因为当您调整图像的高度时,您将有更少的空间来填充字母。
    • @J.Nilles 这是解释标题文本大小调整问题的完美方式,谢谢。
    猜你喜欢
    • 2013-12-07
    • 1970-01-01
    • 2011-03-14
    • 2021-09-28
    • 1970-01-01
    • 1970-01-01
    • 2013-05-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多