简体   繁体   English

用固定列构建可滚动表

[英]Build scrollable table with fixed column

I need to achieve something like this 我需要实现这样的目标

在此处输入图片说明

The scroll to the right is dynamic (the number of columns is variable), and the first column in the left is fixed. 右边的滚动是动态的(列数是可变的),而左边的第一列是固定的。 The scrolling should be with the arrows at the top of the image, but I can negotiate to discard that. 滚动应该使用图像顶部的箭头,但是我可以协商放弃它。

My first thought was to use flexbox like this (this is an example to mock, I will use angular with ng-repeat to dynamically generate the structure) 我的第一个想法是像这样使用flexbox(这是一个模拟示例,我将使用angular和ng-repeat来动态生成结构)

 .reporting-table-container { display: flex; padding-left: 25px; padding-right: 10px; margin-bottom: 15px; } .reporting-table-container .columns-container { display: flex; overflow-x: scroll; margin-right: 15px; } .reporting-table-container .columns-container .single-column-container { display: flex; flex-direction: column; justify-content: space-evenly; } .reporting-table-container .columns-container .single-column-container:nth-child(even), .reporting-table-container .labels-container { background-color: #e9e9e9; } .reporting-table-container .labels-container { display: flex; flex-direction: column; justify-content: space-evenly; } .reporting-table-container .labels-container > div { width: 100px; font-weight: 800px; } 
 <div class="reporting-table-container"> <div class="labels-container"> <div>ID</div> <div>Product Title</div> <div>Strategy Name</div> <div>Score</div> <div>Message</div> <div>Feedback</div> <div>Clicks</div> <div>Conversion Rate</div> <div>Revenue</div> </div> <div class="columns-container"> <div class="single-column-container"> <div>2249</div> <div>25.5 cu. ft. French Door Refrigerator in Stainless Steel</div> <div>Online co-purchase 2wks</div> <div>230</div> <div>Customer also bough this other item</div> <div>43</div> <div>0.50%</div> <div>$282.830</div> </div> <div class="single-column-container"> <div>2249</div> <div>25.5 cu. ft. French Door Refrigerator in Stainless Steel</div> <div>Online co-purchase 2wks</div> <div>230</div> <div>Customer also bough this other item</div> <div>43</div> <div>0.50%</div> <div>$282.830</div> </div> <div class="single-column-container"> <div>2249</div> <div>25.5 cu. ft. French Door Refrigerator in Stainless Steel</div> <div>Online co-purchase 2wks</div> <div>230</div> <div>Customer also bough this other item</div> <div>43</div> <div>0.50%</div> <div>$282.830</div> </div> <div class="single-column-container"> <div>2249</div> <div>25.5 cu. ft. French Door Refrigerator in Stainless Steel</div> <div>Online co-purchase 2wks</div> <div>230</div> <div>Customer also bough this other item</div> <div>43</div> <div>0.50%</div> <div>$282.830</div> </div> <div class="single-column-container"> <div>2249</div> <div>25.5 cu. ft. French Door Refrigerator in Stainless Steel</div> <div>Online co-purchase 2wks</div> <div>230</div> <div>Customer also bough this other item</div> <div>43</div> <div>0.50%</div> <div>$282.830</div> </div> <div class="single-column-container"> <div>2249</div> <div>25.5 cu. ft. French Door Refrigerator in Stainless Steel</div> <div>Online co-purchase 2wks</div> <div>230</div> <div>Customer also bough this other item</div> <div>43</div> <div>0.50%</div> <div>$282.830</div> </div> <div class="single-column-container"> <div>2249</div> <div>25.5 cu. ft. French Door Refrigerator in Stainless Steel</div> <div>Online co-purchase 2wks</div> <div>230</div> <div>Customer also bough this other item</div> <div>43</div> <div>0.50%</div> <div>$282.830</div> </div> <div class="single-column-container"> <div>2249</div> <div>25.5 cu. ft. French Door Refrigerator in Stainless Steel</div> <div>Online co-purchase 2wks</div> <div>230</div> <div>Customer also bough this other item</div> <div>43</div> <div>0.50%</div> <div>$282.830</div> </div> <div class="single-column-container"> <div>2249</div> <div>25.5 cu. ft. French Door Refrigerator in Stainless Steel</div> <div>Online co-purchase 2wks</div> <div>230</div> <div>Customer also bough this other item</div> <div>43</div> <div>0.50%</div> <div>$282.830</div> </div> <div class="single-column-container"> <div>2249</div> <div>25.5 cu. ft. French Door Refrigerator in Stainless Steel</div> <div>Online co-purchase 2wks</div> <div>230</div> <div>Customer also bough this other item</div> <div>43</div> <div>0.50%</div> <div>$282.830</div> </div> <div class="single-column-container"> <div>2249</div> <div>25.5 cu. ft. French Door Refrigerator in Stainless Steel</div> <div>Online co-purchase 2wks</div> <div>230</div> <div>Customer also bough this other item</div> <div>43</div> <div>0.50%</div> <div>$282.830</div> </div> </div> </div> 

but quickly it became apparent that the borders won't follow between the label columns, and the data columns. 但是很快就发现在标签列和数据列之间不会出现边界。 Besides, there's no way to me (at least without javascript) to match the heights for the very same row (I should expand the row height given the largest data for that row) 此外,我没有办法(至少没有javascript)匹配同一行的高度(鉴于该行的最大数据,我应该扩展该行的高度)

Then I moved into CSS Grid Layouts, but I am not quite sure how should it look - Difference from my current example, all "cells" would be within the same unit so I am not sure how to fix the first column nor how to set the css dynamic, depending on the number of items to render. 然后我进入了CSS网格布局,但是我不太确定它的外观-与当前示例不同,所有“单元格”都在同一单元内,因此我不确定如何固定第一列或如何设置css动态,取决于要渲染的项目数。

How can I achieve that? 我该如何实现?

Notice : Although my code will use angularjs to dynamically generate the structure, I believe the problem is pure CSS/HTML (I would like to avoid the usage of javascript to generate this). 注意 :尽管我的代码将使用angularjs动态生成结构,但我相信问题出在纯CSS / HTML(我想避免使用javascript生成此结构)。

Thanks in Advance 提前致谢

I finally manage to fix this by using css grids. 我终于设法通过使用CSS网格来解决此问题。

The following is a mock with the essential, but of course I will use real data (as well as an image that loads properly). 以下是对基本内容的模拟,但我当然会使用真实数据(以及正确加载的图像)。

The key was in using grid-template-columns and ng-style to dynamically assign the number of columns 关键在于使用grid-template-columnsng-style动态分配列数

I am still missing the custom scrollbar next to the images, but I believe that's another story 我仍然缺少图像旁边的自定义滚动条,但是我相信这是另一回事了

 (function(){ function reportingTableController() { this.recommendations = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] } angular .module('app', []) .component('reportingTable', { template: `<div class="reporting-table-container" ng-style="{'grid-template-columns': '90px repeat({{$ctrl.recommendations.length + 1}}, 130px)'}"> <div style="grid-row:1;" class="row-label-title"></div> <div style="grid-row:2;" class="row-label-title">ID</div> <div style="grid-row:3;" class="row-label-title">Product Title</div> <div style="grid-row:4;" ng-style="{'grid-column-end': $ctrl.recommendations.length + 2}" class="orange-delimiter"></div> <div style="grid-row:5;" class="row-label-title">Strategy Name</div> <div style="grid-row:6;" class="row-label-title">Score</div> <div style="grid-row:7;" class="row-label-title">Message</div> <div style="grid-row:8" ng-style="{'grid-column-end': $ctrl.recommendations.length + 2}" class="orange-delimiter">></div> <div style="grid-row:9;" class="row-label-title">Feedback</div> <div style="grid-row:10;" class="row-label-title">Clicks</div> <div style="grid-row:11;" class="row-label-title">Conversion Rate</div> <div style="grid-row:12;" class="row-label-title">Revenue</div> <div ng-class-even="'even-cell'" class="reporting-table-cell" ng-style="{'grid-row': 1, 'grid-column': $index + 2 }" ng-repeat="recommendation in $ctrl.recommendations"> <img src="Angular/app/RecommendationsTab/mock.png" alt="recommendation image" /> </div> <div ng-class-even="'even-cell'" class="reporting-table-cell" ng-style="{'grid-row': 2, 'grid-column': $index + 2 }" ng-repeat="recommendation in $ctrl.recommendations"> 2249 </div> <div ng-class-even="'even-cell'" class="reporting-table-cell" ng-style="{'grid-row': 3, 'grid-column': $index + 2 }" ng-repeat="recommendation in $ctrl.recommendations"> 25.5 cu. ft. French Door Refrigerator in Stainless Steel </div> <div ng-class-even="'even-cell'" class="reporting-table-cell" ng-style="{'grid-row': 5, 'grid-column': $index + 2 }" ng-repeat="recommendation in $ctrl.recommendations"> Online co-purchase 2wks </div> <div ng-class-even="'even-cell'" class="reporting-table-cell" ng-style="{'grid-row': 6, 'grid-column': $index + 2 }" ng-repeat="recommendation in $ctrl.recommendations"> 230 </div> <div ng-class-even="'even-cell'" class="reporting-table-cell" ng-style="{'grid-row': 7, 'grid-column': $index + 2 }" ng-repeat="recommendation in $ctrl.recommendations"> Customer also bough this other item </div> <div ng-class-even="'even-cell'" class="reporting-table-cell" ng-style="{'grid-row': 9, 'grid-column': $index + 2 }" ng-repeat="recommendation in $ctrl.recommendations"> Mailbox </div> <div ng-class-even="'even-cell'" class="reporting-table-cell" ng-style="{'grid-row': 10, 'grid-column': $index + 2 }" ng-repeat="recommendation in $ctrl.recommendations"> 43 </div> <div ng-class-even="'even-cell'" class="reporting-table-cell" ng-style="{'grid-row': 11, 'grid-column': $index + 2 }" ng-repeat="recommendation in $ctrl.recommendations"> 0.50% </div> <div ng-class-even="'even-cell'" class="reporting-table-cell" ng-style="{'grid-row': 12, 'grid-column': $index + 2 }" ng-repeat="recommendation in $ctrl.recommendations"> $282.830 </div> </div>`, controller: reportingTableController, }); })(); 
 .reporting-table-container { display:grid; padding-right: 10px; margin-bottom: 15px; margin-left: 25px; background-color: white; overflow-x: scroll; } .reporting-table-container .row-label-title { font-weight: 800; left: 0; position: sticky; grid-column: 1; } /* grid cells*/ .reporting-table-container > div { padding-left: 6px; padding-right: 6px; padding-top: 8px; padding-bottom: 10px; } .reporting-table-container .row-label-title, .reporting-table-container .reporting-table-cell.even-cell { background-color: #e9e9e9; } .reporting-table-container .reporting-table-cell, .reporting-table-container .row-label-title { border-bottom: #d1d1d1 1px solid; } .reporting-table-container .row-label-title:first-of-type { background-color: white; border-bottom: none; } .reporting-table-container .orange-delimiter { border: 1px solid #f96302; background-color: white; grid-column-start: 1; height: 1px; margin-bottom: 3px; margin-top: 3px; padding: 0; } .reporting-table-container .reporting-table-cell > img { max-width: calc(100% - 12px);/* 12 px of padding*/ } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.2/angular.min.js"></script> <body> <div ng-app="app"> <reporting-table></reporting-table> </div> </body> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM