首页 > 解决方案 > 类似 Trello 的 CSS 网格布局:如何滚动卡片列表并显示标题和页脚

问题描述

我正在尝试基于 css grid-Layouts 构建一个类似 Trello 的 UI。我遵循了 Joshua Saunders 的一个非常有用的教程(https://medium.com/better-programming/creating-trellos-ui-with-css-grid-ed1fbfcd9448)最后它还没有完成,我一直在寻找一个整天解决方案:调整浏览器窗口大小时,Trello 的卡片列表有一个特定的行为:如果列表没有到达视口的底端,“+添加卡片”按钮总是在末尾列表和所有卡片都是可见的。如果卡片列表对于视口来说太长,“+添加卡片”按钮将始终在视口的底端可见,但标题和“+添加卡片”按钮之间的卡片列表变为可滚动的。

总结:在任何视口大小下,每个列表的标题和“+ 添加卡片”按钮将始终可见,如有必要,卡片列表本身可滚动。我想,我找到了一个使用 flex-layouts 的解决方案(还没有尝试过),但我仍然想知道,是否可以使用网格布局。

这是我的代码:

BODY {
    margin:0px;
    padding:0px;
}
.base {
    height: 100vh;
    width: 100vw;
    background-color: rgb(0, 121, 191);
    font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Noto Sans,Ubuntu,Droid Sans,Helvetica Neue,sans-serif;
    font-size: 14px;
    display: grid;
    grid-template-rows: max-content auto;
    grid-gap: 10px;
}
.header {
    padding:5px;
    color:white;
    font-size:18px;
    font-weight:bold;
}
.board {
    margin:5px;
    height:auto;
    display:grid;
    grid-template-columns:max-content;
    overflow:auto;
    grid-auto-flow:column;
    border: 1px solid yellow;
}
.lists {
    height:auto;
    display:grid;
    grid-auto-columns:272px;
    grid-auto-flow:column;
    grid-gap:8px;
    border:1px solid red;
}
.list {
    background-color:rgb(235, 236, 240);
    border-radius:3px;
    padding:10px;
    display:grid;
    grid-template-rows:max-content auto max-content;
    grid-gap:10px;
    height:max-content;
    align-items:stretch;
}
.list-title {
    font-weight:bold;
}
.list-body {
    display:grid;
    grid-auto-rows:max-content;
    grid-gap:10px;
    height:max-content;
    overflow:scroll;
}
.card {
    background-color:white;
    border-radius:3px;
    box-shadow:0 1px 0 rgba(9, 30, 66, 0.25);
    padding:10px;
}
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>grid-layout trello-like UI - heightproblem</title>
    <link rel="stylesheet" type="text/css" href="trello-ui.css">
</head>
<body>
<div class="base">
    <div class="header">
        Header
    </div>
    <div class="board">
        <div class="lists">
        
            <div class="list">
                <div class="list-title">List 1</div>
                <div class="list-body">
                    <div class="card">Card</div>
                    <div class="card">Card</div>
                    <div class="card">Card</div>
                    <div class="card">Card</div>
                    <div class="card">Card</div>
                    <div class="card">Card</div>
                    <div class="card">Card</div>
                    <div class="card">Card</div>
                    <div class="card">Card</div>
                    <div class="card">Card</div>
                    <div class="card">Card</div>
                    <div class="card">Card</div>
                    <div class="card">Card</div>
                    <div class="card">Card</div>
                    <div class="card">Card</div>
                    <div class="card">Card</div>
                    <div class="card">Card</div>
                    <div class="card">Card</div>
                    <div class="card">Card</div>
                    <div class="card">Card</div>
                    <div class="card">Card</div>
                    <div class="card">Card</div>
                    <div class="card">Card</div>
                    <div class="card">Card</div>
                </div><!--// list-body -->
                <div class="list-foot">+ add card</div>
            </div><!--// list -->
            
        
            <div class="list">
                <div class="list-title">List 2</div>
                <div class="list-body">
                    <div class="card">Card</div>
                    <div class="card">Card</div>
                    <div class="card">Card</div>
                    <div class="card">Card</div>
                    <div class="card">Card</div>
                    <div class="card">Card</div>
                    <div class="card">Card</div>
                    <div class="card">Card</div>
                </div><!--// list-body -->
                <div class="list-foot">+ add card</div>
            </div><!--// list -->
            
            <div class="list">
                <div class="list-title">List 3</div>
                <div class="list-body">
                    <div class="card">Card</div>
                    <div class="card">Card</div>
                </div><!--// list-body -->
                <div class="list-foot">+ add card</div>
            </div><!--// list -->
            
            
            <div class="list">
                <div class="list-title">List 4</div>
                <div class="list-body">
                    <div class="card">Card</div>
                    <div class="card">Card</div>
                </div><!--// list-body -->
                <div class="list-foot">+ add card</div>
            </div><!--// list -->
            
            
            <div class="list">
                <div class="list-title">List 5</div>
                <div class="list-body">
                    <div class="card">Card</div>
                    <div class="card">Card</div>
                </div><!--// list-body -->
                <div class="list-foot">+ add card</div>
            </div><!--// list -->
            
            <div class="list">
                <div class="list-title">List 6</div>
                <div class="list-body">
                        &nbsp;
                </div><!--// list-body -->
                <div class="list-foot">+ add card</div>
            </div><!--// list -->
            
            
        </div><!--// lists
    </div>
</div>
</body>
</html>

标签: htmlcssgrid-layouttrello

解决方案


使用 csscalc()方法计算可用高度,这里是它的文档:https ://developer.mozilla.org/en-US/docs/Web/CSS/calc

这是您当前问题的解决方案

body {
  margin: 0px;
  padding: 0px;
}

.base {
  height: 100vh;
  width: 100vw;
  background-color: rgb(0, 121, 191);
  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Noto Sans, Ubuntu, Droid Sans, Helvetica Neue, sans-serif;
  font-size: 14px;
  display: grid;
  grid-template-rows: max-content auto;
  grid-gap: 10px;
}

.header {
  padding: 5px;
  color: white;
  font-size: 18px;
  font-weight: bold;
  height: 35px;
}

.board {
  margin: 5px;
  height: calc(100vh - 70px);
  display: grid;
  grid-template-columns: max-content;
  grid-auto-flow: column;
  border: 1px solid yellow;
  overflow-x: scroll;
  overflow-y: hidden;
}

.lists {
  display: grid;
  grid-auto-columns: 272px;
  grid-auto-flow: column;
  grid-gap: 8px;
  border: 1px solid red;
  height: calc(100vh - 90px);
}

.list {
  background-color: rgb(235, 236, 240);
  border-radius: 3px;
  padding: 10px;
  display: grid;
  grid-template-rows: max-content auto max-content;
  grid-gap: 10px;
  height: max-content;
  align-items: stretch;
  max-height: calc(100vh - 90px);
  overflow: hidden;
}

.list-title {
  font-weight: bold;
  height: 20px;
}

.list-body {
  display: grid;
  grid-auto-rows: max-content;
  grid-gap: 10px;
  overflow: scroll;
  max-height: calc(100vh - 190px);
}

.card {
  background-color: white;
  border-radius: 3px;
  box-shadow: 0 1px 0 rgba(9, 30, 66, 0.25);
  padding: 10px;
}

.list-foot {
  height: 35px;
}

推荐阅读