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

其他回答

在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 { 背景颜色:蓝色; 宽度:10%; 过渡:底色0.5s,宽度0.5s; 字体大小:0; } div:{徘徊 宽度:20%; 背景颜色:红色; } img { 宽度:100%; 高度:汽车; 可见性:隐藏; } < div > <!—使用具有目标纵横比的图像。样本是一个正方形——> <img src="http://i.imgur.com/9OPnZNk.png" /> < / div >

为了补充Web_Designer的答案,<div>的高度(完全由底部填充组成)将是其包含元素宽度的75%。这里有一个很好的总结:http://mattsnider.com/css-using-percent-for-margin-and-padding/。我不知道为什么会这样,但事实就是这样。

如果你想让你的div的宽度不是100%,你需要另一个包装div来设置宽度:

div.ar-outer{
    width: 60%; /* container; whatever width you want */
    margin: 0 auto; /* centered if you like */
}
div.ar {
    width:100%; /* 100% of width of container */
    padding-bottom: 75%; /* 75% of width of container */
    position:relative;
}
div.ar-inner {
    position: absolute;
    top: 0; bottom: 0; left: 0; right: 0;
}

我最近使用了类似于Elliot的图像技巧,允许我使用CSS媒体查询来根据设备分辨率提供不同的logo文件,但仍然按照<img>自然会做的比例缩放(我将logo作为背景图像设置为具有正确纵横比的透明。png)。但是Web_Designer的解决方案将为我节省一个http请求。

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

由于@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(朝向:横向) 媒体查询肖像/风景改变比例。