仅使用 CSS 实现的正方形 div 适应矩形 div

6

我已经确定了如何基于宽度设置div的高度(使用百分比宽度和padding-bottom)。但是我还需要能够基于div的高度来设置div的宽度。我尝试过使用vw/vm/vh单位,但这些相对于视口而不是容器。

因此,在下面的示例中

<body>
    <div class="rectangle">
        <div class="square">
        </div>
    </div>
</body>

这里有一些只在竖屏模式下工作的不可用CSS代码:
.rectangle {
  background-color:red;
  position:absolute;
  top:0;
  left:0;
  bottom:0;
  right:0;
}

.square {
  background-color:blue;
  width:100%;
  padding-bottom:100%;
}

我希望 .rectangle 能够填满其容器,这意味着随着窗口大小的变化,.rectangle 可能从横向布局变为纵向布局。当发生这种情况时,我希望 .square div 能够尽可能地填充,而不会失去其正方形形状。
因此,如果浏览器窗口比它更宽(横向),则 .rectangle 应该填充整个窗口,.square 应该与 .rectangle 的高度一样高,并且与 .rectangle 的高度一样宽。
如果浏览器窗口比它更高(纵向),则 .rectangle 应该填充整个窗口,.square 应该与 .rectangle 的宽度一样宽,并且与 .rectangle 的宽度一样高。
因此,我可以使用媒体查询在横向和纵向之间切换样式,并且我已经有了解决纵向情况的方法,但我还没有找到解决横向情况的方法。如何使正方形填充其父元素的高度,并限制其宽度以保持正方形的纵横比?

3
需要一些与 CSS 相关的代码吗? - davbuc
有不同的方法不能一起使用。由于我还没有找到解决方案,我的CSS对解决方案并不特别相关。以下是肖像案例的一些可能性:https://dev59.com/u3I_5IYBdhLWcg3wK_zE - rich remer
4个回答

3
您可以:
  • 在正方形内放置一个长宽比为1:1的被替换元素。

    例如,可以是一个1像素×1像素的正方形图像或画布。

    使用 height: 100% 样式来使其垂直地覆盖整个正方形。

    保留默认的 width: auto 样式,以便其宽度遵循1:1的宽高比。

    使用 display: block 样式来避免出现图像下方的额外空间问题

  • 使正方形使用收缩适应宽度算法计算其宽度,以便其也具有1:1的宽高比。

    您可以通过浮动它或使用 display: inline-block 来实现。

  • 如果您希望正方形具有内容,请将其放置在绝对定位的包装器中,以防止其改变正方形的大小。

    使用 top:0; right:0; bottom:0; left:0 让该包装器与正方形大小相同,并将正方形作为其相对容器。

这应该有效。但是,由于某种原因,浏览器在调整窗口大小时似乎不会更新宽度,因此它仅在最初起作用。使用JS强制重新渲染可以解决此问题。

var s = document.getElementById('square'),
    p = s.parentNode,
    n = s.nextSibling;
window.addEventListener('resize', function() {
  // Force a rerender
  p.removeChild(s);
  p.insertBefore(s, n);
});
html, body, #square, canvas {
  height: 100%;
  margin: 0;
  display: block;
}
#square {
  float: left;
  position: relative;
  background: red;
}
#contents {
  overflow: auto;
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}
<div id="square">
  <canvas height="1" width="1"></canvas>
  <div id="contents">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a semper sed, adipiscing id dolor. Pellentesque auctor nisi id magna consequat sagittis. Curabitur dapibus enim sit amet elit pharetra tincidunt feugiat nisl imperdiet. Ut convallis libero in urna ultrices accumsan. Donec sed odio eros. Donec viverra mi quis quam pulvinar at malesuada arcu rhoncus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In rutrum accumsan ultricies. Mauris vitae nisi at sem facilisis semper ac in est.</div>
</div>


我尝试强制重新渲染但没有成功。https://dev59.com/k2ox5IYBdhLWcg3w_ZR0 - rich remer
@richremer 嗯,尝试使用开发者工具取消和重置一些样式似乎起作用了。我会尝试找到一种JS的方法。 - Oriol
哦,我想我知道问题出在哪里了。画布是正方形的,但没有背景颜色。容器在调整大小后不是正方形的,而红色让我感到困惑。 - rich remer
2
好的,我已经包含了重新渲染部分。这很丑,现在我可以使用JS计算与1:1比例相对应的宽度,但无论如何。 - Oriol

1
这最容易实现的方法是让.rectangle占据整个窗口,也就是说,它的宽度和高度分别为100vw100vh
如果是这种情况,那么你的正方形就是:
.square {
    width: 100vh;
    height: 100vh;
    margin: 0 auto;
}
@media all and (orientation: portrait) {
    .square {
        width: 100vw;
        height: 100vw;
    }
}

在纵向视图中垂直居中正方形可能会有些棘手,但绝对不是不可能的。例如,margin-top: calc(50vh - 50vw) 就可以实现这一点。

1
我尝试过使用vw/vm/vh单位,但这些单位是相对于视口而不是容器的。 - rich remer

0
你可以尝试使用jQuery来监听resize事件。查看这个JSFiddle

$(".screen").resizable({});

$(".screen").on("load resize",function(e){
    var rectangle = $(".rectangle");
    var square = $(".square");
    
    var rectWidth = rectangle.width();
    var rectHeight = rectangle.height();
    if(rectWidth < rectHeight){
     square.width(rectWidth);
        square.height(rectWidth);
    }
    else{
     square.width(rectHeight);
        square.height(rectHeight);
    }
});
.screen{
    background: gray;
    width: 100px;
    height: 100px;
}

.rectangle{
    background: blue;
    width: 90%;
    height: 90%;
}

.square{
    background: red;
    width: 30px;
    height: 30px;
}
<div class="screen">
    <div class="rectangle">
        <div class="square">
        </div>
    </div>
</div>

它仅包括JQueryUI以模拟“屏幕”的调整大小。


0
如果您可以使用"min"函数,并且父级元素是矩形,则可以执行以下操作:
.rectangle {
  width: 100vw;
  height: 100vh;
}

.square {
  width: min(80vw, 80vh);
  height: min(80vw, 80vh);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接