首页 文章

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

提问于
浏览
93

我有一个网站,它有一个固定的宽高比约为 16:9 景观,就像一个视频 .

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

For example:

  • 高而薄的页面将使内容伸展整个宽度,同时保持比例高度 .

  • 一个短的宽页面将使内容延伸到整个高度,并具有成比例的宽度 .


我一直在研究两种方法:

  • 使用具有正确宽高比的图像来扩展容器 div ,但我无法让它在主要浏览器中以相同的方式运行 .

  • 设置比例底部填充,但仅相对于宽度有效并忽略高度 . 它随着宽度不断变大,并显示垂直滚动条 .


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

有任何想法吗?

8 回答

  • 5

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

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

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

  • 0

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

    然而,通过将 margin-bottom 技巧与前述答案中的方法相结合,可以将问题简化为仅需要知道其他内容的高度 . 如果你有一个固定的高度 Headers ,这很有用例如,侧边栏的宽度是未知的 .

    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,这使得 Value 来自哪里更加明显 .

  • 6

    使用新的CSS viewport units 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!

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

  • 0

    只需在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;
    }
    
  • 16

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

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

    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单元,因此我可能无法接受我的问题的答案,你可能不得不使用更低级的东西 .

  • 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非常相似,更加灵活 .

  • 1

    我知道你问过你想要一个 CSS 特定的解决方案 . 要保持纵横比,您需要将高度除以所需的纵横比 . 16:9 = 1.777777777778 .

    要获得容器的正确高度,您需要将当前宽度除以1.777777777778 . 由于您无法仅使用 CSS 检查容器的 width 或除以百分比 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);
    
  • 232

    基于Daniel's answer,我为一个在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}
      }
    }
    

    用法:

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

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

    当宽度或高度与视频不成比例时,这将始终显示youtube添加到iframe的视频 without those black parts . 笔记:

    • $sides-adjustment 是一个微小的调整,以补偿这些黑色部分的两侧出现的一小部分;

    • 在非常低的设备(<480px)中,标准模态占用了大量空间,所以我决定:

    • 隐藏 .modal-footer ;

    • 调整 .modal-dialog 的定位;

    • 减小 .modal-header 的大小 .

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

相关问题