【问题标题】:CSS Grid row max height 1fr, scroll contentCSS Grid 行最大高度 1fr,滚动内容
【发布时间】:2018-01-05 19:17:26
【问题描述】:

我有一个使用以下 css-grid 样式的“日历”布局:

.calendar {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  grid-template-rows: 1.5em 1.5em repeat(6, 1fr);
  width: 100%;
  height: 100%;
}

(代码笔https://codepen.io/joelhoward0/pen/vJLmWK

前两行是“控件”标题和星期标题,然后是该月中每一天的 div:

<div class="day">
  <div class="header">26</div>
  <div class="content"></div>
</div>

每一天都有一个.header.content div。我希望.header div 占据行高的 1/5,内容占据 4/5 并在内容溢出时滚动。

但是,我尝试过的任何样式组合都会导致 .content 增长,缩小其他网格行以进行补偿。我认为这是由于在容器 grid-template-rows 上使用了1fr

是否可以在.content div 上实现网格行高的 4/5 的最大高度,即可用垂直空间的 1/6?

(注意:.day 上设置overflow-y: auto; 达到了我想要的效果,但是标题包含在滚动区域中。在.content 上设置overflow-y: auto; 似乎不起作用任何东西。)

【问题讨论】:

    标签: html css css-grid


    【解决方案1】:

    看起来如果您将标头设置为position: fixed,设置calc(100%/7) 并给它一个不透明的background。将.day 设置为overflow-y:auto 并给你的.content 一个margin-top,这似乎工作以及保持压延机流动到浏览器高度。

    如果标题是带边框的日期块的全宽很重要,您可以将当前边框属性仅添加到右侧并添加box-sizing: border-box

    .header{
      position:fixed;
      background: white;
      width: calc(100%/7);
      border: solid grey;
      border-width: 0 1px 0 0;
      box-sizing: border-box;
    }
    
    .day {
      border: solid grey;
      border-width: 0 1px 1px 0;
      overflow-y: auto;
    }
    
    .content {
      margin-top: 20px;
    }
    

    Demo

    【讨论】:

      【解决方案2】:

      网格中的每一行(标题除外)都设置为1fr 高度。这意味着每一行将消耗容器中相同比例的可用空间。

      请注意fr 大小实际上并未定义长度——widthheight。使用fr,您只是在分配可用空间。

      但要使overflow 属性起作用,必须定义实际高度:

      为了使overflow 生效,块级容器必须设置高度(heightmax-height)或将white-space 设置为nowrap

      来源:https://developer.mozilla.org/en-US/docs/Web/CSS/overflow

      因此,请考虑使用实际高度而不是空间分布。这是一个例子:

      html,
      body {
        height: 100%;
      }
      
      body {
        position: relative;
        margin: 0;
      }
      
      .calendar {
        display: grid;
        grid-template-columns: repeat(7, 1fr);
        grid-template-rows: 1.5em 1.5em repeat(6, 175px);  /* adjusment */
        width: 100%;
        height: 100%;
        box-sizing: border-box;
        border: solid grey;
        border-width: 1px 0 0 1px;
        position: relative;
      }
      
      .dayHeader {
        border: solid grey;
        border-width: 0 1px 1px 0;
      }
      
      .day {
        height: 175px;  /* new */
        border: solid grey;
        border-width: 0 1px 1px 0;
      }
      
      .header { /* new */
        height: 20%;
        background-color: yellow;
      }
      
      .content {
        height: 80%; /* new */
        overflow-y: auto;
        background-color: aqua;
      }
      
      .controls {
        grid-column-start: 1;
        grid-column-end: 8;
        border: solid grey;
        border-width: 0 1px 1px 0;
      }
      <div class="calendar">
        <div class="controls">July 2017</div>
        <div class="dayHeader">Sunday</div>
        <div class="dayHeader">Monday</div>
        <div class="dayHeader">Tuesday</div>
        <div class="dayHeader">Wednesday</div>
        <div class="dayHeader">Thursday</div>
        <div class="dayHeader">Friday</div>
        <div class="dayHeader">Saturday</div>
        <div class="day">
          <div class="header">25</div>
          <div class="content">
            this is a lot of content that I want to have scroll instead of just stretching the grid row and forcing the other rows to be smaller to compensate for this one's increased size due
          </div>
        </div>
        <div class="day">
          <div class="header">26</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">27</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">28</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">29</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">30</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">1</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">2</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">3</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">4</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">5</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">6</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">7</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">8</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">9</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">10</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">11</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">12</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">13</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">14</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">15</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">16</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">17</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">18</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">19</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">20</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">21</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">22</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">23</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">24</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">25</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">26</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">27</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">28</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">29</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">30</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">31</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">1</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">2</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">3</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">4</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">5</div>
          <div class="content"></div>
        </div>
      </div>

      revised demo

      【讨论】:

      • 这绝对有效,但我希望有一个不需要固定高度的解决方案。我希望它们占用 1/6 的可用空间,但要防止超出该空间的增长。似乎网格规则不允许这样做?
      • 这不是网格规则。 overflow 属性需要固定长度才能实际溢出。
      【解决方案3】:

      虽然@MichaelB 的回答在技术上是正确的,但我发现您可以真正做到这一点,而无需手动指定高度。而且做起来也很简单。

      除了将overflow:auto 添加到您想要滚动条的网格项之外,您还需要将overflow:auto 添加到该网格项的父项

      https://codepen.io/kumarharsh/pen/jejGMm?editors=1100

      html,
      body {
        height: 100%;
      }
      
      body {
        position: relative;
        margin: 0;
      }
      
      .calendar {
        display: grid;
        grid-template-columns: repeat(7, 1fr);
        grid-template-rows: 1.5em 1.5em repeat(6, 1fr);
        width: 100%;
        height: 100%;
        box-sizing: border-box;
        border: solid grey;
        border-width: 1px 0 0 1px;
        position: relative;
      }
      
      .dayHeader {
        border: solid grey;
        border-width: 0 1px 1px 0;
      }
      
      .day {
        border: solid grey;
        border-width: 0 1px 1px 0;
        overflow: auto; /* added overflow here! */
      }
      
      .content {
        overflow-y: auto;
      }
      
      .controls {
        grid-column-start: 1;
        grid-column-end: 8;
        border: solid grey;
        border-width: 0 1px 1px 0;
      }
      <div class="calendar">
        <div class="controls">July 2017</div>
        <div class="dayHeader">Sunday</div>
        <div class="dayHeader">Monday</div>
        <div class="dayHeader">Tuesday</div>
        <div class="dayHeader">Wednesday</div>
        <div class="dayHeader">Thursday</div>
        <div class="dayHeader">Friday</div>
        <div class="dayHeader">Saturday</div>
        <div class="day">
          <div class="header">25</div>
          <div class="content">
            this is a lot of content that I want to have scroll instead of just stretching the grid row and forcing the other rows to be smaller to compensate for this one's increased size due
          </div>
        </div>
        <div class="day">
          <div class="header">26</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">27</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">28</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">29</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">30</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">1</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">2</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">3</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">4</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">5</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">6</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">7</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">8</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">9</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">10</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">11</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">12</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">13</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">14</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">15</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">16</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">17</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">18</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">19</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">20</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">21</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">22</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">23</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">24</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">25</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">26</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">27</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">28</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">29</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">30</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">31</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">1</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">2</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">3</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">4</div>
          <div class="content"></div>
        </div>
        <div class="day">
          <div class="header">5</div>
          <div class="content"></div>
        </div>
      </div>

      最重要的是,它适用于所有浏览器(在 Firefox、Chrome 和 Edge 中测试),因此它可能不是黑客攻击,而是一种预期行为。

      为什么会这样?

      我无法在规范中找到明确的答案,但是当我有具体的内容时,我会继续在这里查找和更新。

      更新

      请阅读@Victoria 的后续评论:CSS Grid row max height 1fr, scroll content,它有另一种方式 - 如果您的设计允许,我建议您使用这种方式。

      【讨论】:

      • 哇!花了一些搜索才找到这个,但它确实有效!
      • 进一步搜索,将 auto 放置在父级上的另一种方法是使用“ minmax( 0, 1fr ) ”而不是普通的“ 1fr ”来调整网格轨道的大小。见github.com/w3c/csswg-drafts/issues/1777
      • @Victoria 你是对的——几个月前我也学到了这一点。我会更新我的答案。谢谢:)
      猜你喜欢
      • 2018-09-16
      • 1970-01-01
      • 2021-11-10
      • 2019-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多