将 div 缩放以适应窗口大小,但保持纵横比。

52

如何使用CSS和/或JQuery将div缩放以适应浏览器视口,但保留div的纵横比?


我在这里提供了解决方案:https://dev59.com/qEbRa4cB1Zd3GeqP4d-K#19390489 - tommybananas
1
你可以接受下面的答案吗?看起来很遗憾一些非常好的答案未被采纳。 - gillytech
这个问题的所有答案都没有达到期望的结果。保持宽高比很简单,但让它成为正确的宽高比并始终适合或小于可视区域在两个方向上更加棘手。 - atomless
这里的最佳答案(来自Danield)是最好的解决方案:https://dev59.com/0GIj5IYBdhLWcg3wIx7W - atomless
6个回答

48

您不需要使用JavaScript。您可以使用纯CSS。

padding-top百分比相对于包含块的 宽度 进行解释。将其与子元素的position:absolute结合使用,您可以将几乎任何内容放入一个保持其宽高比的框中。

HTML:

<div class="aspectwrapper">
  <div class="content">
  </div>
</div>

CSS:

.aspectwrapper {
  display: inline-block; /* shrink to fit */
  width: 100%;           /* whatever width you like */
  position: relative;    /* so .content can use position: absolute */
}
.aspectwrapper::after {
  padding-top: 56.25%; /* percentage of containing block _width_ */
  display: block;
  content: '';
}
.content {
  position: absolute;
  top: 0; bottom: 0; right: 0; left: 0;  /* follow the parent's edges */
  outline: thin dashed green;            /* just so you can see the box */
}
display: inline-block会在.aspectwrapper框的底部边缘留下一点额外的空间,因此它下面的另一个元素不会与之完全贴合。使用display:block将解决此问题。
感谢这篇文章的提示!
另一种方法依赖于浏览器在只调整图像的宽度或高度时保持其纵横比。 (我将让google生成一个16x9透明图像作为演示,但实际上您将使用自己的静态图像。)
HTML:
<div class="aspectwrapper">
  <img class="aspectspacer" src="http://chart.googleapis.com/chart?cht=p3&chs=160x90" />
  <div class="content">
  </div>
</div>

CSS:

.aspectwrapper {
  width: 100%;
  position: relative;
}
.aspectspacer {
  width: 100%; /* let the enlarged image height push .aspectwrapper's bottom edge */
}
.content {
  position: absolute;
  top: 0; bottom: 0; right: 0; left: 0;
  outline: thin dashed green;
}

1
你能否提供一个 jsFiddle 示例,演示如何使用第一种方法实现完美的盒子(四边相等)调整大小?我还不太明白如何使用你的第一种方法来完成。 - vsync
4
这是链接:http://jsfiddle.net/ks2jH/1/ 请注意,制作完美的框的关键是 padding-top: 100%,这意味着高度应该是 .aspectwrapper 宽度的 100%。由于该宽度设置为 50%,因此它将随其父元素调整大小。我还添加了 overflow: hidden,这样文本在小尺寸下不会扭曲框。 - ʇsәɹoɈ
太好了,谢谢!你应该更新你的答案,包括这个测试页面。 - vsync
7
这似乎只能调整宽度,因此它不会调整div的宽度以适应高度。所以它并不能真正地适应视口,只是维护了容易实现的纵横比。 - Lassi Kinnunen
1
@ʇsәɹoɈ 当然可以,但它似乎不能做这个问题的主题。我忘记了我需要它的确切情况,但我想事情是这样的,我有一个div,必须将该div放入另一个div中,因为某种原因,使其完全适合,而不适合的任何一侧都将按相同的比例缩放。并不是说这个线程中的其他答案也很好。 - Lassi Kinnunen
显示剩余3条评论

5

感谢 Geoff 提供的有关如何构建数学和逻辑结构的提示。以下是我的 jQuery 实现,我使用它来调整灯箱的大小,使其填充整个窗口:

var height = originalHeight;
var width = originalWidth;
aspect = width / height;

if($(window).height() < $(window).width()) {
    var resizedHeight = $(window).height();
    var resizedWidth = resizedHeight * aspect;
}

else { // screen width is smaller than height (mobile, etc)
    var resizedWidth = $(window).width();
    var resizedHeight = resizedWidth / aspect;      
}

目前来说,这在笔记本电脑和移动设备的屏幕尺寸上都运行良好。


2
你对 height < width 的检查只适用于1:1的宽高比。 - talljosh
1
这段程序相关的内容翻译如下:虽然这个代码可以工作,但是你的 IF 语句没有检查正确的东西。var vw=$("#absoluteSized").width(); var vh=$("#absoluteSized").height(); var divAspect=vw/vh; if(divAspect > aspect) { resizedHeight = vh; resizedWidth = resizedHeight * aspect; } else { // screen width is smaller than height (mobile, etc) resizedWidth = vw; resizedHeight = resizedWidth / aspect; } - Lassi Kinnunen
@TRMW,请根据评论修正您的答案,否则将被视为错误。 - BBaysinger

4
我有一种不同的纯HTML/CSS方法,它不依赖于填充或绝对定位。相反,它使用em单位,并依赖于CSS min()函数加上一点数学运算。
想象一下,我们想要一个视口div,其纵横比为16:9,始终适合浏览器窗口,并在轴向上与多余空间居中。以下是我们如何实现这一目标: HTML
  <body>
    <div class="viewport">
      <p>
        This should be a 16:9 viewport that fits the window.
      </p>
    </div>
  </body>

CSS

body {
  width: 100vw;
  height: 100vh;
  margin: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: white;
  font-size: min(1vw, 1.778vh);
}

div.viewport {
  width: 100em;
  height: 56.25em;
  background-color: lightblue;
}

div.viewport > p {
  font-size: 3em;
  text-align: center;
}

您可以在此JSFiddle示例网站中进行实验。
关键就在于body的字体大小font-size,应该设置为min(1vw,Avh),其中A是您想要div具有的长宽比,即width / height。在上面的示例中,我们使用了1.778,约为16/9。
在CSS中,em单位基于元素的字体大小font-size,如果没有明确设置,则继承自父元素。对于您的viewport div,请将width设置为100em(不是rem),并将height设置为Iem,其中I是作为百分比表达的长宽比的倒数,即100 / A或100 * height / width。在上面的示例中,我们使用了56.25,即100 * 9/16。
这种方法的一个额外优点是,所有嵌套的元素也可以使用em单位,以便它们始终与视口的大小精确匹配。您可以在示例中的p元素中看到这一点。
请注意,除了上述方法之外,您还可以在html元素上设置字体大小,然后在所有地方使用rem单位。CSS rem单位类似于em单位,但始终相对于根元素的字体大小。

1
这应该是被接受的答案,因为它完美地实现了最初的要求,并且代码非常简洁。多么优雅的解决方案啊。谢谢。 - undefined

2

Javascipt:

//Responsive Scaling
let outer = document.getElementById('outer'),
wrapper = document.getElementById('wrap'),
maxWidth  = outer.clientWidth,
maxHeight = outer.clientHeight;

window.addEventListener("resize", resize);
resize();

function resize(){
let scale,
width = window.innerWidth,
height = window.innerHeight,
isMax = width >= maxWidth && height >= maxHeight;

scale = Math.min(width/maxWidth, height/maxHeight);
outer.style.transform = isMax?'':'scale(' + scale + ')';
wrapper.style.width = isMax?'':maxWidth * scale;
wrapper.style.height = isMax?'':maxHeight * scale;
}

HTML:

<div id="wrap">
<div id="outer">
{{ fixed content here }}
</div>
</div>

样式:

/* Responsive Scaling */
#wrap {
  position: relative;
  width: 1024px;
  height: 590px;
  margin: 0 auto;
}
#outer {
  position: relative;
  width: 1024px;
  height: 590px;
  transform-origin: 0% 0%;
  overflow: hidden;
}

一些解释和/或一个Codepen会让这个答案更好。 - BBaysinger

1

这可以通过使用JQuery和一些数学知识来实现。

使用JQuery获取视口的宽度和高度以及div当前的尺寸。

$(document).width();

计算div当前的宽高比,例如宽度/高度

您需要一些逻辑来确定是先设置宽度还是高度,然后使用初始比率来计算另一侧。


提供简单的数学路线而不是插件路线,这点值得肯定。 - eyelidlessness

1

jQuery有一个插件,可以将对象扩展到其中一侧达到特定的像素值。结合视口的高度,您可以将任何元素扩展到该大小:jQuery MaxSide


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