我想创建一个div,它可以随着窗口宽度的变化而改变宽度/高度。

是否有任何CSS3规则允许高度根据宽度变化,同时保持其纵横比?

我知道我可以通过JavaScript做到这一点,但我更喜欢只使用CSS。


当前回答

我想分享这一点,因为这是一段令人沮丧的几天的旅程,找到了一个适合我的解决方案。我使用这些填充技术(上面提到过使用一些填充和绝对定位的变化)来为网格/flex布局中的按钮类元素实现1:1的纵横比。布局设置为100vh高,以便始终显示为单个非滚动页面。

填充技术确实工作得很好,但它很容易破坏你的网格布局,并导致爆炸性/讨厌的滚动条。在这种情况下,那些说绝对div不会影响布局的人是错误的,因为父元素在高度和宽度上都在增长,即使子元素没有直接影响布局,父元素也会扰乱你的布局。

通常这不是问题,但在使用网格时需要注意。网格是一个2D布局,它可以在两个轴上考虑大小和布局。我仍然试图理解这的确切性质,但到目前为止,似乎至少如果你在一个网格区域内使用这种技术,在两个轴上都受到fr单位的限制,当纵横比项增长或以其他方式改变布局时,你几乎肯定会遇到井喷(显示:无切换和交换网格区域与css也是布局变化问题,导致我的井喷)。

在我的例子中,我限制了一个不需要的列的高度。将其改为“auto”而不是“1fr”,使我所有的其他布局保持不变,防止井喷,同时仍然让我保持我漂亮的方形按钮!

我不知道这是否是这里每个人沮丧的来源,但这是一个很容易犯的错误,即使使用开发工具也不能让你准确地知道井喷来自哪里,因为在许多情况下,它并不是一个单独的元素井喷出来的情况,而是网格布局扩大自己,以保持那些fr单位在垂直和水平上的准确。

其他回答

我想分享这一点,因为这是一段令人沮丧的几天的旅程,找到了一个适合我的解决方案。我使用这些填充技术(上面提到过使用一些填充和绝对定位的变化)来为网格/flex布局中的按钮类元素实现1:1的纵横比。布局设置为100vh高,以便始终显示为单个非滚动页面。

填充技术确实工作得很好,但它很容易破坏你的网格布局,并导致爆炸性/讨厌的滚动条。在这种情况下,那些说绝对div不会影响布局的人是错误的,因为父元素在高度和宽度上都在增长,即使子元素没有直接影响布局,父元素也会扰乱你的布局。

通常这不是问题,但在使用网格时需要注意。网格是一个2D布局,它可以在两个轴上考虑大小和布局。我仍然试图理解这的确切性质,但到目前为止,似乎至少如果你在一个网格区域内使用这种技术,在两个轴上都受到fr单位的限制,当纵横比项增长或以其他方式改变布局时,你几乎肯定会遇到井喷(显示:无切换和交换网格区域与css也是布局变化问题,导致我的井喷)。

在我的例子中,我限制了一个不需要的列的高度。将其改为“auto”而不是“1fr”,使我所有的其他布局保持不变,防止井喷,同时仍然让我保持我漂亮的方形按钮!

我不知道这是否是这里每个人沮丧的来源,但这是一个很容易犯的错误,即使使用开发工具也不能让你准确地知道井喷来自哪里,因为在许多情况下,它并不是一个单独的元素井喷出来的情况,而是网格布局扩大自己,以保持那些fr单位在垂直和水平上的准确。

2022解决方案-使用CSS的纵横比属性

<div class='demo'></div>
.demo {
  background: black;
  width: 500px;
  aspect-ratio: 4/3;
}

更新:现在所有常绿浏览器都支持这个解决方案

这是对公认答案的改进:

使用伪元素而不是包装器div 长宽比基于盒子的宽度,而不是它的父元素 当内容变高时,盒子会垂直拉伸

.box { margin-top: 1 em; margin-bottom: 1 em; background - color: # CCC; } {前.fixed-ar:: 内容:“”; 浮:左; 宽度:1 px; margin-left: 1 px; } {后.fixed-ar:: 内容:“”; 显示:表; 明确:; } {前.fixed-ar-16-9:: padding-top: 56.25%; } {前.fixed-ar-3-2:: padding-top: 66.66%; } {前.fixed-ar-4-3:: padding-top: 75%; } {前.fixed-ar-1-1:: padding-top: 100%; } .width-50 { 显示:inline-block; 宽度:50%; } .width-20 { 显示:inline-block; 宽度:20%; } <div class="box - fixed-ar- ar-16-9">16:9 full width</div> <人力资源> <div class="box - fixed-ar- ar-16-9 width-50">16:9</div> <人力资源> <div class="box - fixed-ar- ar-16-9 width-20">16:9</div> <div class="box - fixed-ar-3-2 width-20">3:2</div> <div class="box - fixed-ar-4-3 width-20">4:3</div> <div class="box - fixed-ar-1-1 width-20">1:1</div> <人力资源> <div class="box - fixed-ar- ar-16-9 width-20">16:9</div> <div class="box - fixed-ar- ar-16-9 width-50">16:9</div>

感谢大家的贡献,我将在这里添加我的解决方案,这主要是通过重复已接受的答案来实现的。我喜欢这种方法的主要原因是没有不必要的DOM,因为我在填充之前使用:。

@card-standard-line-height: 21px;
@card-standard-title-line-height: 22.5px;
@16to9percentage: 56.25%;

.overflow {
  background-color: inherit;
  /* stylelint-disable property-no-unknown */
  box-orient: vertical;
  -moz-box-orient: vertical;
  -webkit-box-orient: vertical;
  /* stylelint-enable */
  color: inherit;
  display: box;
  display: -webkit-box;
  display: -moz-box;
  max-width: 100%;
  overflow: hidden;
  position: relative;
  text-overflow: -o-ellipsis-lastline;
  text-overflow: ellipsis;
}

* {
  box-sizing: border-box;
}

body {
  padding: 2rem;
}

.card {
  color: #fff;
  height: auto;
  max-width: 100%;
  min-width: unset;
  position: relative;
  
  h2 {
    font: 18px / 22.5px bold;
  }
  
  p {
    font: 14px / 21px normal;
  }

  &-16to9 {
    .badge {
      color: white;
      display:flex;
      background-color: red;
      justify-content: baseline;
      padding: 16px 32px 12px 16px;
      position: absolute;
      right: 0;
      top: 16px;
      z-index: 2;
      span {
        font: 14px / 14px bold;
      }
    }
    // look at this https://css-tricks.com/aspect-ratio-boxes/
    .card {
      &_description {
        max-height: @card-standard-line-height * 1;
        // Number of allowable lines in layout
        -webkit-line-clamp: 1;
      }

      &_image,
      &_info {
        bottom: 0;
        height: 100%;
        max-height: 100%;
        min-height: 100%;
        left: 0;
        position: absolute;
        right: 0;
        top: 0;
        z-index: 0;
      }

      &_info {
        display: flex;
        flex-direction: column;
        justify-content: flex-end;
        padding: 24px;
        z-index: 2;
      }

      &_title {
        max-height: @card-standard-title-line-height * 2;
        // Number of allowable lines in layout
        -webkit-line-clamp: 2;
      }
    }

    &:after,
    &:before {
      content: "";
      display: block;
    }

    &:after {
      background: rgba(0, 0, 0, 0);
      background: linear-gradient(0deg, rgba(0, 0, 0, 1) 16%, rgba(0, 0, 0, 0) 100%);
      bottom: 0;
      height: 100%;
      left: 0;
      position: absolute;
      right: 0;
      top: 0;
      z-index: 1;
    }

    &:before {
      padding-bottom: @16to9percentage;
    }
  }
}

https://codepen.io/augur/pen/GRNGLZv?editors=0100

实际上,高投票的答案是一个非常好的解决方案,但有一个新的CSS功能,名字是长宽比。

它可以这样使用:

.someClass {
  width: 100%;
  aspect-ratio: 4/3;
}

自动确定高度,但请参见兼容性表:

如果浏览器支持对你的项目很重要,不要使用它。使用填充底技术。