flex与grid响应式布局中的子容器为固定空间后的剩余空间,该元素容器不出现滚动条或者滚动条异常问题

flex与grid响应式布局中的子容器滚动条问题

最近在用grid布局写一些简单的响应式页面页面,遇到一个问题,就是我们的全局用grid布局或者flex布局中,遇到某个子元素的宽度或者高度是页面剩下的空间(flex是flex-grow:1的空间,grid是1fr的空间),但是这个元素空间又需要有滚动条的出现,即该元素中有很多子元素需要以滚动条的形式查看内容。
出现的问题:grid中即使设置了overflow:auto也还是不会出现滚动条,并且该元素被子内容撑高了,高度不再是剩余空间。

例如我们想要这种效果:(区域内有滚动条)
flex与grid响应式布局中的子容器为固定空间后的剩余空间,该元素容器不出现滚动条或者滚动条异常问题
但是实际上会出现这种效果:(区域被撑高,没有滚动条)
flex与grid响应式布局中的子容器为固定空间后的剩余空间,该元素容器不出现滚动条或者滚动条异常问题
该效果为header宽度或者高度固定,其余为剩余空间利用。
解决办法:grid中每一层都加上overflow:auto,层层传递,如果有一层没有overflow将不能正常出现预期效果,注意如果设置了1fr的容器不要设置height:100%,否者会出现滚动条异常

html代码:

<body>
    <div class="system-header">system-header</div>
    <div class="system-main">
        <div class="main-header">main header</div>
        <div class="main-content">
            <div class="content-header">
                content header
            </div>
            <div class="content-article">
                <div class="article-header">this is header</div>
                <div class="face-info">
                    <div class="face-header">face header</div>
                    <div class="face-list">
                        <div class="itemBox"></div>
                        <div class="itemBox"></div>
                        <div class="itemBox"></div>
                        <div class="itemBox"></div>
                        <div class="itemBox"></div>
                        <div class="itemBox"></div>
                        <div class="itemBox"></div>
                        <div class="itemBox"></div>
                        <div class="itemBox"></div>
                        <div class="itemBox"></div>
                    </div>
                </div>
            </div>
        </div>
    </div>

</body>

grid布局中css代码:

<style>
    html {
        height: 100%;
    }
    
    body {
        height: 100%;
        overflow: hidden;
        display: grid;
        grid-template-rows: 40px 1fr;
    }
    
    .system-header {
        background: lightgreen;
    }
    
    .system-main {
        display: grid;
        grid-template-columns: 60px 1fr;
        overflow: auto;
    }
    
    .main-header {
        background: lightsalmon;
    }
    
    .main-content {
        display: grid;
        grid-template-rows: 40px 1fr;
        overflow: auto;
    }
    
    .content-header {
        background: yellowgreen;
    }
    
    .content-article {
        border: 1px solid #ccc;
        display: grid;
        overflow: auto;
        margin-top: 20px;
        grid-template-columns: 1fr 250px;
    }
    
    .article-header {
        background: #c00;
    }
    
    .face-info {
        display: grid;
        grid-template-rows: 30px 1fr;
        overflow: auto;
    }
    
    .face-header {
        background: violet;
    }
    
    .face-list {
        border: 10px solid lightblue;
        overflow: auto;
    }
    
    .itemBox {
        width: 100%;
        height: 100px;
        border: 1px solid #c00;
        box-sizing: border-box;
    }
</style>

flex布局利用flex-direction来改变方向,设定固定大小的header一个固定值不能缩放,然后内容块用flex-grow:1来实现,并且只需要在需要有滚动条的区域用overflow即可
flex实现的css代码:

<style>
    html {
        height: 100%;
    }
    
    body {
        height: 100%;
        overflow: hidden;
        display: flex;
        flex-direction: column;
    }
    
    .system-header {
        height: 84px;
        flex-shrink: 0;
        background: lightgreen;
    }
    
    .system-main {
        flex-grow: 1;
        display: flex;
    }
    
    .main-header {
        width: 154px;
        flex-shrink: 0;
        background: lightsalmon;
    }
    
    .main-content {
        flex-grow: 1;
        display: flex;
        flex-direction: column;
    }
    
    .content-header {
        background: yellowgreen;
        height: 50px;
        flex-shrink: 0;
    }
    
    .content-article {
        flex-grow: 1;
        border: 1px solid #ccc;
        display: flex;
        margin-top: 20px;
    }
    
    .article-header {
        background: #c00;
        width: auto;
        flex-grow: 1;
    }
    
    .face-info {
        width: 350px;
        flex-shrink: 0;
        display: flex;
        flex-direction: column;
    }
    
    .face-header {
        height: 130px;
        flex-shrink: 0;
        background: violet;
    }
    
    .face-list {
        flex-grow: 1;
        border: 10px solid lightblue;
        overflow: auto;
    }
    
    .itemBox {
        width: 100%;
        height: 100px;
        border: 1px solid #c00;
        box-sizing: border-box;
    }
</style>

由于想测试多种情况嵌套了很多层次,每个层次都是使用grid或者flex来创建一个元素宽或高固定,另一个元素宽高分配剩余空间。也可以grid,flex混合着用都也能正常。
混合使用的情况:这种响应式也可以混合着使用,如果需要子元素正常出现滚动条,其中的是grid父元素一样需要overflow:auto。并且是flex的父元素也需要添加overflow:auto属性。

在这个问题上使用两种情况的利弊:
grid利弊:使用grid需要给层层嵌套元素添加overflow:auto属性比较繁琐。但是可以使用grid-template-columns:100px 1fr;这种形式来一次性给子元素分配空间来布局。
flex利弊:使用flex可以不用给每个嵌套的元素使用overflow:auto属性,但是每个使用了flex的子元素需要手动分配空间,固定元素需要写宽或高属性,并且设置flex-shrink:0;得到剩余空间的元素需要写flex-grow:1属性。

两种方法都可以使用,具体选择可以看个人情况。另外grid布局在ie上的支持很不友好,ie11大部分属性不能使用。而flex可以在ie11上正常显示,根据实际情况选择。