如何使div高度自适应背景大小?

340

如何使一个div根据设置的背景自动调整大小,而无需为它设置特定的高度(或最小高度)?


请查看我的回答: https://stackoverflow.com/a/62262990/8508777 - Yosef Tukachinsky
30个回答

657

有一种非常好的方法可以让背景图片像 img 元素一样工作,从而自动调整其 height。您需要知道图像的宽高比。将容器的 height 设置为 0,并将 padding-top 按百分比设置为图像比例。

效果如下:

div {
    background-image: url('http://www.pets4homes.co.uk/images/articles/1111/large/feline-influenza-all-about-cat-flu-5239fffd61ddf.jpg');
    background-size: contain;
    background-repeat: no-repeat;
    width: 100%;
    height: 0;
    padding-top: 66.64%; /* (img-height / img-width * container-width) */
                /* (853 / 1280 * 100) */
}

你刚刚获得了一个带有自动高度的背景图片,其工作方式类似于img元素。这是一个可工作的原型(你可以调整大小并检查div高度):http://jsfiddle.net/8m9ur5qj/


25
太棒了!为了未来观看这个答案的人,如果你正在使用指南针(scss),我已经使用它们的辅助函数创建了一个混合器,可以为您执行计算: @mixin div-same-size-as-background-img($url) { background-image: url($url); background-size: contain; background-repeat: no-repeat; width: 100%; height: 0; padding-top: percentage(image-height($url) / image-width($url)); } - Benjamin K.
20
给那些好奇的人FYI,padding-top并不会创建白色空间,因为它只增加元素的高度。图片是背景图片,所以它可以适当地显示定位和间距。我们必须想出这样的CSS技巧,感觉相当愚蠢。 - ahnbizcad
14
很遗憾,padding-top会防止你在div中放置其他任何东西,比如覆盖在背景上的表单元素。 - Gary Hayes
18
你可以将position:relative应用于某个div,然后在其中添加另一个div,并设置其为position:absolute; top:0; bottom:0; left:0; right:0; - malifa
23
虽然这种方法可以显示背景图片,但填充内部间距使div本身的实用性减弱。Kryptik建议在容器内添加一个绝对定位的div,但那么使用背景图片还有何意义?如果你只是要绝对定位所有东西,那么可以在内容div中直接使用实际图像,这样做就失去了一开始使用背景图片的目的。 - paulmz
显示剩余14条评论

299

另一个,可能效率较低的解决方案是在 img 元素下包含图像并将其设置为 visibility: hidden;。然后将周围 div 的 background-image 设置为与图像相同。

这将使周围的div大小与 img 元素中的图像相同,但以背景形式显示。

<div style="background-image: url(http://your-image.jpg);">
 <img src="http://your-image.jpg" style="visibility: hidden;" />
</div>

19
由于图像会占用“空间”,导致内容看起来上方有大量的边距,因此这并不是非常有用。 - Bart Calixto
51
也许我漏掉了什么,但是如果你无论如何都要在你的标记中插入一个 img,为什么不直接 隐藏实际的 <img>,也不用考虑 background-image 呢?这种做法有什么优势呢? - Mark Amery
5
回答不错,但是浏览器需要加载两次吗? - www139
11
当你说“load”时,你具体指的是什么?一旦图像被下载,它就会被缓存。从那时起,任何其他请求都基于本地副本。所以,不会下载两次,但是会加载两次。 - Tmac
3
@MarkAmery background-image 最酷的一点是它可以使用 CSS 混合模式,而 img 不能。 - Aaron Gray
显示剩余9条评论

38

使用CSS无法自动调整背景图像的大小。

你可以通过在服务器上测量背景图像,然后将这些属性应用于div来绕过此问题,正如其他人所提到的那样。

您也可以通过编写一些JavaScript,根据图像大小(一旦图像已下载)调整div的大小来解决此问题 - 这基本上是相同的方法。

如果您需要使您的div适应图像大小,我想问为什么不在您的div内部放置一个<img>标签?


谢谢 - 但我需要它作为背景,所以图像技巧行不通。我想我会像你说的那样破解一些JavaScript,最坏的情况是,但这可能不值得。 - JohnIdol
4
那可能不是一个好主意。浏览器可能需要几秒钟才能下载您的图片,并且在那之前您无法测量它,因此您的 div 将会保持错误的大小相当长一段时间! - Orion Edwards
2
他可以在文档准备就绪时运行JavaScript。 - Scott Tesler
2
你不能通过媒体查询更改 imgsrc,但是你可以通过媒体查询更改用作背景图像的文件。 - Scott Marcus

25

这个回答与其他回答类似,但对大多数应用程序来说是最好的。您通常需要事先知道图像大小。这将使您能够添加叠加文本、标题等,而无需使用负填充或绝对定位图像。关键是将填充%设置为与图像宽高比相匹配,如下面的示例所示。我使用了此答案,基本上只是添加了一个图像背景。

.wrapper {
  width: 100%;
  /* whatever width you want */
  display: inline-block;
  position: relative;
  background-size: contain;
  background: url('https://upload.wikimedia.org/wikipedia/en/thumb/6/67/Wiki-llama.jpg/1600px-Wiki-llama.jpg') top center no-repeat;
  margin: 0 auto;
}
.wrapper:after {
  padding-top: 75%;
  /* this llama image is 800x600 so set the padding top % to match 600/800 = .75 */
  display: block;
  content: '';
}
.main {
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  left: 0;
  color: black;
  text-align: center;
  margin-top: 5%;
}
<div class="wrapper">
  <div class="main">
    This is where your overlay content goes, titles, text, buttons, etc.
  </div>
</div>


2
-1 用 !important 是不推荐的,而且链接到另一个答案也不好。请考虑将其他答案中相关的代码复制过来(并注明出处),以使此答案更完整,并防止链接失效。 - totallyNotLizards
@jammypeach 这样好吗? - horsejockey
1
@horsejockey,除非我漏掉了什么,否则这不会扩展图像,只会遮蔽它。 - dwkns
@dwkns 奇怪的是,所有的背景调用都需要在同一个元素中。我发现当我在特定的id上指定“background: url()”和在一般类中指定“background-size: contain”时,它会被裁剪。 - Nathan Williams
@dwkns 更新:我通过使用“background-image: url()”而不是“background: url()”来解决了那个问题。 - Nathan Williams

18

我看了一些解决方案,它们很棒,但我觉得我找到了一个令人惊讶的简单方法。

首先,我们需要从背景图像中获取比例。我们只需通过一个维度除以另一个维度。然后我们得到类似于66.4%的东西。

当我们有了图像比率之后,我们可以通过将比率乘以视口宽度来简单地计算div的高度:

height: calc(0.664 * 100vw);

对我来说,它很有效,可以正确设置div的高度,并在窗口调整大小时进行更改。


2
是的,这是一个很巧妙的技巧,但如果图像尺寸已知,为什么不直接使用图像的高度呢?我认为我们正在寻找一种适用于任何图像的解决方案,而不是硬编码数字... - minusf
根据屏幕尺寸调整高度的增加和减小也不总是理想的。 - minusf
很棒的解决方案:它可以根据浏览器的大小进行响应,并且您仍然可以使用flex box显示。我现在会尝试用它来解决我的问题,看看能否完成我的工作。干杯! - m3.b
然而,我很想了解为什么将图像比率乘以100vw会使其起作用。干杯! - m3.b

16

也许这可以帮助您,虽然不完全是一个背景,但您可以得到灵感:

<style>
div {
    float: left;
    position: relative;
}
div img {
    position: relative;
}

div div {
    position: absolute;
    top:0;
    left:0;
}
</style>

<div>
    <img src="http://antwrp.gsfc.nasa.gov/apod/image/0903/omegacen_davis.jpg" />
    <div>Hi there</div>
</div>

请解释一下为什么您将img的位置保持为相对定位? - Divyanshu Jimmy
1
可能是因为 float: left; 破坏了他的定位。 - Isaac

15

我很确定这段话不会被看到,但如果你的问题和我的一样,这是我的解决方案:

.imaged-container{
  background-image:url('<%= asset_path("landing-page.png") %> ');
  background-repeat: no-repeat;
  background-size: 100%;
  height: 65vw;
}

我想让一个div在图片中央,这可以让我实现这个效果。


15

其他答案忽略的一个纯CSS解决方案。

"content:"属性主要用于向元素插入文本内容,但也可以用于插入图像内容。

.my-div:before {
    content: url("image.png");
}
这将导致div的高度调整为图像的实际像素大小。要同时调整宽度,请添加以下内容:
.my-div {
    display: inline-block;
}

1
我喜欢这个解决方案,但当浏览器变小时,头部图像被设置为响应式,下面会留下很多空白。 - MG1
这是一个很棒的答案 ❤ - kuubson

12

最近引入的CSS aspect-ratio 属性(约2020-2021年)是一种很好的方法,可以避免填充黑客,并且受到所有主流浏览器的支持。

由于我们需要事先知道图像的宽高比,在许多用例中,您将能够预先确定图像尺寸比率(但并非始终适用于用户生成的内容),因此您可以在必要时硬编码单个样式或内联css。

aspect-ratio 将根据提供的比例计算高度(或如果指定了高度,则计算宽度),当宽度被指定时。

div {
    /*common ratio, like an 800*600px image */
    aspect-ratio: 3 / 2;
    /* computed height will be 133.33px, which is width/aspect-ratio */
    width: 200px;
    /* red BG for debugging so any image bleed is shown*/
    background: red; 
    background-image: url('https://images.unsplash.com/photo-1631163190830-8770a0ad4aa9?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=200&q=80');
}
<div></div>


1
感谢您在此留下评论的努力。 - Matt
1
天啊,他们终于加入了一个纵横比属性??我记得几年前曾经为了解决这个问题而苦苦挣扎,但最终只能用JS来解决。感谢这个新属性! - SeriousLee

6
你可以在服务器端完成此操作:测量图像大小,然后设置div大小;或者使用JS加载图像,读取其属性,然后设置DIV大小。
还有一个想法,将相同的图像作为IMG标签放入div中,但将其可见性设置为隐藏,通过相对位置进行调整,并将此div的背景设置为该图像。

为什么需要服务器端?这应该可以通过CSS实现。 - GTHell
2
@GTHell 哈哈哈 - 检查我回答的年份 - Itay Moav -Malimovka
@ItayMoav-Malimovka 呵呵,没有注意到。 - GTHell

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