【问题标题】:CSS min-height on canvas (or even svg) has a limit?画布(甚至 svg)上的 CSS 最小高度有限制吗?
【发布时间】:2020-08-29 12:52:15
【问题描述】:

用例

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

您可以在任何方向调整父 <div> 的大小,一切正常。

注意<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>

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

如果您取一个&lt;div&gt; 元素(标记为“dut”的红色元素),并将其替换为&lt;canvas&gt;,您将得到:

换句话说,红色元素不能在“300x150”这里收缩

我们应该可以用min-heightmin-width 来解决这个问题(早于弹性计算):

{
    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 属性有关&lt;svg&gt;)

谢谢!!

【问题讨论】:

    标签: html css flexbox html5-canvas


    【解决方案1】:

    如果你查看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>

    【讨论】:

    • 我不明白,如果我写height=0,我最终会得到画布的任何空缓冲区,因此没有空间可以绘制任何东西,对吗?让我们添加一点内容 ``` const ctx = dut.getContext('2d') ctx.beginPath(); ctx.arc(0,0,100,0,2*Math.PI); /* 半径 = 100px */ ctx.fill() ctx.stroke(); ``` 如果(画布高度=100),我可以看到四分之一的圆圈,是的,我可以缩小到“100px”(再缩小到 150),但是高度=50 或更差的高度=0,我的绘图被裁剪
    • @chtimi59 当然,当添加 height=0 时你什么也看不到。我试图解释你的行为。我没有关注如何在画布内绘图。如果你想画一些东西,你需要在 CSS 中设置 height;0 而不是 as 属性
    • @chtimi59 检查更新,添加了另一种选择
    • 我已根据您的解释更新了原帖,如果我的解释(基于您的评论)不准确,请纠正我
    • @chtimi59 both height:0;min-height:100% 用于移除约束,不仅 height:0 ... height:0 将强制元素具有 height:0然后 min-height:100% 将再次强制它占用所有可用空间,所以现在容器将决定高度
    【解决方案2】:

    这是基于之前答案的完整sn-p(svg和canvas)

    来自@Termani Afif 的引述:

    { height:0; min-height:100% } 都用于删除约束。它将强制元素具有height:0,然后min-height:100% 将再次强制它占用所有可用空间。所以现在容器将决定高度

    <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;
        height: 0;
        min-height: 100%;
      }
      
      #dut2 {
        background-color: red;
        min-width: 0;
        height: 0;
        min-height: 100%;
      }
    </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;" width=100 height=100></canvas>
            <div style="flex: 1 1 0px; background-color: gray;"></div>
            <svg id="dut2" style="flex: 1 1 0px;" viewBox="0 0 100 100" preserveAspectRatio="none">
                    <circle cx="0" cy="0" r="100" stroke="black" stroke-width="1" fill="#a00" />
                  </svg>
          </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)
    
        const ctx = dut.getContext('2d')
        ctx.beginPath();
        ctx.arc(0, 0, 100, 0, 2 * Math.PI);
        ctx.fillStyle = "#a00";
        ctx.fill()
        ctx.stroke();
      </script>
    </body>
    
    </html>
    </body>
    
    </html>

    【讨论】:

      猜你喜欢
      • 2010-09-06
      • 2012-10-24
      • 1970-01-01
      • 1970-01-01
      • 2012-01-02
      • 2019-04-21
      • 1970-01-01
      • 2011-05-29
      • 2012-12-06
      相关资源
      最近更新 更多