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

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

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


当前回答

假设你有2个div,外部的div是一个容器,内部的div可以是你需要保持其比例的任何元素(img或YouTube iframe或其他)

HTML看起来是这样的:

<div class='container'>
  <div class='element'>
  </div><!-- end of element -->
<div><!-- end of container -->

比如说你需要保持元素的比例 比例=> 4比1或2比1…

CSS是这样的

.container{
  position: relative;
  height: 0
  padding-bottom : 75% /* for 4 to 3 ratio */ 25% /* for 4 to 1 ratio ..*/
  
}

.element{
  width : 100%;
  height: 100%;
  position: absolute; 
  top : 0 ;
  bottom : 0 ;
  background : red; /* just for illustration */
}

当在%中指定填充时,它是基于宽度而不是高度计算的。 .. 所以基本上,不管你的宽是多少,高总是以此为基础计算出来的。这样就能保持比例不变。

其他回答

我想只是使用rem或em应该解决固定比例的问题,但不会像vw或vh那样难以绑定到屏幕上,或者像%那样痛苦地使用flexbox。好吧,没有一个答案适合我,在我的情况下,这对我来说很重要:

<div class="container">
   <div>
   </div>
</div>
.container {
   height: 100vh;
   width: 100vw;
}
.container div {
   height: 4em;
   width: 3em;
}

或者用rem,但是不管怎样,它们中的任何一个都可以。 Rem使用默认的字体大小值,而em使用最接近的字体大小。

我是这样做的:

[data-aspect-ratio] {
    display: block;
    max-width: 100%;
    position: relative;
}

[data-aspect-ratio]:before {
    content: '';
    display: block;
}

[data-aspect-ratio] > * {
    display: block;
    height: 100%;
    left: 0;
    position: absolute;
    top: 0;
    width: 100%;
}
[data-aspect-ratio="3:1"]:before {
    padding-top: 33.33%;
}
[data-aspect-ratio="2:1"]:before {
    padding-top: 50%;
}
[data-aspect-ratio="16:9"]:before {
    padding-top: 56.25%;
}
[data-aspect-ratio="3:2"]:before {
    padding-top: 66.66%;
}
[data-aspect-ratio="4:3"]:before {
    padding-top: 75%;
}
[data-aspect-ratio="1:1"]:before {
    padding-top: 100%;
}
[data-aspect-ratio="3:4"]:before {
    padding-top: 133.33%;
}
[data-aspect-ratio="2:3"]:before {
    padding-top: 150%;
}
[data-aspect-ratio="9:16"]:before {
    padding-top: 177.77%;
}
[data-aspect-ratio="1:2"]:before {
    padding-top: 200%;
}
[data-aspect-ratio="1:3"]:before {
    padding-top: 300%;
}

例如:

<div data-aspect-ratio="16:9"><iframe ...></iframe></div>

保持纵横比的一个简单方法,使用canvas元素。

尝试调整下面的div的大小,看看它的作用。

对我来说,这种方法效果最好,所以我把它分享给其他人,这样他们也能从中受益。

.cont { 边框:5px纯蓝色; 位置:相对; 宽度:300 px; 填充:0; 保证金:5 px; 调整:水平; 溢出:隐藏; } .ratio { 宽度:100%; 保证金:0; 显示:块; } .content { Background-color: rgba(255, 0,0, 0.5); 位置:绝对的; 上图:0; 左:0; 宽度:100%; 高度:100%; 保证金:0; } < div class = "跟" > <canvas class="ratio" width="16" height="9"></canvas> <div class="content">我是16:9</div> < / div >

也适用于动态高度!

.cont { 边框:5px纯蓝色; 位置:相对; 身高:170 px; 填充:0; 保证金:5 px; 调整:垂直; 溢出:隐藏; 显示:inline-block;/*所以div不会自动扩展到最大宽度*/ } .ratio { 高度:100%; 保证金:0; 显示:块; } .content { Background-color: rgba(255, 0,0, 0.5); 位置:绝对的; 上图:0; 左:0; 宽度:100%; 高度:100%; 保证金:0; } < div class = "跟" > <canvas class="ratio" width="16" height="9"></canvas> <div class="content">我是16:9</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)。

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