2016-03-01 9 views
12

Ho cercato di creare una griglia simile a una tabella con scorrimento utilizzando Flexbox. no horizontal scrollCome rendere l'elemento flexbox sorvolato per avere la larghezza dei suoi figli?

La maggior parte funziona correttamente, ma esiste un modo per forzare le righe ad avere la larghezza del loro contenuto quando lo scorrimento orizzontale è attivo?

horizontal scroll on

Come si può vedere, ogni fila anche hanno sfondo bianco, quindi è facile da individuare che c'è un problema con la larghezza.

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>

Tutte le idee?


EDIT 1

E 'importante che le righe calcolano la loro larghezza sulla base delle sue cellule, non il contrario. In un mondo ideale, la fila crescerebbe quando lo spazio è disponibile (e consentirebbe anche alle cellule di crescere), ma non si ridurrebbe: ecco perché lo scorrimento è abilitato.

Sono consapevole che esiste una possibilità che non può essere eseguita. Ci ho passato un po 'di tempo, ma mi aggrappo ancora alla speranza di non essere così intelligente come voi ragazzi.

+0

Così si vuole ogni riga di conformarsi alle larghezze totali di bambini è? O vuoi che ogni "cella" sia conforme al più ampio contenuto di una colonna? Hai una tabella reale e hai un tavolo pseudo div. Questo è per sperimentare? – zer00ne

+0

Il primo. Quest'ultimo credo non sia possibile senza javascript o senza approccio a colonna. O è? :-) – m1gu3l

+0

Il primo approccio della colonna sarebbe scoraggiante senza JS, anzi, grazie a Dio hai la sensibilità di richiedere il primo: P IE è un requisito, signore? – zer00ne

risposta

6

Non ci sono stati errori, HTML, CSS e JS (presumo che Angular e loDash siano a posto). Tutto bene. Quindi OP aveva solo bisogno di un modo per termoretraibile le righe. Le file si allungano in uno strano overflow? Ci sono stati alcuni cambiamenti al CSS, ma erano più per l'estetica e piccoli aggiustamenti. I principali cambiamenti di stile sono le seguenti:

.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 è una vecchia ma poco conosciuta proprietà ancora nella sua fase sperimentale. Ciò che fondamentalmente fa è che un elemento avvolge il suo contenuto in una misura perfetta. Quindi, se lo si applica a un elemento genitore, il genitore sarà largo quanto contenuto e aumenterà e diminuirà con il contenuto.

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

rimosso il flex-direction: column quindi sarebbe default flex-direction: row ho pensato che un tr che scorre in senso verticale sarebbe probabilmente fermarsi e bruscamente.

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

justify-content: flex-end applicata al fine di spostare le colonne a destra ricordando il problema era sul lato destro del tavolo.

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

table-layout: fixed è stato applicato anche alla tabella quindi c'è maggiore controllo sulla larghezza delle colonne.

- Result: See previous result. 

jsBin

Snippet

$('.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 per esplorare _fit-content_. È una risposta, ma non è la risposta che sto cercando ed ecco perché: 1) il restringimento delle righe non funzionerà sul piccolo schermo o quando ci sono molte colonne - ecco perché è necessario un overflow e lo scorrimento 2) restringimento le righe sembrano essere anche la causa delle colonne che non allineano la tabella 3) sulla destra sembra che non funzioni affatto Grazie comunque! – m1gu3l

+0

Prova a cambiare 'fit-content' in' max-content' La tabella a destra sembra funzionare come quella a destra per me. Usi un Mac o un PC e quali browser stai usando? Hai esaminato http://jsbin.com/godoqi/3/edit?css,output? – zer00ne

+0

Non ci si può aspettare che la tabella a destra imiti quella a sinistra a meno che non si assegni 'display: table/table-cell/table-row' che atm è impossibile perché ogni div ha un' display: flex' Ci sarà sempre ci sono differenze di comportamento tra queste due tabelle perché le differenze tra div e una tabella, tr o td. – zer00ne

Problemi correlati