切图仔:我的height:100%为什么没生效?

925 阅读5分钟

很多情况下,开发设置了height:100%,最后效果都不是事先设想的那样。这一切都是因为height本身就是trick满满,再加上百分比这个buff就容易出现多种情况

我们设置百分比percent,最终计算后的height肯定是 基准 * percent。那重点就是这个基准到底是多少呢?接下来我们用code的形式来讨论一下。

非DOCTYPE声明

<!DOCTYPE html>声明表明是HTML5文档规范。这里把它单独拎出来是因为,如果不声明这个,那么百分比就会以最近的祖先节点设置的height为基准。

这不是我们讨论的重点

给出一个code,有兴趣的自行调整test

<html>
<body>
    <div style="height:50%;">
        <div>
            <div style="height:50%;">
                我还是有1/4高的
            </div>
        </div>
    </div>
</body>

</html>

block

接下来讨论block元素

position:static(默认)|relative|sticky

父元素没有显式设置height

父元素没有显示的设置height样式,那么该元素设置的height百分比无效

<!DOCTYPE html>
<html>
<body>
    <div>
        <div style="height:50%;background-color:#92cbe6;">
            虽然我想100%,但实际只有文字高
        </div>
    </div>
</body>
</html>

注意这里一定要是父元素设置了height,,祖先元素设置了也是无效的

<!DOCTYPE html>
<html>
<body>
    <div style="height:100%;background-color:#999999;">
        <div>
            <div style="height:50%;background-color:#92cbe6;">
                虽然我想100%,但实际只有文字高
            </div>
        </div>
    </div>
</body>
</html>

对于html标签,它则没有这个要求,它的基准就是屏幕高度,也就是window.innerHeight

<!DOCTYPE html>
<html style="height:100%;background-color:#999999;">
<body>
    <div >
        <div>
            <div style="height:50%;background-color:#92cbe6;">
                虽然我想100%,但实际只有文字高
            </div>
        </div>
    </div>
</body>
</html>

父元素显式设置height

这时候子元素的基准 = 父元素的实际content高度

实际是什么意思

  1. height无效设置
    有时候,父元素也设置了height,例如height:100%,但这时候对于子元素来说,基准还是NaN,因为父元素自己在计算height:100%,由于它的父元素没有设置height,这就导致父元素的height:100%是失效的。这时候就变成了上一个没有显示设置height的场景
<!DOCTYPE html>
<html>
<body>
    <div style="height:100%;">
        <div style="height:100%;background-color:#92cbe6;">
            虽然我想100%,但实际只有文字高
        </div>
    </div>
</body>
</html>

下面这种只设置了min-height情况,其实父元素也是无效设置

<!DOCTYPE html>
<html>
<body>
    <div style="min-height:100px;border:  solid 1px rgb(250,0,255)">
        <div style="height:100%;">
            虽然我想100%,但实际只有文字高
        </div>
    </div>
</body>
</html>
  1. height实际值不为设置的值
    别忘了,我们还有min-height/max-height这些,它们也会影响最终的height。在下面这种情况,基准其实是60px
<!DOCTYPE html>
<html>
<body>
    <div style="height:50px;min-height:60px;">
        <div style="height:100%;background-color:#92cbe6;">
            content: 60px
        </div>
    </div>
</body>
</html>

content高度:根据盒子模型,父元素的有padding、content、border、margin这些。我们需要知道的是,子元素的百分比基准是以父元素的content高度为准的。为什么强调这个,是因为有别的情况不是这样

<!DOCTYPE html>
<html>
<body>
    <div style="height:50px;min-height:60px;padding:10px;border:5px solid black;margin:10px">
        <div style="height:100%;background-color:#92cbe6;">
            content60px
        </div>
    </div>
</body>
</html>
  1. 多个祖先节点百分比设置
    这里本质上还是上面说的那个原则,看父节点是否设置了有效height。简单描述成,如果某节点A设置了非百分比height,那么它下面节点B设置的百分比height会生效,因为A有基准。B下面C设置的百分比也会生效,因为B生效后也有了基准。但是,如果C下面的D没有设置height,那D下面的E设置的百分比就不会生效,因为中间断了
<!DOCTYPE html>
<html>
<body>
    <div style="height:100px;">
        <div style="height:100%;">
            <div style="height:100%;">
                <div>
                    <div style="height:100%;background-color:#92cbe6;">
                        我失效咯
                    </div>
                </div>
            </div>
        </div>
    </div>
</body>
</html>
  1. 如果一个元素设置绝对高度且为绝对定位,那子元素的百分比基准是多少?
<!DOCTYPE html>
<html>
<body>
    <div style="height:200px;">
        <div style="height:100px;position:absolute;">
            <div style="height:100%;">
                我到底是100px还是200px呢?
            </div>
        </div>
    </div>
</body>
</html>

答案是100px哦。
对于普通定位的元素来说,它只关注父元素的实际高度,而不用关注父元素是什么定位。

position:absolute

它大致逻辑与上面一致,不一样的是这个基准值。它找到的基准不是父元素的基准。它要找的,是离它最近的、具有定位(position 属性值为 relative, absolute, fixed, 或者 sticky)的祖先元素

祖先元素存在

这又分为了以下几种情况

  • 祖先元素设置了有效height
  • 祖先元素设置了无效height但被撑起
  • 祖先元素设置了无效height且没被撑起
  • 祖先元素未设置height但被撑起
  • 祖先元素未设置height且没被撑起
  1. 祖先元素设置了有效height 当祖先元素设置了有效height,那么基准 = 该祖先节点"设置的"content高度 + padding高度
    注意未包含border
<!DOCTYPE html>
<html>
<body>
    <div style="height:100px;">
        <!-- 下面的height:50%是有效的,因为父元素显示设置了height:100px -->
        <!-- 最后采用的是由这个设置的50%而转换成的实际高度,而不是下面80px撑起的高度 -->
        <div style="height:50%;position:relative;border:10px solid black;padding:10px">
            <div style="height:80px;">
                <div>
                    <div style="height:100%;position:absolute;background-color:#92cbe6;">
                        content: 100*0.5+10+10 = 70 px
                    </div>
                </div>
            </div>
        </div>
    </div>
</body>
</html>
  1. 祖先元素设置了无效height但被撑起 当祖先元素设置了无效height,且被子元素高度撑起来了,那么基准 = 该祖先节点的"实际撑起的"content高度 + padding高度
<!DOCTYPE html>
<html>
<body>
    <!-- 下面的height:50%是无效的 -->
    <!-- 最后采用的是由子元素撑起来的80px -->
    <div style="height:50%;position:relative;padding:10px">
        <div style="height:80px;">
            <div style="height:100%;position:absolute;background-color:#92cbe6;">
                content: 80+10+10 = 100 px
            </div>
        </div>
    </div>
</body>
</html>
  1. 祖先元素设置了无效height且没被撑起 此时基准 = 该祖先节点的padding高度
<!DOCTYPE html>
<html>
<body>
    <!-- 下面的height:50%是无效的 -->
    <!-- 最后absolute元素height为0 -->
    <div style="height:50%;padding:10px;position:relative">
        <div style="height:100%;position:absolute;background-color:#92cbe6;">
            content:20px
        </div>
    </div>
</body>
</html>
  1. 祖先元素没有设置height但被撑起 此时基准 = 该祖先节点的"实际撑起的"content高度 + padding高度
<!DOCTYPE html>
<html>
<body>
    <div style="position:relative">
        <div style="height:80px;">
            <div style="height:100%;position:absolute;background-color:#92cbe6;">
                content: 80px
            </div>
        </div>
    </div>
</body>
</html>
  1. 祖先元素没有设置height且没被撑起 此时基准 = 该祖先节点的padding高度
<!DOCTYPE html>
<html>
<body>
    <div style="position:relative">
            <div style="height:100%;position:absolute;background-color:#92cbe6;">
                content: 0
            </div>
        </div>
    </div>
</body>
</html>

祖先元素不存在

当不存在这样一个祖先元素时,这个基准值就是屏幕高度

<!DOCTYPE html>
<html>
<body>
    <div style="height:100px;">
        <div style="height:100%;position:absolute;background-color:#92cbe6;">
            content:撑满
        </div>
    </div>
</body>
</html>

position:fixed

基准就是屏幕高度,window.innerHeight

<!DOCTYPE html>
<html>
<body>
    <div style="height:100px;">
        <div style="height:50%;position:relative;border:10px solid black;padding:10px">
            <div style="height:80px;">
                <div>
                    <div style="height:100%;position:fixed;background-color:#92cbe6;">
                        content = window.innerHeight
                    </div>
                </div>
            </div>
        </div>
    </div>
</body>
</html>

inline-block

我其实感觉和block是一样的。但具体的code没验证,有兴趣的可以自己写写