首页 > 解决方案 > 画布(甚至 svg)上的 CSS 最小高度有限制吗?

问题描述

用例

假设您有两个<div>嵌套的 flex(一个用于列,另一个用于行),以获得类似:

在此处输入图像描述

<div>您可以在任何方向调整 parent的大小,并且一切都按预期工作。

注意<div>定义为

{
   /* flex: 1 1 0px */
   flex-grow: 1
   flex-shrink: 1
   flex-basis: 0px /* i.e. independant of content */
}

<html>
<style type="text/css">
  html,
  body {
    height: 100%;
    margin: 0px;
  }
  
  body {
    padding-left: 30px
  }
  
  span {
    display: block;
    margin-top: 30px
  }
  
  #dut {
    background-color: red;
  }
</style>

<body>
  <span id="info"></span>
  <div style="
        background-color: gray;
        height: 200px;
        width: 50%;
        resize: both;
        overflow: auto;" onresize="onResize()">

    <div style="
            height:100%;
            display:flex;
            flex-direction: column;
        ">

      <div style="
            flex: 1 1 0px;
            display:flex;
            flex-direction: row;
            ">
        <div style="flex: 1 1 0px; background-color: chocolate;"></div>
        <div style="flex: 1 1 0px; background-color: gray;"></div>
        <div style="flex: 1 1 0px; background-color: chocolate;"></div>
        <div style="flex: 1 1 0px; background-color: gray;"></div>
      </div>

      <div style="
            flex: 1 1 0px;
            display:flex;
            flex-direction: row;
            ">
        <div style="flex: 1 1 0px; background-color: gray;"></div>
        <div id="dut" style="flex: 1 1 0px;"></div>
        <div style="flex: 1 1 0px; background-color: gray;"></div>
        <div style="flex: 1 1 0px; background-color: chocolate;"></div>
      </div>

    </div>
  </div>

  <script>
    const dut = window.document.getElementById("dut");
    const info = window.document.getElementById("info");
    const cb = () => info.innerHTML = `size of RED element: ${dut.offsetWidth} x ${dut.offsetHeight}`
    new ResizeObserver(cb).observe(dut)
  </script>
</body>

</html>

我开始困惑的地方......

如果您采用一个<div>元素(标记为“dut”的红色元素),并将其替换为<canvas>您将得到:

在此处输入图像描述

换句话说,红色元素不能在“300x150”下缩小

我们应该能够用min-heightand min-width它早于 flex 计算)来解决这个问题:

{
    background-color: red;
    min-width: 0;
    min-height: 0;
}

结果:

在此处输入图像描述

width现在是正确的,但为什么不是高度?!

<html>
<style type="text/css">
  html,
  body {
    height: 100%;
    margin: 0px;
  }
  
  body {
    padding-left: 30px
  }
  
  span {
    display: block;
    margin-top: 30px
  }
  
  #dut {
    background-color: red;
    min-width: 0;
    min-height: 0;
  }
</style>

<body>
  <span id="info"></span>
  <div style="
        background-color: gray;
        height: 200px;
        width: 50%;
        resize: both;
        overflow: auto;" onresize="onResize()">

    <div style="
            height:100%;
            display:flex;
            flex-direction: column;
        ">

      <div style="
            flex: 1 1 0px;
            display:flex;
            flex-direction: row;
            ">
        <div style="flex: 1 1 0px; background-color: chocolate;"></div>
        <div style="flex: 1 1 0px; background-color: gray;"></div>
        <div style="flex: 1 1 0px; background-color: chocolate;"></div>
        <div style="flex: 1 1 0px; background-color: gray;"></div>
      </div>

      <div style="
            flex: 1 1 0px;
            display:flex;
            flex-direction: row;
            ">
        <div style="flex: 1 1 0px; background-color: gray;"></div>
        <canvas id="dut" style="flex: 1 1 0px;"></canvas>
        <div style="flex: 1 1 0px; background-color: gray;"></div>
        <div style="flex: 1 1 0px; background-color: chocolate;"></div>
      </div>

    </div>
  </div>

  <script>
    const dut = window.document.getElementById("dut");
    const info = window.document.getElementById("info");
    const cb = () => info.innerHTML = `size of RED element: ${dut.offsetWidth} x ${dut.offsetHeight}`
    new ResizeObserver(cb).observe(dut)
  </script>
</body>

</html>

所以为什么 ?

我正在考虑一堆解决方法(或多或少丑陋),但我的问题更多是关于这种行为的根本原因是什么?那里有另一个 css 标签,比如min-min-height?!?

我注意到min-min-height在我的情况下等于 150 像素实际上取决于您的浏览器,以及画布的height属性(并且将与viewBox属性有关<svg>

谢谢 !!

标签: htmlcssflexboxhtml5-canvas

解决方案


如果您查看MDN ,您可以阅读:

高度

以 CSS 像素为单位的坐标空间的高度。默认为 150。

宽度

以 CSS 像素为单位的坐标空间的宽度。默认为 300。

您已经找到了一种抵消宽度的方法,因为在 flexbox 世界元素中,元素可以缩小以适应主轴上的父尺寸(使用flex-shrink并通过添加min-width),但在横轴上没有缩小效果,您的代码相当于以下内容:

  html,
  body {
    height: 100%;
    margin: 0px;
  }
  
  body {
    padding-left: 30px
  }
  
  span {
    display: block;
    margin-top: 30px
  }
  
  #dut {
    background-color: red;
    min-width: 0;
    min-height: 0;
    height:150px;
    width:300px;
  }
  <span id="info"></span>
  <div style="
        background-color: gray;
        height: 200px;
        width: 50%;
        resize: both;
        overflow: auto;" onresize="onResize()">

    <div style="
            height:100%;
            display:flex;
            flex-direction: column;
        ">

      <div style="
            flex: 1 1 0px;
            display:flex;
            flex-direction: row;
            ">
        <div style="flex: 1 1 0px; background-color: chocolate;"></div>
        <div style="flex: 1 1 0px; background-color: gray;"></div>
        <div style="flex: 1 1 0px; background-color: chocolate;"></div>
        <div style="flex: 1 1 0px; background-color: gray;"></div>
      </div>

      <div style="
            flex: 1 1 0px;
            display:flex;
            flex-direction: row;
            ">
        <div style="flex: 1 1 0px; background-color: gray;"></div>
        <div id="dut" style="flex: 1 1 0px;"></div>
        <div style="flex: 1 1 0px; background-color: gray;"></div>
        <div style="flex: 1 1 0px; background-color: chocolate;"></div>
      </div>

    </div>
  </div>

  <script>
    const dut = window.document.getElementById("dut");
    const info = window.document.getElementById("info");
    const cb = () => info.innerHTML = `size of RED element: ${dut.offsetWidth} x ${dut.offsetHeight}`
    new ResizeObserver(cb).observe(dut)
  </script>
</body>

</html>

我用尺寸为 300x150 的简单 div 替换了画布。宽度可以缩小,高度只能触发溢出,永远不会缩小。

如果您将高度设为 0,您将拥有您想要的,因为我们删除了高度约束,它现在表现得像一个 div(默认情况下空 div 没有高度)

html,
  body {
    height: 100%;
    margin: 0px;
  }
  
  body {
    padding-left: 30px
  }
  
  span {
    display: block;
    margin-top: 30px
  }
  
  #dut {
    background-color: red;
    min-width: 0;
    min-height: 0;
  }
<span id="info"></span>
  <div style="
        background-color: gray;
        height: 200px;
        width: 50%;
        resize: both;
        overflow: auto;" onresize="onResize()">

    <div style="
            height:100%;
            display:flex;
            flex-direction: column;
        ">

      <div style="
            flex: 1 1 0px;
            display:flex;
            flex-direction: row;
            ">
        <div style="flex: 1 1 0px; background-color: chocolate;"></div>
        <div style="flex: 1 1 0px; background-color: gray;"></div>
        <div style="flex: 1 1 0px; background-color: chocolate;"></div>
        <div style="flex: 1 1 0px; background-color: gray;"></div>
      </div>

      <div style="
            flex: 1 1 0px;
            display:flex;
            flex-direction: row;
            ">
        <div style="flex: 1 1 0px; background-color: gray;"></div>
        <canvas id="dut" style="flex: 1 1 0px;" height=0></canvas>
        <div style="flex: 1 1 0px; background-color: gray;"></div>
        <div style="flex: 1 1 0px; background-color: chocolate;"></div>
      </div>

    </div>
  </div>

  <script>
    const dut = window.document.getElementById("dut");
    const info = window.document.getElementById("info");
    const cb = () => info.innerHTML = `size of RED element: ${dut.offsetWidth} x ${dut.offsetHeight}`
    new ResizeObserver(cb).observe(dut)
  </script>
</body>

</html>

height:0;min-height:100%在 CSS 内部并保持内在尺寸不变,并能够在画布内绘制。

html,
  body {
    height: 100%;
    margin: 0px;
  }
  
  body {
    padding-left: 30px
  }
  
  span {
    display: block;
    margin-top: 30px
  }
  
  #dut {
    background-color: red;
    min-width: 0;
    height: 0;
    min-height:100%;
  }
<span id="info"></span>
  <div style="
        background-color: gray;
        height: 200px;
        width: 50%;
        resize: both;
        overflow: auto;" onresize="onResize()">

    <div style="
            height:100%;
            display:flex;
            flex-direction: column;
        ">

      <div style="
            flex: 1 1 0px;
            display:flex;
            flex-direction: row;
            ">
        <div style="flex: 1 1 0px; background-color: chocolate;"></div>
        <div style="flex: 1 1 0px; background-color: gray;"></div>
        <div style="flex: 1 1 0px; background-color: chocolate;"></div>
        <div style="flex: 1 1 0px; background-color: gray;"></div>
      </div>

      <div style="
            flex: 1 1 0px;
            display:flex;
            flex-direction: row;
            ">
        <div style="flex: 1 1 0px; background-color: gray;"></div>
        <canvas id="dut" style="flex: 1 1 0px;" ></canvas>
        <div style="flex: 1 1 0px; background-color: gray;"></div>
        <div style="flex: 1 1 0px; background-color: chocolate;"></div>
      </div>

    </div>
  </div>

  <script>
    const dut = window.document.getElementById("dut");
    const info = window.document.getElementById("info");
    const cb = () => info.innerHTML = `size of RED element: ${dut.offsetWidth} x ${dut.offsetHeight}`
    new ResizeObserver(cb).observe(dut)
  </script>
</body>

</html>

您甚至可以根据需要更新属性,它的行为将相同:

html,
  body {
    height: 100%;
    margin: 0px;
  }
  
  body {
    padding-left: 30px
  }
  
  span {
    display: block;
    margin-top: 30px
  }
  
  #dut {
    background-color: red;
    min-width: 0;
    height: 0;
    min-height:100%;
  }
<span id="info"></span>
  <div style="
        background-color: gray;
        height: 200px;
        width: 50%;
        resize: both;
        overflow: auto;" onresize="onResize()">

    <div style="
            height:100%;
            display:flex;
            flex-direction: column;
        ">

      <div style="
            flex: 1 1 0px;
            display:flex;
            flex-direction: row;
            ">
        <div style="flex: 1 1 0px; background-color: chocolate;"></div>
        <div style="flex: 1 1 0px; background-color: gray;"></div>
        <div style="flex: 1 1 0px; background-color: chocolate;"></div>
        <div style="flex: 1 1 0px; background-color: gray;"></div>
      </div>

      <div style="
            flex: 1 1 0px;
            display:flex;
            flex-direction: row;
            ">
        <div style="flex: 1 1 0px; background-color: gray;"></div>
        <canvas id="dut" style="flex: 1 1 0px;" heght="600" width="600"></canvas>
        <div style="flex: 1 1 0px; background-color: gray;"></div>
        <div style="flex: 1 1 0px; background-color: chocolate;"></div>
      </div>

    </div>
  </div>

  <script>
    const dut = window.document.getElementById("dut");
    const info = window.document.getElementById("info");
    const cb = () => info.innerHTML = `size of RED element: ${dut.offsetWidth} x ${dut.offsetHeight}`
    new ResizeObserver(cb).observe(dut)
  </script>
</body>

</html>


推荐阅读