灵活的CSS网格表


查看线索列表(冷接触)

自从我们开始以来,我终于可以谈谈过去两年来我一直在从事的一个秘密项目。 团队合作CRM的有趣功能之一是列表视图。

这是一个功能强大的组件,在应用程序中发生了七次。 实际上,有一张关于类固醇的表格。 我可以说很多,但我不想让您感到无聊。 我将重点介绍如何仅用几行CSS(网格)来实现这种灵活性。 即,我们如何布置大量数据表,如何支持列大小调整等等。

首先,需要从这些表的目的和设计任务入手说明上下文。 如果不感兴趣,请立即立即进行技术实施

首先,我们的解决方案使客户能够快速查看列表(例如,线索或联系人)并注意重要的细节。 它看起来不像是Excel电子表格-如果其中有很多,我们最好处理数据布局。

绝对一切都可以在自适应灵活设计中进行。 我们从最窄的选项开始,然后根据内容,设计和用例(我们没有面向设备的断点)自定义布局。

在最小屏幕宽度下,列垂直堆叠,占据整个屏幕宽度。


列表在狭窄的屏幕上看起来像什么

灵活的表格并不容易做到。 您可以从几个现有模板中进行选择。 考虑用户正在寻找什么信息并明智地选择。

一旦我们在屏幕上有足够的像素,我们就会切换到更典型的布局,以使列...成为列。 然后,布局没有重大变化,但我们仍然希望为客户显示尽可能方便的列。

假设我们有很多列(稍后我们将介绍用户如何自定义它们)。 首先,桌子至少应填满屏幕宽度。 其次,列的宽度应由其内容和值的类型确定。 例如,短/长文本,日期,数字,URL等。带有日期的列应比长文本的列占用更少的空间。

列必须具有最小宽度。 结果通常是一个可以垂直和水平滚动的表格。


布局如何取决于窗口的宽度。 抱歉,GIF抽搐了,稍后我将给您一些交互式示例。

首先,最大程度地使用表格的旧式常规CSS。 然后,我们使用CSS Grid对其进行改进。 然后,我将展示用户如何使用Grid工具来调整列的大小,而这对于常规CSS而言不便得多。

好了,已经展示了CSS Grid


我不是CSS Grid专家,但我喜欢它。 这是一个非常强大且简单的工具,它以最少的代码实现了复杂的布局。 在这里,我将跳过技术介绍。 您可以阅读Rachel Andrew 撰写的The New CSS LayoutsThe Complete Grid Guide 。 当您结束思考此工具一生的用途时,请回到我身边。

首先,将display:grid应用于<table>以将表转换为网格。 这不会破坏任何内容:如果浏览器不支持Grid,则它将使用display:table 。 子元素<thead><tbody>成为网格元素。 我们不需要考虑<thead><tbody>甚至<tr> 。 我们想通过对每个栅格应用display:grid (即,栅格内部的栅格)在此栅格上布置<th><td> ,但这并不理想。 每个<tr>网格都将独立于其他网格,这并不好(稍后您将看到Flexbox同样的问题)。

解决方法是使用display:contents <thead><tbody><tr> 。 这基本上将它们从网格布局中删除,从而推动子元素( <th><td> )。

然后,我们使用魔术规则grid-template-columns控制网格元素。 是的,只有一行CSS。 例如,如果我们有一个日期列和一个URL列,它将看起来像这样:

 grid-template-columns: minmax(150px, 1.33fr) minmax(150px, 2.33fr); 

我们对所有列使用相同的最小大小,但是最大值( fr )由列的数据类型确定。 我尝试了automax-content ,但是我们想出了一个更好的选择。 这是一个简化的示例: 带有code的交互式表 。 尝试调整窗口大小。

使用网格更改列宽


此外,在我们的表格中,您可以交换,更改宽度并隐藏列。 后者之所以重要,是因为它支持许多具有不同类型数据的列:这些是元素本身的属性(例如,线索),相关元素的属性(例如,与线索相关的公司)和自定义字段。

例如,用户可以为称为“出生日期”的联系人创建自定义字段(日期),系统将为每个联系人对其进行跟踪。

由于创建自定义字段时,选择了“日期”类型,因此系统将考虑该类型来处理该字段。 首先,我将解释宽度如何变化。

  1. 当用户将光标移到列标题上方时,将在右侧显示调整大小标记。 我们在调整大小滑块上监听mousedown事件。
  2. 当用户单击滑块时,我们将绑定其他方法来侦听mousemovemousedown事件(到window )。 在这一阶段,我们还添加了一些装饰类。
  3. 当用户移动鼠标时,我们将考虑光标位置,表格滚动位置和设置的最小值来计算新的列宽。 然后我们重新设置<table>grid-template-columns规则(通过style属性),这次用一个像素替换最大值( fr )。 例如, grid-template-columns: minmax(150px, 1.33fr) 296px; 。 这是使用requestAnimationFrame完成的,以提供尽可能平滑的动画。
  4. mouseup到达时,我们取消事件侦听器并删除类。

尝试这个简化的示例

值得注意的是,仅更新DOM中的一个元素,而不更新每个单元就足够了。

我们总是根据触摸输入来开发UI,但是在这种情况下,不支持它是很正常的。 这太准确了。 即使我想在触摸屏上调整列的大小,也可能希望进行其他交互,例如通过多点触摸手势。

固定宽度列


您可能已经注意到您对某些事情保持沉默。 实际上,不仅一列的宽度改变,而且所有列的宽度改变。 也许您甚至没有注意到这一点,因为这就是它的工作方式。

最初,我以为用户会喜欢它:拉伸或压缩列时,其他人也会进行调整。 如果这些列恰好填满了屏幕的宽度,并且您将其中的一列缩小了,那么如果其中的内容不适合一行,则其他列可以扩大。 试试这个例子

但是经过一些用户测试,事实证明,对于人们来说,这是一种意外的行为。 当用户的动作引起不可预测的副作用时,用户会感到一定程度的失控。

我们不应该基于哪些列交互而哪些不交互来进行假设。 在调整一列的大小时,用户已经可以隐式地确定其余列的宽度是完美的。

因此,如果您是第一次打开该应用程序,则以最佳方式对列进行布局。 如果更改屏幕大小,则列也将根据相同原理更改。 触摸滑块以调整任何列的大小后,所有可见列的宽度就会固定。


更改列宽之前,期间和之后。 再次抱歉,GIF抽搐了一下

每次调整列大小或固定列大小时,我们都会创建一个独立的localStorage记录,该记录将列标识符与像素值匹配以保留用户首选项。

我不记得为什么我们决定设置一个固定的像素值,而不是自适应选项。 也许是为了简单起见。 或因为在不支持Grid和display:contents回滚到了一种更古老的方法来调整列宽。

在任何情况下,自适应选项都可能与用户的意图不符。 我们不能认为对他来说最重要的事情是使所有列变小,以便它们都保留在屏幕上。 如果某人更改了列的宽度,则他想在此列中看到一定数量的内容。 如果我们有一个自适应块,然后它在一个较小的窗口中变窄,那么我们将忽略该人的选择。 他将不得不再次更改列宽才能看到相同的内容。 用户不太可能会想:“嗯,我希望此列占据窗口的20%,即使我更改了它也是如此。” 但是,我过于深入地研究了边界问题:实际上,用户很少调整窗口的大小。

移动和删除列



自定义显示列的界面

假设用户通过此界面更改了一组列。 如果先前未更改任何选定列,则将使用默认值grid-template-column来显示它们,具体取决于数据类型。 例如, minmax(150px, 3.33fr)

如果在localStorage中列的宽度是固定的,我们将固定所有选定列的宽度,并将这些值存储在localStorage中。

随着时间的流逝,越来越多的列保持固定的宽度。 对于用户而言,返回到响应式设计的唯一方法是重置列。

我们还将列标识符数组存储在localStorage中,与宽度条目分开。

“为什么不只使用{{libraryName}}?”


使用JavaScript库,该解决方案将变得笨拙,棘手,不会提供交互性,甚至可能根本不支持<table>。 我也不想写这样的东西。 我以为:“一定有更好的办法。”

“为什么不只使用Flexbox?”


每行将独立评估/显示。 由于内容量不同,该列可能无法与上面的列对齐。

对于内部具有垂直分组单元的列,我可以切换到<div>。 但是不想这样做。 我想使用<table>。 另外,我们很容易遇到其他问题:例如,列之间的单元格高度不匹配。

“为什么不只使用<colgroup> ?”


实际上, <colgroup>是一个方便的旧元素。 在使用<col>定义列之后,应用于一个的样式将有效地应用于该列中的所有单元格。

但是,事实证明,这种解决方案太有限了。 我们尝试过,但很快就拒绝了。 太快了,我不记得确切的问题了。 我几乎可以肯定,不可能达到理想的适应性水平,并且它不适用于Flexbox和Grid。

“为什么不只使用表格布局:固定?”


我可以在<table>上应用table-layout: fixed规则,并将列宽设置为百分比。 但是查看示例并遵循此规则,我得到的印象是它仅适用于100%宽的桌子。 此外,调整一列的大小会更改其他列的大小,以达到100%的总宽度。

“但是您可以通过简单的桌子来度过!”


是的,开箱即用的表格可以处理许多聪明的事情,但是它们不能有效地支持我想要实现的所有功能。 不同意吗? 好吧,向导,教我。

不要对显示内容走得太远


display: contents值允许保存表布局。 仅在确实需要时使用它。 一些浏览器在可访问性和屏幕阅读器上存在或至少存在问题。

我们发现了一个奇怪的 display: contents在Firefox中通过本机拖放操作导致display: contents 错误

幸运的是,将很快释放一个子网格功能,该功能将允许子元素正确集成到网格中。 在我们的应用程序中,我们只想简化标记,但是子网将为通向多维网格的狂欢敞开大门。 请参阅“为什么显示:内容不是CSS网格布局”

我想我忘记了什么


调整列大小时似乎仍然存在文本溢出的问题,但我记不清了。

为了在向下滚动时保存表头,我们使用position: sticky 。 这是一个很大的增强,并且在较旧的浏览器中会降级得很好。 但是,对于IE11用户,我们有备用JavaScript。 实际上,我不推荐position: sticky由于水平滚动的困难而发position: sticky

我什至没有提到我们列表视图的某些功能。 例如,用户可以应用,保存和交换自定义过滤器(例如,与欧洲的潜在客户展示500美元以上的销售线索)。 在这些过滤器中,您可以记住一组列,以始终显示特定工作流程的特定列。

很快,我们将在列表视图中实现批量编辑,并将自定义视图导出到CSV。

无论如何,感谢您的阅读。

Source: https://habr.com/ru/post/zh-CN452922/


All Articles