保持div的宽高比但在CSS中填充屏幕宽度和高度?

时间:2013-12-15 01:24:51

标签: html css responsive-design aspect-ratio

我有一个网站,它具有大约16:9横向的固定宽高比,就像一个视频。

我想让它居中并扩展以填充可用的宽度和可用的高度,但绝不会在任何一侧变大。

例如:

  1. 高而薄的页面会使内容在保持比例高度的同时拉伸整个宽度。
  2. 一个较短的宽页面将使内容延伸到整个高度,并具有成比例的宽度。

  3. 我一直在研究两种方法:

    1. 使用具有正确宽高比的图像来展开容器div,但我无法让它在主要浏览器中的行为方式相同。
    2. 设置比例底部填充,但仅相对于宽度有效并忽略高度。它随着宽度不断变大,并显示垂直滚动条。

    3. 我知道你可以很容易地用JS做到这一点,但我想要一个纯粹的CSS解决方案。

      有什么想法吗?

9 个答案:

答案 0 :(得分:244)

使用新的CSS viewport units vwvh(视口宽度/视口高度)

<强> FIDDLE

垂直和水平调整大小,您会看到元素将始终填充最大视口大小而不会破坏比例且没有滚动条!

(PURE)CSS

div
{
    width: 100vw; 
    height: 56.25vw; /* height:width ratio = 9/16 = .5625  */
    background: pink;
    max-height: 100vh;
    max-width: 177.78vh; /* 16/9 = 1.778 */
    margin: auto;
    position: absolute;
    top:0;bottom:0; /* vertical center */
    left:0;right:0; /* horizontal center */
}

* {
  margin: 0;
  padding: 0;
}
div {
  width: 100vw;
  height: 56.25vw;
  /* 100/56.25 = 1.778 */
  background: pink;
  max-height: 100vh;
  max-width: 177.78vh;
  /* 16/9 = 1.778 */
  margin: auto;
  position: absolute;
  top: 0;
  bottom: 0;
  /* vertical center */
  left: 0;
  right: 0;
  /* horizontal center */
}
<div></div>

如果您想要使用视口的最大宽度和高度的90%: FIDDLE

* {
  margin: 0;
  padding: 0;
}
div {
  width: 90vw;
  /* 90% of viewport vidth */
  height: 50.625vw;
  /* ratio = 9/16 * 90 = 50.625 */
  background: pink;
  max-height: 90vh;
  max-width: 160vh;
  /* 16/9 * 90 = 160 */
  margin: auto;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
}
<div></div>

此外,浏览器支持也非常好:IE9 +,FF,Chrome,Safari- caniuse

答案 1 :(得分:16)

只需在LESS mixin中重新制定Danield的答案,以便进一步使用:

// Mixin for ratio dimensions    
.viewportRatio(@x, @y) {
  width: 100vw;
  height: @y * 100vw / @x;
  max-width: @x / @y * 100vh;
  max-height: 100vh;
}

div {

  // Force a ratio of 5:1 for all <div>
  .viewportRatio(5, 1);

  background-color: blue;
  margin: 0;
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0;
}

答案 2 :(得分:7)

我原来的问题是如何既有一个固定方面的元素,又要在指定的容器中完全适合它,这使得它有点繁琐。如果您只是想要一个单独的元素来保持其宽高比,那么它就容易多了。

我遇到的最好方法是给元素零高度,然后使用百分比填充 - 底部给它高度。填充百分比始终与元素的宽度成比例,而不是其高度,即使其顶部或底部填充也是如此。

W3C Padding Properties

因此,利用它可以给元素一个百分比宽度放在一个容器中,然后填充以指定宽高比,或者换句话说,它的宽度和高度之间的关系。

.object {
    width: 80%; /* whatever width here, can be fixed no of pixels etc. */
    height: 0px;
    padding-bottom: 56.25%;
}
.object .content {
    position: absolute;
    top: 0px;
    left: 0px;
    height: 100%;
    width: 100%;
    box-sizing: border-box;
    -moz-box-sizing: border-box;
    padding: 40px;
}

因此,在上面的示例中,对象占据容器宽度的80%,然后其高度为该值的56.25%。如果它的宽度是160px那么底部填充,因此高度将是90px - 一个16:9的宽高比。

这里可能不是问题的一个小问题是你的新对象里面没有自然空间。如果您需要放置一些文本,并且文本需要使用自己的填充值,则需要在其中添加容器并在其中指定属性。

在某些较旧的浏览器上也不支持vw和vh单位,因此我可能无法接受我的问题的答案,你可能不得不使用更低级的东西。

答案 3 :(得分:7)

CSS media query @mediaCSS viewport units vwvh一起使用,以适应视口的宽高比。这样做的好处是可以更新其他属性,例如font-size

This fiddle演示了div的固定宽高比,以及与其比例完全匹配的文本。

初始尺寸基于全宽:

div {
  width: 100vw; 
  height: calc(100vw * 9 / 16);

  font-size: 10vw;

  /* align center */
  margin: auto;
  position: absolute;
  top: 0px; right: 0px; bottom: 0px; left: 0px;

  /* visual indicators */
  background:
    url(data:image/gif;base64,R0lGODlhAgAUAIABAB1ziv///yH5BAEAAAEALAAAAAACABQAAAIHhI+pa+EPCwA7) repeat-y center top,
    url(data:image/gif;base64,R0lGODlhFAACAIABAIodZP///yH5BAEAAAEALAAAAAAUAAIAAAIIhI8Zu+nIVgEAOw==) repeat-x left center,
    silver;
}

然后,当视口宽度大于所需的宽高比时,切换到高度作为基本度量:

/* 100 * 16/9 = 177.778 */
@media (min-width: 177.778vh) {
  div {
    height: 100vh;
    width: calc(100vh * 16 / 9);

    font-size: calc(10vh * 16 / 9);
  }
}

这与@Danield的max-widthmax-height approach非常相似,只是更加灵活。

答案 4 :(得分:5)

我了解到您要求您提供CSS特定解决方案。要保持纵横比,您需要将高度除以所需的纵横比。 16:9 = 1.777777777778。

要获得容器的正确高度,您需要将当前宽度除以1.777777777778。由于您无法仅使用width检查容器的CSS或除以CSS的百分比,因此如果没有JavaScript(据我所知),这是不可能的。

我写了一个可以保持所需宽高比的工作脚本。

<强> HTML

<div id="aspectRatio"></div>

<强> CSS

body { width: 100%; height: 100%; padding: 0; margin: 0; }
#aspectRatio { background: #ff6a00; }

<强>的JavaScript

window.onload = function () {
    //Let's create a function that will scale an element with the desired ratio
    //Specify the element id, desired width, and height
    function keepAspectRatio(id, width, height) {
        var aspectRatioDiv = document.getElementById(id);
        aspectRatioDiv.style.width = window.innerWidth;
        aspectRatioDiv.style.height = (window.innerWidth / (width / height)) + "px";
    }

    //run the function when the window loads
    keepAspectRatio("aspectRatio", 16, 9);

    //run the function every time the window is resized
    window.onresize = function (event) {
        keepAspectRatio("aspectRatio", 16, 9);
    }
}

如果您想使用

显示不同比例的其他内容,可以再次使用function
keepAspectRatio(id, width, height);

答案 5 :(得分:2)

现在指定了一个新的CSS属性来解决这个问题:object-fit

http://docs.webplatform.org/wiki/css/properties/object-fit

浏览器支持仍然有点缺乏(http://caniuse.com/#feat=object-fit) - 目前在大多数浏览器中都有一定程度的作用,除了微软 - 但考虑到时间,这正是这个问题所需要的。

答案 6 :(得分:1)

Danield's answer很好,但它只能在div填充整个视口时使用,或者使用一些calc,如果其他内容的宽度和高度可以使用视口已知。

然而,通过将margin-bottom技巧与上述答案中的方法相结合,可以将问题简化为只需要知道其他内容的高度。如果您有一个固定的高度标题,但是例如边栏的宽度未知,则此选项很有用。

body {
  margin: 0;
  margin-top: 100px; /* simulating a header */
}

main {
  margin: 0 auto;
  max-width: calc(200vh - 200px);
}

section {
  padding-bottom: 50%;
  position: relative;
}

div {
  position:absolute;
  background-color: red;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
}
<main>
  <section>
    <div></div>
  </section>
</main>

Here it is in a jsfiddle using scss,这使得价值来自哪里更加明显。

答案 7 :(得分:0)

基于Daniel's answer,我为Bootstrap模态对话框内的youtube视频的iframe编写了带内插( server { listen 443 ssl default_server; listen [::]:443 ssl default_server; server_name subdomain_name; include /etc/nginx/snippets/ssl; location / { proxy_pass http://ip_address:port_number/services; } } )的SASS mixin:

#{}

用法:

@mixin responsive-modal-wiframe($height: 9, $width: 16.5,
                                $max-w-allowed: 90, $max-h-allowed: 60) {
  $sides-adjustment: 1.7;

  iframe {
    width: #{$width / $height * ($max-h-allowed - $sides-adjustment)}vh;
    height: #{$height / $width * $max-w-allowed}vw;
    max-width: #{$max-w-allowed - $sides-adjustment}vw;
    max-height: #{$max-h-allowed}vh;
  }

  @media only screen and (max-height: 480px) {
    margin-top: 5px;
    .modal-header {
      padding: 5px;
      .modal-title {font-size: 16px}
    }
    .modal-footer {display: none}
  }
}

HTML:

.modal-dialog {
  width: 95vw; // the modal should occupy most of the screen's available space
  text-align: center; // this will center the titles and the iframe

  @include responsive-modal-wiframe();
}

当宽度或高度与视频不成比例时,这将始终显示视频没有YouTube添加到iframe的黑色部分。注意:

  • <div class="modal"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">&times;</span> </button> <h4 class="modal-title">Video</h4> </div> <div class="modal-body"> <iframe src="https://www.youtube-nocookie.com/embed/<?= $video_id ?>?rel=0" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> </div> <div class="modal-footer"> <button class="btn btn-danger waves-effect waves-light" data-dismiss="modal" type="button">Close</button> </div> </div> </div> </div> 稍作调整,以补偿侧面出现的黑色部分中的一小部分;
  • 在超低高度的设备(<480px)中,标准模式占用了大量空间,因此我决定:
    1. 隐藏$sides-adjustment;
    2. 调整.modal-footer的位置;
    3. 减小.modal-dialog的大小。

经过大量测试,现在这对我来说是完美的。

答案 8 :(得分:-1)

这里是基于@Danield解决方案的解决方案,即使在div中也可以使用。

在该示例中,我使用的是Angular,但是它可以快速迁移到Vanilla JS或其他框架。

主要思想是将@Danield解决方案移到空的iframe中,并在iframe窗口大小更改后复制尺寸。

该iframe必须与其父元素相适应。

https://stackblitz.com/edit/angular-aspect-ratio-by-iframe?file=src%2Findex.html

以下是一些屏幕截图:

enter image description here

enter image description here

enter image description here