我想创建一个div,它可以随着窗口宽度的变化而改变宽度/高度。
是否有任何CSS3规则允许高度根据宽度变化,同时保持其纵横比?
我知道我可以通过JavaScript做到这一点,但我更喜欢只使用CSS。
我想创建一个div,它可以随着窗口宽度的变化而改变宽度/高度。
是否有任何CSS3规则允许高度根据宽度变化,同时保持其纵横比?
我知道我可以通过JavaScript做到这一点,但我更喜欢只使用CSS。
当前回答
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 >
其他回答
我们是这样解决的:
.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/
我想分享这一点,因为这是一段令人沮丧的几天的旅程,找到了一个适合我的解决方案。我使用这些填充技术(上面提到过使用一些填充和绝对定位的变化)来为网格/flex布局中的按钮类元素实现1:1的纵横比。布局设置为100vh高,以便始终显示为单个非滚动页面。
填充技术确实工作得很好,但它很容易破坏你的网格布局,并导致爆炸性/讨厌的滚动条。在这种情况下,那些说绝对div不会影响布局的人是错误的,因为父元素在高度和宽度上都在增长,即使子元素没有直接影响布局,父元素也会扰乱你的布局。
通常这不是问题,但在使用网格时需要注意。网格是一个2D布局,它可以在两个轴上考虑大小和布局。我仍然试图理解这的确切性质,但到目前为止,似乎至少如果你在一个网格区域内使用这种技术,在两个轴上都受到fr单位的限制,当纵横比项增长或以其他方式改变布局时,你几乎肯定会遇到井喷(显示:无切换和交换网格区域与css也是布局变化问题,导致我的井喷)。
在我的例子中,我限制了一个不需要的列的高度。将其改为“auto”而不是“1fr”,使我所有的其他布局保持不变,防止井喷,同时仍然让我保持我漂亮的方形按钮!
我不知道这是否是这里每个人沮丧的来源,但这是一个很容易犯的错误,即使使用开发工具也不能让你准确地知道井喷来自哪里,因为在许多情况下,它并不是一个单独的元素井喷出来的情况,而是网格布局扩大自己,以保持那些fr单位在垂直和水平上的准确。
感谢大家的贡献,我将在这里添加我的解决方案,这主要是通过重复已接受的答案来实现的。我喜欢这种方法的主要原因是没有不必要的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
如果你想在纵向视图或横向视图的视口中放置一个正方形(尽可能大,但没有任何东西粘在外面),在纵向/横向方向上切换使用vw/vh:
@media (orientation:portrait ) {
.square {
width :100vw;
height:100vw;
}
}
@media (orientation:landscape) {
.square {
width :100vh;
height:100vh;
}
}
在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());
}
}