2016-03-01 191 views
12

我一直在嘗試使用Flexbox滾動表格式網格。 no horizontal scroll如何使溢出的flexbox元素具有其子元素的寬度?

它的大部分工作正常,但是有沒有辦法強制行橫向滾動時的內容寬度?

horizontal scroll on

正如你所看到的,每個偶數行具有白色背景,所以很容易被發現存在與寬度的問題。

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"> 
 

 
\t \t <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.2.1/jquery.min.js"></script> 
 
\t \t <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0/angular.min.js"></script> 
 
\t \t <script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/4.5.1/lodash.min.js"></script> 
 
\t \t <script src="//cdnjs.cloudflare.com/ajax/libs/jquery.perfect-scrollbar/0.6.10/js/min/perfect-scrollbar.jquery.min.js"></script> 
 

 
\t \t <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jquery.perfect-scrollbar/0.6.10/css/perfect-scrollbar.min.css"/> 
 
\t </head> 
 
\t <body ng-controller="testController as ctrl"> 
 
\t <input type="number" ng-model="ctrl.n" ng-max="100" /> 
 
\t <div style="display: flex"> 
 
\t \t <div style="flex: 1 1 auto"> 
 
\t \t \t <table class="table" style="width: 40vw; height: 40vh"> 
 
\t \t \t \t <tbody class="tbody" style="height: calc(100% - 60px)"> 
 
\t \t \t \t \t <tr class="tr" ng-repeat="item in ctrl.collection" style="min-width: 200px"> 
 
\t \t \t \t \t \t <th class="th">{{item}}</th> 
 
\t \t \t \t \t \t <th class="td" style="flex-basis: 200px">{{item}}</th> 
 
\t \t \t \t \t \t <th class="td">{{item}}</th> 
 
\t \t \t \t \t \t <th class="td">{{item}}</th> 
 
\t \t \t \t \t \t <th class="td">{{item}}</th> 
 
\t \t \t \t \t </tr> 
 
\t \t \t \t </tbody> 
 
\t \t \t \t <thead class="thead"> 
 
\t \t \t \t \t <tr class="tr"> 
 
\t \t \t \t \t \t <td class="th">A</td> 
 
\t \t \t \t \t \t <td class="th" style="flex-basis: 200px">B</td> 
 
\t \t \t \t \t \t <td class="th">C</td> 
 
\t \t \t \t \t \t <td class="th">D</td> 
 
\t \t \t \t \t \t <td class="th">E</td> 
 
\t \t \t \t \t </tr> 
 
\t \t \t \t </thead> 
 
\t \t \t \t <tfoot class="tfoot"> 
 
\t \t \t \t \t <tr class="tr"> 
 
\t \t \t \t \t \t <th class="th">A</th> 
 
\t \t \t \t \t \t <th class="th" style="flex-basis: 200px">B</th> 
 
\t \t \t \t \t \t <th class="th">C</th> 
 
\t \t \t \t \t \t <th class="th">D</th> 
 
\t \t \t \t \t \t <th class="th">E</th> 
 
\t \t \t \t \t </tr> 
 
\t \t \t \t </tfoot> 
 
\t \t \t </table> 
 
\t \t </div> 
 
\t \t <div style="flex: 1 1 auto"> 
 
\t \t \t <div class="table" style="width: 40vw; height: 40vh"> 
 
\t \t \t \t <div class="tbody" style="height: calc(100% - 60px)"> 
 
\t \t \t \t <div class="tr" ng-repeat="item in ctrl.collection"> 
 
\t \t \t \t \t <div class="th">{{item}}</div> 
 
\t \t \t \t \t <div class="td" style="flex-basis: 200px">{{item}}</div> 
 
\t \t \t \t \t <div class="td">{{item}}</div> 
 
\t \t \t \t \t <div class="td">{{item}}</div> 
 
\t \t \t \t \t <div class="td">{{item}}</div> 
 
\t \t \t \t </div> 
 
\t \t \t \t </div> 
 
\t \t \t \t <div class="thead"> 
 
\t \t \t \t <div class="tr"> 
 
\t \t \t \t \t <div class="th">A</div> 
 
\t \t \t \t \t <div class="th" style="flex-basis: 200px">B</div> 
 
\t \t \t \t \t <div class="th">C</div> 
 
\t \t \t \t \t <div class="th">D</div> 
 
\t \t \t \t \t <div class="th">E</div> 
 
\t \t \t \t </div> 
 
\t \t \t \t </div> 
 
\t \t \t \t <div class="tfoot"> 
 
\t \t \t \t <div class="tr"> 
 
\t \t \t \t \t <div class="th">A</div> 
 
\t \t \t \t \t <div class="th" style="flex-basis: 200px">B</div> 
 
\t \t \t \t \t <div class="th">C</div> 
 
\t \t \t \t \t <div class="th">D</div> 
 
\t \t \t \t \t <div class="th">E</div> 
 
\t \t \t \t </div> 
 
\t \t \t \t </div> 
 
\t \t \t </div> 
 
\t \t </div> 
 
\t </div> 
 

 
\t </body> 
 
</html>

任何想法?


編輯1

重要的是,行基於其細胞,而不是倒過來計算它們的寬度。在理想世界中,當空間可用時行會增長(並允許單元格增長),但不會縮小 - 這就是爲什麼滾動被啓用的原因。

我知道有可能無法完成。我花了相當一段時間,但我仍然堅持希望我不像你們那麼聰明。

+0

所以,你要每一行,以符合它的孩子總寬度?或者你想讓每個「單元格」符合列中最寬的內容?你有一個真正的表,你有一個僞div表。那是爲了試驗? – zer00ne

+0

第一個。後者我相信是不可能沒有JavaScript或沒有列優先的方法。或者是? :-) – m1gu3l

+0

確實,第一種方法很難令人望而卻步,謝天謝地,您有要求前者的敏感性:P是IE的要求嗎,先生? – zer00ne

回答

6

沒有錯誤,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是一個古老的,但鮮爲人知的財產仍然在它的試驗階段。它的基本功能是使元素將其內容完美地包裝起來。因此,如果將其應用於父元素,父元素將與內容一樣寬,並且隨着內容的增加和減少。

- Result: The overflow was gone but `tr` did not extend. 

刪除了flex-direction: column所以它會默認爲flex-direction: row我計算過,在垂直方向上流動的tr可能會突然停止和突然。

- Result: The `tr` extended, but the `td`s and `th`s were not aligned. 

justify-content: flex-end以列轉移到回顧問題的正確施加是在表的右側。

- Result: http://jsbin.com/godoqi/3/edit?css,output 

table-layout: fixed也適用於表,以便有超過列寬更多的控制。

- Result: See previous result. 

jsBin

片段

$('.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>

+0

+1中瀏覽_fit-content_時無所謂。這是一個答案,但它不是我正在尋找的答案,原因如下: 1)縮小的行不會在小屏幕上顯示,或當列數很多時 - 這就是爲什麼需要溢出和滾動 2)縮小行似乎也是列不對齊的原因 3)右邊的表看起來好像根本不工作 無論如何感謝! – m1gu3l

+0

嘗試將'fit-content'更改爲'max-content'右側的表格似乎對我而言是正確的。你是否使用Mac或PC以及使用哪些瀏覽器?你有沒有回顧http://jsbin.com/godoqi/3/edit?css,output? – zer00ne

+0

順便說一句,右邊的表格不能模仿左邊的表格,除非你指定'display:table/table-cell/table-row'這個atm是不可能的,因爲每個div都有一個'display:flex'總會有這兩個表之間的行爲差​​異,因爲div和表tr,tr或td之間的差異。 – zer00ne

相關問題