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

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

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


当前回答

由于@web-tiki已经展示了一种使用vh/vw的方法,我还需要一种方法在屏幕中心,这里是9:16人像的代码片段。

.container {
  width: 100vw;
  height: calc(100vw * 16 / 9);
  transform: translateY(calc((100vw * 16 / 9 - 100vh) / -2));
}

translateY会保持这个中心在屏幕上。Calc (100vw * 16 / 9)预计高度为9/16。(100vw * 16 / 9 - 100vh)为溢流高度,因此,拉升溢流高度/2将使其保持在屏幕中心。

为风景,并保持16:9,你显示使用

.container {
  width: 100vw;
  height: calc(100vw * 9 / 16);
  transform: translateY(calc((100vw * 9 / 16 - 100vh) / -2));
}

9/16的比例很容易改变,不需要预定义100:56.25或100:75。如果你想先保证高度,你应该切换宽度和高度,例如:高度:100vh;宽度:calc(100vh * 9 / 16) 9:16纵向。

如果你想适应不同的屏幕尺寸,你可能也会感兴趣

background-size封面/包含 上面的样式类似于包含,取决于宽高比。 object-fit img/video标签的封面/包含 @media(朝向:纵向)/@media(朝向:横向) 媒体查询肖像/风景改变比例。

其他回答

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

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

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

感谢大家的贡献,我将在这里添加我的解决方案,这主要是通过重复已接受的答案来实现的。我喜欢这种方法的主要原因是没有不必要的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

我们是这样解决的:

.square {
  width: 100%;
  max-height: 100%;
  aspect-ratio: 1;
  background: red;
  position: relative;
  margin: auto;
  top: 50%;
  transform: translateY(-50%);
}

参见https://jsfiddle.net/r1jL3oqa/1/

2020解决方案-使用网格和填充伪元素

我找到了一些更新颖的方法来破案。该解决方案是any填充底部方法的后代,但没有任何位置:绝对子方法,只使用display: grid;和伪元素。

这里我们有。ratio::before,填充底部:XX%,网格区域:1 / 1 / 1 / 1;,这迫使伪元素保持在网格中的位置。虽然这里我们有width: 0;为了防止主元素被这个索引溢出(我们在这里冷地使用z-index,但是这个索引更短)。

我们的主元素。ratio > *:first-child与。ratio::之前的位置相同,即grid-area: 1 / 1 / 1 / 1;,因此它们共享相同的网格单元格位置。现在我们可以在div中放入任何内容,而pseudo元素是决定宽高比的元素。更多关于网格区域。

.ratio { 显示:网格; grid-template-columns: 1 fr; max-width: 200 px;例如,/*可以是100%,取决于父*/ } {前.ratio:: 内容:”; 宽度:0; 填充底:calc(100% / (16/9));/*在这里你可以放置任何比例*/ 网格面积:1 / 1 / 1 / 1; } .ratio > *:第一个孩子{ 网格面积:1 / 1 / 1 / 1;/*与*/前的::相同 背景:rgba(0,0,0,0.1);例如*/ } < div class = "比" > 16/9 < div > < / div > < / div >


虽然你可以使用cssval并使用样式属性将比值放在HTML中。工作与显示:内联网格以及。

.ratio { 显示:inline-grid; grid-template-columns: 1 fr; 宽度:200 px;例如,/*可以是100%,取决于父*/ margin-right: 10 px;例如*/ } {前.ratio:: 内容:”; 宽度:0; 填充底部:calc(100% / (var(—r)));/*在这里你可以放置任何比例*/ 网格面积:1 / 1 / 1 / 1; } .ratio > *:第一个孩子{ 网格面积:1 / 1 / 1 / 1;/*与*/前的::相同 背景:rgba(0,0,0,0.1);例如*/ } <div class="ratio" style="——r: 4/3;"> < div > 4/3 < / div > < / div > <div class="ratio" style="——r: 16/9;"> 16/9 < div > < / div > < / div >

艾略特启发我想出了这个解决方案——谢谢:

png是一个完全透明的png文件,大小和你喜欢的纵横比一样,在我的例子中是30x10像素。

HTML

<div class="eyecatcher">
  <img src="/img/aspectratio.png"/>
</div>

CSS3

.eyecatcher img {
  width: 100%;
  background-repeat: no-repeat;
  background-size: 100% 100%;
  background-image: url(../img/autoresized-picture.jpg);
}

请注意:background-size是css3特性,可能不适用于你的目标浏览器。你可以检查互操作性(f.e.在caniuse.com)。