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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20590239/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 22:30:00  来源:igfitidea点击:

Maintain aspect ratio of div but fill screen width and height in CSS?

htmlcssresponsive-designaspect-ratio

提问by Henry Gibson

I have a site to put together that has a fixed aspect ratio of approximately 16:9landscape, like a video.

我有一个网站可以放在一起,它具有大约16:9横向的固定纵横比,例如视频。

I want to have it centred and expand to fill the available width, and the available height, but never to grow larger on either side.

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

For example:

例如:

  1. A tall and thin page would have the content stretching the full width while maintaining a proportional height.
  2. A short wide page would have the content stretching the full height, with a proportional width.
  1. 又高又薄的页面会在保持比例高度的同时,将内容拉伸到整个宽度。
  2. 短而宽的页面的内容会拉伸整个高度,宽度成比例。


There are two methods I've been looking at:

我一直在研究两种方法:

  1. Use an image with the right aspect ratio to expand a container div, but I couldn't get it to behave the same way across major browsers.
  2. Setting a proportional bottom padding, but that only works relatively to the width and ignores the height. It just keeps getting bigger with the width and displays vertical scroll bars.
  1. 使用具有正确纵横比的图像来扩展容器div,但我无法让它在主要浏览器中以相同的方式运行。
  2. 设置成比例的底部填充,但这仅适用于宽度而忽略高度。它只是随着宽度不断变大并显示垂直滚动条。


I know you could do this with JS quite easily, but I'd like a pure CSS solution.

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

Any ideas?

有任何想法吗?

采纳答案by Henry Gibson

There is now a new CSS property specified to address this: object-fit.

现在有规定来解决这个新的CSS属性:object-fit

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

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

Browser support is still somewhat lacking (http://caniuse.com/#feat=object-fit) - currently works to some extent in most browsers except Microsoft - but given time it is exactly what was required for this question.

浏览器支持仍然有些缺乏(http://caniuse.com/#feat=object-fit) - 目前在除 Microsoft 之外的大多数浏览器中都有一定程度的工作 - 但给定时间它正是这个问题所需要的。

回答by Danield

Use the new CSS viewport unitsvwand vh(viewport width / viewport height)

使用新的CSS 视口单位vwvh(视口宽度/视口高度)

FIDDLE

小提琴

Resize vertically and horizontally and you'll see that the element will always fill the maximum viewport size without breaking the ratio and without scrollbars!

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

(PURE) CSS

(纯)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>

If you want to use a maximum of say 90% width and height of the viewport: FIDDLE

如果你想使用最多 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>

Also, browser support is pretty good too: IE9+, FF, Chrome, Safari- caniuse

此外,浏览器支持也很不错:IE9+、FF、Chrome、Safari- caniuse

回答by Christophe Marois

Just reformulating Danield's answer in a LESS mixin, for further usage:

只需Danield在 LESS mixin 中重新制定's answer,以供进一步使用:

// 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;
}

回答by Paul

Use a CSS media query@mediatogether with the CSS viewport unitsvwand vhto adapt to the aspect ratio of the viewport. This has the benefit of updating other properties, like font-size, too.

CSS 媒体查询@mediaCSS 视口单元一起使用vwvh适应视口的纵横比。这有利于更新其他属性,例如font-size

This fiddledemonstrates the fixed aspect ratio for the div, and the text matching its scale exactly.

这个小提琴演示了 div 的固定纵横比,以及与其比例完全匹配的文本。

Initial size is based on full width:

初始大小基于全宽:

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;
}

Then, when the viewport is wider than the desired aspect ratio, switch to height as base measure:

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

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

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

This is very similar in vein to the max-widthand max-heightapproachby @Danield, just more flexible.

这与@Danield的max-widthandmax-height方法非常相似,只是更灵活。

回答by Henry Gibson

My original question for this was how to both have an element of a fixed aspect, but to fit that within a specified container exactly, which makes it a little fiddly. If you simply want an individual element to maintain its aspect ratio it is a lot easier.

我最初的问题是如何使两者都具有固定方面的元素,但要完全将其放入指定的容器中,这使得它有点繁琐。如果您只是想让单个元素保持其纵横比,那就容易多了。

The best method I've come across is by giving an element zero height and then using percentage padding-bottom to give it height. Percentage padding is always proportional to the width of an element, and not its height, even if its top or bottom padding.

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

W3C Padding Properties

W3C 填充属性

So utilising that you can give an element a percentage width to sit within a container, and then padding to specify the aspect ratio, or in other terms, the relationship between its width and height.

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

.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;
}

So in the above example the object takes 80% of the container width, and then its height is 56.25% of that value. If it's width was 160px then the bottom padding, and thus the height would be 90px - a 16:9 aspect.

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

The slight problem here, which may not be an issue for you, is that there is no natural space inside your new object. If you need to put some text in for example and that text needs to take it's own padding values you need to add a container inside and specify the properties in there.

这里有一个小问题,这对您来说可能不是问题,是您的新对象内部没有自然空间。例如,如果您需要放入一些文本并且该文本需要采用它自己的填充值,则您需要在其中添加一个容器并在其中指定属性。

Also vw and vh units aren't supported on some older browsers, so the accepted answer to my question might not be possible for you and you might have to use something more lo-fi.

此外,某些较旧的浏览器不支持 vw 和 vh 单位,因此您可能无法接受我的问题的公认答案,您可能必须使用更多 lo-fi 的东西。

回答by MCSharp

I understand that you asked that you would like a CSSspecific solution. To keep the aspect ratio, you would need to divide the height by the desired aspect ratio. 16:9 = 1.777777777778.

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

To get the correct height for the container, you would need to divide the current width by 1.777777777778. Since you can't check the widthof the container with just CSSor divide by a percentage is CSS, this is not possible without JavaScript(to my knowledge).

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

I've written a working script that will keep the desired aspect ratio.

我编写了一个工作脚本,可以保持所需的纵横比。

HTML

HTML

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

CSS

CSS

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

JavaScript

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);
    }
}

You can use the functionagain if you'd like to display something else with a different ratio by using

function如果您想通过使用以不同的比例显示其他内容,您可以再次使用

keepAspectRatio(id, width, height);

回答by Cameron Martin

Danield's answeris good, but it can only be used when the div fills the whole viewport, or by using a bit of calc, can be used if the width and height of the other content in the viewport is known.

Danield 的回答很好,但它只能在 div 填满整个视口时使用,或者通过使用一点calc, 如果视口中其他内容的宽度和高度已知,则可以使用。

However, by combining the margin-bottomtrick with the method in the aforementioned answer, the problem can be reduced to just having to know the height of the other content. This is useful if you have a fixed height header, but the width of the sidebar, for example, is not known.

但是,通过将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, which makes it more obvious where the values come from.

这里是在 jsfiddle 中使用 scss,这使得值的来源更加明显。

回答by CPHPython

Based on Daniel's answer, I wrote this SASS mixin with interpolation (#{}) for a youtube video's iframe that is inside a Bootstrap modal dialog:

根据Daniel 的回答,我#{}为 Bootstrap 模态对话框内的 youtube 视频 iframe编写了带有插值 ( ) 的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}
  }
}

Usage:

用法:

.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();
}

HTML:

HTML:

<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>

This will always display the video without those black partsthat youtube adds to the iframe when the width or height is not proportional to the video. Notes:

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

  • $sides-adjustmentis a slight adjustment to compensate a tiny part of these black parts showing up on the sides;
  • in very low height devices (< 480px) the standard modal takes up a lot of space, so I decided to:
    1. hide the .modal-footer;
    2. adjust the positioning of the .modal-dialog;
    3. reduce the sizes of the .modal-header.
  • $sides-adjustment是对这些黑色部分的一小部分进行轻微调整以补偿出现在侧面的;
  • 在非常低的设备(< 480px)中,标准模式占用了大量空间,所以我决定:
    1. 隐藏.modal-footer;
    2. 调整定位.modal-dialog
    3. 减小.modal-header.

After a lot of testing, this is working flawlessly for me now.

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

回答by Angel Fraga Parodi

here a solution based on @Danield solution, that works even within a div.

这里是一个基于@Danield 解决方案的解决方案,它甚至可以在 div 中使用。

In that example, I am using Angular but it can quickly move to vanilla JS or another framework.

在那个例子中,我使用的是 Angular,但它可以快速迁移到 vanilla JS 或其他框架。

The main idea is just to move the @Danield solution within an empty iframe and copy the dimensions after iframe window size changes.

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

That iframe has to fit dimensions with its father element.

该 iframe 必须与其父元素匹配尺寸。

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

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

Here a few screenshots:

这里有几个截图:

enter image description here

在此处输入图片说明

enter image description here

在此处输入图片说明

enter image description here

在此处输入图片说明