我一直在尝试使用 Flexbox 通过滚动创建类似表格的网格。
大部分工作正常,但是有什么方法可以在水平滚动打开时强制行具有其内容的宽度?
如您所见,每偶数行都有白色背景,因此很容易发现宽度有问题。
http://jsbin.com/fedisozafe/embed?html,css,output
$('.tbody').on('scroll', function(e) {
$(this).siblings().scrollLeft($(this).scrollLeft());
});
$('.tbody').perfectScrollbar();
$(window).on('resize', function(e) {
$('.tbody')
.perfectScrollbar('update')
.siblings()
.scrollLeft($(this).scrollLeft());
});
angular.module('app', [])
.controller('testController', [
'$scope',
function($scope) {
this.n = 5;
$scope.$watch(() => this.n, () => this.collection = _.range(this.n));
}
]);
* {
box-sizing: border-box;
border-collapse: collapse;
}
.table {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
border: solid 1px red;
}
.table > * {
border-top: solid 1px transparent;
border-bottom: solid 1px transparent;
}
.thead {
border-bottom: solid 1px red;
}
.tfoot {
border-top: solid 1px red;
}
.thead {
flex: none;
display: flex;
flex-direction: column;
overflow: hidden;
order: -1;
background-color: lightgoldenrodyellow;
}
.tbody {
position: relative;
flex: 1 1 auto;
display: flex;
flex-direction: column;
overflow: hidden;
justify-content: space-between;
background-color: lightgray;
}
.tfoot {
flex: none;
display: flex;
flex-direction: column;
overflow: hidden;
order: 1;
background-color: lightblue;
}
.tr {
display: flex;
flex: 1 0 20px;
justify-content: space-between;
align-items: center;
}
.tr:nth-child(2n) {
background-color: white;
}
.td,
.th {
flex: 1 0 60px;
display: inline-flex;
}
.th {
font-weight: bold;
}
<!doctype html>
<html ng-app="app">
<head>
<meta charset="utf-8">
<title></title>
<meta name="viewport" content="width=device-width">
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.2.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0/angular.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/4.5.1/lodash.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery.perfect-scrollbar/0.6.10/js/min/perfect-scrollbar.jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jquery.perfect-scrollbar/0.6.10/css/perfect-scrollbar.min.css"/>
</head>
<body ng-controller="testController as ctrl">
<input type="number" ng-model="ctrl.n" ng-max="100" />
<div style="display: flex">
<div style="flex: 1 1 auto">
<table class="table" style="width: 40vw; height: 40vh">
<tbody class="tbody" style="height: calc(100% - 60px)">
<tr class="tr" ng-repeat="item in ctrl.collection" style="min-width: 200px">
<th class="th">{{item}}</th>
<th class="td" style="flex-basis: 200px">{{item}}</th>
<th class="td">{{item}}</th>
<th class="td">{{item}}</th>
<th class="td">{{item}}</th>
</tr>
</tbody>
<thead class="thead">
<tr class="tr">
<td class="th">A</td>
<td class="th" style="flex-basis: 200px">B</td>
<td class="th">C</td>
<td class="th">D</td>
<td class="th">E</td>
</tr>
</thead>
<tfoot class="tfoot">
<tr class="tr">
<th class="th">A</th>
<th class="th" style="flex-basis: 200px">B</th>
<th class="th">C</th>
<th class="th">D</th>
<th class="th">E</th>
</tr>
</tfoot>
</table>
</div>
<div style="flex: 1 1 auto">
<div class="table" style="width: 40vw; height: 40vh">
<div class="tbody" style="height: calc(100% - 60px)">
<div class="tr" ng-repeat="item in ctrl.collection">
<div class="th">{{item}}</div>
<div class="td" style="flex-basis: 200px">{{item}}</div>
<div class="td">{{item}}</div>
<div class="td">{{item}}</div>
<div class="td">{{item}}</div>
</div>
</div>
<div class="thead">
<div class="tr">
<div class="th">A</div>
<div class="th" style="flex-basis: 200px">B</div>
<div class="th">C</div>
<div class="th">D</div>
<div class="th">E</div>
</div>
</div>
<div class="tfoot">
<div class="tr">
<div class="th">A</div>
<div class="th" style="flex-basis: 200px">B</div>
<div class="th">C</div>
<div class="th">D</div>
<div class="th">E</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
有什么想法吗?
编辑 1
行根据其单元格计算宽度非常重要,而不是相反。在理想的世界中,行会在空间可用时增长(并允许单元格也增长),但不会收缩 - 这就是启用滚动的原因。
我知道有可能无法完成。我在这上面花了很多时间,但我仍然希望我没有你们那么聪明。
最佳答案
没有错误,HTML、CSS 和 JS(我假设 Angular 和 loDash 都很好。)都很好。所以 OP 只需要一种方法来收缩包装行。以奇怪的方式扩展的行溢出了吗? CSS 有一些变化,但更多的是为了美观和小的调整。主要样式变化如下:
.tr {
display: flex;
min-width: -moz-fit-content;
min-width: -webkit-fit-content;
min-width: fit-content;
flex: 1 0 20px;
justify-content: flex-end;
}
fit-content
is an old but little known property still in it's experimental stage. What it basically does is it will make an element wrap it's content in a perfect fit. So if you apply it to a parent element, the parent will be as wide as it's content and it will increase and decrease with the content.
- Result: The overflow was gone but `tr` did not extend.
Removed the
flex-direction: column
so it would default toflex-direction: row
I figured that atr
flowing in a vertical direction would probably stop short and abruptly.
- Result: The `tr` extended, but the `td`s and `th`s were not aligned.
justify-content: flex-end
applied in order to shift the columns to the right recalling the problem was on the right side of the table.
- Result: http://jsbin.com/godoqi/3/edit?css,output
table-layout: fixed
was also applied to the table so there's more control over column widths.
- Result: See previous result.
片段
$('.tbody').on('scroll', function(e) {
$(this).siblings().scrollLeft($(this).scrollLeft());
});
$('.tbody').perfectScrollbar();
$(window).on('resize', function(e) {
$('.tbody')
.perfectScrollbar('update')
.siblings()
.scrollLeft($(this).scrollLeft());
});
angular.module('app', [])
.controller('testController', [
'$scope',
function($scope) {
this.n = 5;
$scope.$watch(() => this.n, () => this.collection = _.range(this.n));
}
]);
* {
box-sizing: border-box;
}
.table {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
border: solid 1px red;
border-collapse: collapse;
table-layout: fixed;
}
.table > * {
border-top: solid 1px transparent;
border-bottom: solid 1px transparent;
}
.thead {
border-bottom: solid 1px red;
}
.tfoot {
border-top: solid 1px red;
}
.thead {
display: flex;
flex-direction: column;
overflow: hidden;
order: -1;
background-color: lightgoldenrodyellow;
}
.tbody {
position: relative;
flex: 1 1 auto;
display: flex;
flex-direction: column;
align-content: space-between;
background-color: lightgray;
}
.tfoot {
flex: none;
display: flex;
flex-direction: column;
overflow: hidden;
order: 1;
background-color: lightblue;
text-align: center;
}
.tr {
display: flex;
min-width: -moz-fit-content;
min-width: -webkit-fit-content;
min-width: fit-content;
flex: 1 0 20px;
justify-content: flex-end;
}
.tr:nth-child(2n) {
background-color: white;
}
.td,
.th {
flex: 0 1 60px;
text-align: center;
}
.th {
font-weight: bold;
}
.ng-not-empty {
text-align: center;
width: 8ex;
}
<!doctype html>
<html ng-app="app">
<head>
<meta charset="utf-8">
<title></title>
<meta name="viewport" content="width=device-width">
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.2.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0/angular.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/4.5.1/lodash.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery.perfect-scrollbar/0.6.10/js/min/perfect-scrollbar.jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jquery.perfect-scrollbar/0.6.10/css/perfect-scrollbar.min.css" />
</head>
<body ng-controller="testController as ctrl">
<input type="number" ng-model="ctrl.n" ng-max="100" />
<div style="display: flex">
<div style="flex: 1 1 auto">
<table class="table" style="width: 40vw; height: 40vh">
<tbody class="tbody" style="height: calc(100% - 60px)">
<tr class="tr" ng-repeat="item in ctrl.collection" style="min-width: 200px">
<th class="th">{{item}}</th>
<th class="td" style="flex-basis: 200px">{{item}}</th>
<th class="td">{{item}}</th>
<th class="td">{{item}}</th>
<th class="td">{{item}}</th>
</tr>
</tbody>
<thead class="thead">
<tr class="tr">
<td class="th">A</td>
<td class="th" style="flex-basis: 200px">B</td>
<td class="th">C</td>
<td class="th">D</td>
<td class="th">E</td>
</tr>
</thead>
<tfoot class="tfoot">
<tr class="tr">
<th class="th">A</th>
<th class="th" style="flex-basis: 200px">B</th>
<th class="th">C</th>
<th class="th">D</th>
<th class="th">E</th>
</tr>
</tfoot>
</table>
</div>
<div style="flex: 1 1 auto">
<div class="table" style="width: 40vw; height: 40vh">
<div class="tbody" style="height: calc(100% - 60px)">
<div class="tr" ng-repeat="item in ctrl.collection">
<div class="th">{{item}}</div>
<div class="td" style="flex-basis: 200px">{{item}}</div>
<div class="td">{{item}}</div>
<div class="td">{{item}}</div>
<div class="td">{{item}}</div>
</div>
</div>
<div class="thead">
<div class="tr">
<div class="th">A</div>
<div class="th" style="flex-basis: 200px">B</div>
<div class="th">C</div>
<div class="th">D</div>
<div class="th">E</div>
</div>
</div>
<div class="tfoot">
<div class="tr">
<div class="th">A</div>
<div class="th" style="flex-basis: 200px">B</div>
<div class="th">C</div>
<div class="th">D</div>
<div class="th">E</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
关于html - 如何使溢出的 flexbox 元素具有其子元素的宽度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35727958/