我想创建一个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(朝向:横向) 媒体查询肖像/风景改变比例。

其他回答

新的纵横比标签会很棒,但它打乱了我的divs的定位。 填充包装器div的传统解决方案是有效的,但只能根据父类或视口的宽度调整大小,当高度是限制因素时,这就产生了问题。

我发现min()函数非常有用,并调整了传统的方法,如下所示:

身体{ background-image: linear-gradient(到右上,#FFE6B5, #B3CEBF); 填充:0; 保证金:0自动; overflow-y:隐藏;/*这是为了避免在视口高度小于纵横比要求*/时滚动 } .wrapper { 位置:相对; 宽度:100大众; max-height: 100 vh; } .sixteen-by-nine。宽高比{ 衬底:56.25% /* 9:16比*/ } .content { 位置:绝对的; 上图:0;底部:0;左:0;右:0; 背景颜色:绿色 } .centered { 位置:绝对的; 左:50%; 上图:50%; 转换:翻译(-50%,-50%); 高度:100%; 宽度:min(177.8vh, 100%);/*这总是在视口中保持16:9的比例*/ 字体大小:最小(1.7 3 vh,大众);/*如果你也对缩放字体大小*/感兴趣 背景颜色:蓝色 } 身体< > < div class = "包装" > <div class=" 16x9纵横比"></div> <div class="content" > < div class = "集中" > <!——东西在这里——> < / div > < / div > < / div > 身体< / >

在Angular中,我添加了一个处理纵横比的指令。

import { AfterViewInit, Directive, ElementRef, Input, Renderer2 } from 
"@angular/core";
import { debounceTime, fromEvent, Subject, takeUntil } from "rxjs";
 
// Auto sets the height of element based on width. Also supports window resize
@Directive({
    selector: '[aspectRatio]'
})
export class AspectRatioDirective implements AfterViewInit {
    @Input() aspectRatio?: number; // example 9/16

    private readonly onDestroy$ = new Subject<void>();

    constructor(private element: ElementRef, private renderer: Renderer2) {}

    public ngAfterViewInit(): void {
        this.setDimensions();
        this.initResizeListeners();
    }

    public ngOnDestroy(): void {
        this.onDestroy$.next();
        this.onDestroy$.complete();
      }

    private setDimensions(): void {
        if (!this.aspectRatio) { return; }
        const width = this.element.nativeElement.clientWidth;
        this.renderer.setStyle(this.element.nativeElement, 'height', `${width * this.aspectRatio}px`);
    }

    private initResizeListeners(): void {
        fromEvent(window, 'resize')
          .pipe(debounceTime(100), takeUntil(this.onDestroy$))
          .subscribe(() => this.setDimensions());
      }
}

只需创建一个包装器<div>,并为padding-bottom设置一个百分比值,如下所示:

.demoWrapper { 填充:10 px; 背景:白色; box-sizing: border-box; 调整:水平; 边框:1px虚线; 溢出:汽车; max-width: 100%; 高度:calc(100vh - 16px); } div { 宽度:100%; padding-bottom: 75%; 背景:黄金;/** <——用于演示**/ } < div class = " demoWrapper”> < div > < / div > < / div >

它将生成一个<div>,其高度等于其容器宽度的75%(4:3长宽比)。

这依赖于以下事实:

百分比是根据生成的盒子的包含块的宽度计算的[…](来源:w3.org,重点是我的)

其他纵横比和100%宽度的填充底部值:

aspect ratio  | padding-bottom value
--------------|----------------------
    16:9      |       56.25%
    4:3       |       75%
    3:2       |       66.66%
    8:5       |       62.5%

在div中放置内容:

为了保持div的纵横比并防止它的内容被拉伸,你需要添加一个绝对定位的子元素,并将其拉伸到包装器的边缘:

div.stretchy-wrapper {
  position: relative;
}

div.stretchy-wrapper > div {
  position: absolute;
  top: 0; bottom: 0; left: 0; right: 0;
}

这里有一个演示和另一个更深入的演示

感谢大家的贡献,我将在这里添加我的解决方案,这主要是通过重复已接受的答案来实现的。我喜欢这种方法的主要原因是没有不必要的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来做到这一点的方法,但你必须小心,因为它可能会根据你自己网站的流程而变化。我这样做是为了在我的网站的流体宽度部分中嵌入具有恒定长宽比的视频。

假设你有一个这样的嵌入视频:

<object>
     <param ... /><param ... />...
     <embed src="..." ...</embed>
</object>

然后你可以把这些都放在一个带有“video”类的div中。这个视频类可能是你网站中的流动元素,它本身没有直接的高度限制,但当你调整浏览器的大小时,它会根据网站的流量改变宽度。这可能是你想要嵌入视频的元素,同时保持一定的视频宽高比。

为了做到这一点,我在“video”类div中的嵌入对象之前放了一张图像。

! !重要的部分是图像具有您希望保持的正确长宽比。此外,确保图像的大小至少与你期望的视频(或你正在维护的A.R.)根据你的布局得到的最小尺寸一样大。这将避免在调整百分比大小时图像分辨率中的任何潜在问题。例如,如果你想保持3:2的纵横比,不要只使用3px * 2px的图像。它在某些情况下可能会工作,但我还没有测试过,避免使用它可能是个好主意。

您可能已经为网站的流体元素定义了这样的最小宽度。如果没有,那么这样做是一个好主意,以避免在浏览器窗口变得太小时删除元素或出现重叠。在某些地方最好有一个滚动条。一个网页的最小宽度应该在600px左右(包括任何固定宽度的列),因为屏幕分辨率不能再小了,除非你处理的是手机友好型网站。! !

我使用一个完全透明的png,但我真的不认为它最终是重要的,如果你做得对。是这样的:

<div class="video">
     <img class="maintainaspectratio" src="maintainaspectratio.png" />
     <object>
          <param ... /><param ... />...
          <embed src="..." ...</embed>
     </object>
</div>

现在你应该能够添加类似于下面的CSS:

div.video { ...; position: relative; }
div.video img.maintainaspectratio { width: 100%; }
div.video object { position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; }
div.video embed {width: 100%; height: 100%; }

确保您还删除了对象和嵌入标记中任何显式的高度或宽度声明,这些标记通常带有复制/粘贴嵌入代码。

它的工作方式取决于视频类元素的位置属性和你想要的项目保持一定的纵横比。它利用了图像在元素中调整大小时保持适当长宽比的方法。它告诉视频类元素中的任何其他元素,通过强制其宽度/高度为图像所调整的视频类元素的100%来充分利用动态图像提供的空间。

很酷,是吧?

您可能需要稍微摆弄一下才能让它与您自己的设计一起工作,但这实际上对我来说工作得非常好。大概的概念是这样的。