如何在 flex div 中使 canvas 宽度和高度被包含?

3

简而言之:这里有一个完整的页面示例:https://jsfiddle.net/rfp8xv6g/show(可在此处进行编辑:https://jsfiddle.net/rfp8xv6g),如何使画布(带有紫色边框)在垂直方向上完全包含在容器中,而不需要硬编码高度?


这里有一个简化的例子。我有以下布局(在片段中点击“全屏”以查看它)。

左列包含一个包含多个<canvas>的包装器,这些画布彼此叠放(这里仅为简单起见只有一个画布)。

问题:如果画布的宽度/高度很高(在画布坐标系中,这里是4000x3000),则完整的画布不可见(高度太高,超出了视口)。

如何使画布缩放/收缩以包含在左列中?(没有页面垂直滚动条)

这里max-width: 100%; 可以用于水平包含画布。

但是max-height: 100%;没有任何效果:画布在垂直方向上没有被包含,为什么?

* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

html,
body, 
.page {
  height: 100%;
  width: 100%;
}

.page {
  background-color: red;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}

.left-column {
  background-color: green;
  display: flex;
}

.right-column {
  background-color: orange;
  flex: 1;
}

canvas {
  border: 3px solid magenta;
  max-width: 100%;
  max-height: 100%;
}
<div class="page">
  <div class="left-column">
    <div class="canvas-wrapper">
      <canvas width="4000" height="3000"></canvas>
    </div>
  </div>
  <div class="right-column">
    RIGHT
  </div>
</div>


你是否在寻找一个仅使用 CSS 的解决方案? - obscure
@obscure 是的,最好这样。 - Basj
@obscure 这是一个完整的示例:https://jsfiddle.net/rfp8xv6g/show - Basj
2个回答

2
如果您希望canvas适应弹性元素的高度,则不需要在弹性容器中指定align-items: center;值。或者您需要向弹性元素添加align-self: stretch;
您还可以使用flexbox来居中画布容器。
实际上,解决您问题的所有代码都归结为:
.zone-left-column {
  align-self: stretch;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.canvas-wrapper {
  min-height: 0;
}

以下是一个完整的示例:

* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

html,
body,
.page {
  height: 100%;
}

.page {
  max-width: 70rem;
  margin: 0 auto;
  padding: 1rem;
  display: flex;
  flex-direction: column;
  background-color: yellow;
}

.toolbar {
  background-color: rgba(200, 200, 200, 0.5);
  margin-bottom: 1rem;
  display: flex;
  align-items: center;
  justify-content: space-around;
  flex: 0 0 5rem;
}

.container {
  background-color: red;
  flex: 1;
  overflow: hidden;
  gap: 2rem;
}

.flex-horizontal {
  display: flex;
  justify-content: center;
  align-items: center;
}

.zone-left-column {
  background-color: green;
  /* add  */
  align-self: stretch;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.canvas-wrapper {
  background-color: rgba(255, 255, 255, .4);
  /* must have  */
  min-height: 0;
}

canvas {
  border: 3px solid magenta;
  max-width: 100%;
  max-height: 100%;
  display: block;
}

.zone-right-column {
  background-color: orange;
  flex: 1;
  border: 1px solid black;
}
<div class="page">
  <div class="toolbar">
    TOOLBAR
  </div>
  <div class="container flex-horizontal">
    <div class="zone-left-column">
      <div class="canvas-wrapper">
        <canvas width="2000" height="1500"></canvas>
      </div>
    </div>
    <div class="zone-right-column">
      RIGHT
    </div>
  </div>
</div>


1
非常感谢!我看到它起作用了,但我不知道为什么:min-height: 0为什么很重要,它确切地做了什么? - Basj
感谢选择我的答案,很高兴能帮到你。min-height: 0; 是必需的,这样元素才能收缩,因为默认情况下当 overflow: visible; 时,它的值被设置为 min-height: auto;。你也可以将元素的 overflow 值更改为除了 visible 之外的任何其他值。Flex 元素的自动最小尺寸 - imhvost
我仍在努力理解为什么min-height会使其子元素成为其“祖父母”的100%高度,但它确实能够完成工作。 - Salman A
@Salman A 我在之前的评论中提供了规范的链接。也许 min-height 在这里有点令人困惑,因为我们的主轴来自于 flex-direction: column;。这里是一个 flex-direction: row; 的例子:codepen 最好的问候!✌️ - imhvost

0

当元素具有百分比高度时,父元素必须有一个定义好的高度。

如果父元素没有定义好的高度,则百分比高度将简单地解析为 auto

这里是完整的解释:

你至少有两个可用的解决方案:

  1. 在父元素(.canvas-wrapper)上定义高度或者更好的做法是

  2. 使用视口百分比单位 (例如,vh)而不是百分比单位%)。

对你的代码进行一个调整:

canvas {
  border: 3px solid magenta;
  max-width: 100%;
  /* max-height: 100%; */
   max-height: 100vh; /* new */
}

* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

html,
body, 
.page {
  height: 100%;
  width: 100%;
}

.page {
  background-color: red;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}

.left-column {
  background-color: green;
  display: flex;
}

.right-column {
  background-color: orange;
  flex: 1;
}

canvas {
  border: 3px solid magenta;
  max-width: 100%;
  /* max-height: 100%; */
   max-height: 100vh; /* new */
}
<div class="page">
  <div class="left-column">
    <div class="canvas-wrapper">
      <canvas width="4000" height="3000"></canvas>
    </div>
  </div>
  <div class="right-column">
    RIGHT
  </div>
</div>


这是全屏版本:https://jsfiddle.net/rfp8xv6g/show - Basj
1
使用 calc() 函数:max-height: calc(100vh - 8rem)(即完整高度减去工具栏的高度 (5rem),再减去内边距和外边距 (3em))。https://jsfiddle.net/yfwvnbu6/ - Michael Benjamin
1
请添加以下内容:.canvas-wrapper { display: flex; align-items: center } - Michael Benjamin
1
感谢您的帮助@MichaelBenjamin!这是更新,包含您最后一条评论的链接:https://gget.it/0bdc/page7.html。(当我们放大时仍然存在一些问题,但我认为通过另一种方法解决了这个问题,请参见我链接的SO问题)。再次感谢您的帮助。 - Basj
1
@Michael Benjamin,请允许我稍微不同意您的观点。在父元素上直接设置高度并非必要。父元素可以是灵活的。此外,根据此链接min-height也并非如此清晰明了。 - imhvost
显示剩余10条评论

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