我在 Shopify 上的 Pattern Tap 遇到了特性表格设计,我当时就觉得,哇,Shopify,这表格太性感了。我受到启发,尝试复制它。首先是在 Photoshop 中,然后是在 HTML/CSS 中。重现你在网络上发现的酷炫事物绝对是我推荐的练习(几天后,我读了 这篇 文章——我完全同意)。像往常一样,这些练习让我走上了一些有趣的道路。
这是我的仿制品
标记
以下是简化的 HTML 代码
<table id="feature-table">
<colgroup class="basic"></colgroup>
<colgroup class="plus"></colgroup>
<colgroup class="premium" id="featured"></colgroup>
<colgroup class="pro"></colgroup>
<thead>
<tr>
<th id="header-basic"><span>$15 Basic</span> <a class="button" href="#">Sign Up</a></th>
<th id="header-plus"><span>$35 Plus</span><a class="button" href="#">Sign Up</a></th>
<th id="header-premium"><span>$99 Premium</span><a class="button" href="#">Sign Up</a></th>
<th id="header-pro"><span>$150 Pro</span><a class="button" href="#">Sign Up</a></th>
</tr>
</thead>
<tbody>
<tr>
<td>50 pages</td>
<td>75 pages</td>
<td>Unlimited</td>
<td>Unlimited</td>
</tr>
<!-- More rows here -->
</tbody>
</table>
非常简洁。唯一不那么干净的地方是标题中的 <span>。那里有所有那些花哨的渐变和花哨的字体样式。理论上,可以使用大量的 CSS3 来实现,但你知道,有时一张图片就足够了,特别是当它完全可访问时 CSS 图片替换。
值得注意的是 <colgroup> 元素,我认为它被低估了。Colgroup 允许你定位表格单元格的整列并应用样式,即使这些表格单元格实际上不是 <colgroup> 的后代。有点奇怪的概念,但它确实有效,而且比在每个表格单元格上应用一个类名来表示它所在的列更容易。
如果你需要一些快速标记,我有一些你可以复制粘贴到 HTML-Ipsum 上。
CSS 代码
每个表头单元格 (<th>) 都有一个 ID。我们将为它们设置一个静态高度并为其设置背景图片。通过一点底部填充垂直对齐到底部,我们可以使链接按钮均匀放置。这些标题中的 span 通过绝对定位(即可访问隐藏)被踢出页面。
#feature-table th { height: 120px; padding-bottom: 14px; vertical-align: bottom; }
#header-basic { background: url(../images/header-15.png) no-repeat; }
#header-plus { background: url(../images/header-35.png) no-repeat; }
#header-premium { background: url(../images/header-99.png) no-repeat; }
#header-pro { background: url(../images/header-150.png) no-repeat; }
#feature-table th span { position: absolute; top: -9999px; left: -9999px; }
说到这些按钮。我只是使用了 CSS 按钮生成器 来快速设计一个我认为看起来不错且符合配色方案的按钮,并将 CSS 复制粘贴到此演示中。
要为单元格着色,我设置了一个回退十六进制颜色代码,然后是一个 HSLa 颜色值。这些类名正在定位 colgroup 元素。
.basic { background-color: #d5e4bc; background-color: hsla(85, 30%, 80%, 1); }
.plus { background-color: #c1dcb7; background-color: hsla(110, 30%, 80%, 1); }
.premium { background-color: #bad6c8; background-color: hsla(150, 30%, 80%, 1); }
.pro { background-color: #bbd3dc; background-color: hsla(190, 30%, 80%, 1); }
最终产品是斑马纹,并且具有“特色列”的功能,但我们可以用 JavaScript 来实现它……
JavaScript 代码
jQuery,显然。我们可以将“odd”类应用于奇数行表格行,以及使用 jQuery 超级轻松地应用“final-row”类
$("tr:odd").addClass("odd"); // Zebra action
$("tr:last").addClass("final-row"); // For extra padding

最后一行有额外的填充
为了处理“特色”列,并保持语义,我们只需在 colgroup 上应用一个 ID
<colgroup class="premium" id="featured"></colgroup>
现在 JavaScript 需要找出该列的列号。
// Figure out which column # is featured.
var featuredCol;
$("colgroup").each(function(i) {
if (this.id == "featured") featuredCol = i+1;
});
现在我们将遍历所有表格单元格,并确定单元格是否位于特色列之前的列(如果是,则应用“leftOfFeatured”类)或特色列之后的列(如果是,则应用“rightOfFeatured”类)。
趁此机会,我们不妨将类名应用于所有指示其列的表格单元格。Colgroup 应该消除了这种需求,但事实证明它们有一个相当大的弱点。你不能做这样的事情
.basic .odd {
/*
.basic is the colgroup, .odd is the row
the row really isn't a descendant of the colgroup
in other words, this doen't work
*/
}
此设计要求根据列进行不同的颜色更改。因此,当我们运行该循环时,我们将只将类名应用于表格单元格并使用这些类名来执行我们的操作。
// Apply classes to each table cell indicating column
// Also applies classes if cell is right or left of featured column
var numCols = $("colgroup").length;
$("td, th").each(function(i) {
$(this).addClass("table-col-" + ((i % numCols) + 1));
if (((i%numCols)+1) == (featuredCol-1)) $(this).addClass("leftOfFeatured");
if (((i%numCols)+1) == (featuredCol+1)) $(this).addClass("rightOfFeatured");
});
此函数中的变量 i 是索引。它基本上告诉我们循环的哪个迭代我们正在进行。因此,它找到的第 50 个表格单元格,索引将为 49(索引是从零开始的)。因此,如果我们取索引模数列数(通过测试 jQuery 集的长度确定)并加 1,我们将得到单元格所在的列号。例如:4 列,找到第 10 个单元格。 9 % 4 = 1,加 1 是 2,所以第 10 个单元格在第 2 列。因此,该单元格获得类“table-col-2”。
使用行 .odd 类和新的 table-col-x 类,我们现在可以根据设计要求真正地创建斑马纹效果
.odd .table-col-1 { background-color: #edf3e2; background-color: hsla(85, 30%, 94%, 1); }
.odd .table-col-2 { background-color: #edf3e2; background-color: hsla(110, 30%, 94%, 1); }
.odd .table-col-3 { background-color: #edf3e2; background-color: hsla(150, 30%, 94%, 1); }
.odd .table-col-4 { background-color: #e2ecf0; background-color: hsla(190, 30%, 94%, 1); }

斑马纹效果完成。
注意,它又是十六进制代码回退和 HSLa。在这里使用 HSLa 的乐趣在于,除了第三个值(“亮度”)之外,所有值都完全相同。我们将该值增加 14%,这就是明显的色调差异。
“leftOfFeatured”和“rightOfFeatured”类应用背景图片,只是一个分别向左或向右对齐和重复的 alpha 透明 PNG 阴影。

.leftOfFeatured { background-image: url(../images/shadow-left.png); background-repeat: repeat-y; background-position: right center; }
.rightOfFeatured { background-image: url(../images/shadow-right.png); background-repeat: repeat-y; background-position: left center; }
结论
就是这样,朋友们。尝试重现我认为很棒的东西对我来说很有趣,但只是以“这是我将如何做”的方式,而不是查看他们的任何代码。如果您时间允许,我强烈推荐这种练习。
如果我这么说的话,仿制品非常棒。
嘿,Chris,
这是一篇非常棒的文章,我认为它不仅适用于 HTML 和 CSS。这真的激励我尝试在我的最新关于图形设计灵感的帖子中尝试一些东西,该帖子发表在 http://mographtv.com 上。
尝试重新创建漂亮的设计来增强我自己的感觉会很棒。
很棒的文章,
干杯。
正是医生开的药,非常感谢,Chris,你是最棒的!!!
不错的文章,不过有个错别字。excise 应该是 exercise。
看起来真的很棒,而且组织得很好。对像我这样的设计新手来说很有用 :)
顺便说一句,我在您的演示页面上看到您有“HTML Rockstars”的广告。我看了一下他们的网站,并查看了源代码。天哪,那真是令人毛骨悚然的标记。
每行都在 HTML 属性之前断开。它看起来就是不对劲。不过它通过了验证,所以我想这是一件好事……
从没想过我们可以用表格来做这个。
完美。这太酷了。
哇,感谢 Chris 的好意,并没有对我的标记太苛刻——它肯定可以改进 :)
Chris,
不确定这是否有效,但我敢打赌,如果你在 colgroup 中添加一个悬停属性,你也可以做一些很酷的样式。很想看到更新后的内容。
-Chris
嘿,Chris,又一篇很棒的文章,并附带示例。我经常使用您的示例来学习,它们对我来说非常宝贵。当我有机会时,我会将其他人推荐到您的网站,以便他们向大师学习 :) 您真是太棒了,Chris。
继续保持良好的状态,感谢您所做的一切,伙计。
Jim Zak
<colgroup> 是否基本上做同样的事情或是否不需要 <th scope=”col”>?我以前从未使用过 colgroup。
在您的表格中添加一个 summary 属性将是一个不错的补充。
我承认我很少使用 scope。我认为 scope 的重点是在声明此表头是哪组单元格的表头方面提供更好的可访问性。例如,在此表格中,<th> 元素是信息列的表头,但 <th> 也可用于作为数据行的表头。因此,您应该对其进行限定以声明它是哪一个。
<colgroup> 另一方面,实际上允许您将样式应用于一列单元格,尽管 <colgroup> 元素实际上并没有“包装”任何这些单元格。
这太棒了,我不会用 jQuery 在这里做任何魔法,但我真的很喜欢你在这方面的所有理念,Chris。
探索选项,分解它,构建它,并在任何适合你那个特定时刻的方式中达到最终目标。
你的文章在技术方面 100% 的时间都是完美且合适的。
现在,如果你使用 Flash 来实现上述目标,那将会很有趣。我敢挑战你。
非常棒,Chris!我喜欢你说的关于重现启发你的事物——我完全同意。
顺便说一句,我想知道你为什么使用 jQuery 来添加交替样式而不是 :nth-of-type?这似乎是该选择器的完美应用 :)
太棒了!!!Chris,你技术超群……
非常感谢。这篇文章太棒了 :) 一个问题,我们如何将 PSD 价格表转换为 HTML?因为网上有很多漂亮的 PSD 价格表,但我想知道人们如何用 CSS 编写它们?
优秀,Chris。非常易于理解,并且是创建优秀表格设计的绝佳基础。
我会把“特色”列设置得稍微宽一些。
阴影让该列看起来像是前景,因此应该显得更大。
我去过 Shopify,他们就是这么做的。
嗨,感谢分享你的想法。
一个小提示:与其遍历元素,我们可以使用 jQuery 的“index()”方法,我认为这非常方便。
// 找出哪一列是特色列。
var featuredCol = (“colgroup”).index($(“#featured”));
一如既往的好文章.. ;)
首先,内容相当无聊……
其次,更重要的是,为什么使用 JavaScript,而所有这些都可以用 CSS 独自完成?这个页面不是叫做 CSS-tricks 吗?当然,tr:odd / tr:nth-child 并不适用于所有浏览器,但它是 CSS,所以你至少应该提到它!
你可以在没有数百个类属性(以及没有 js!)的情况下完成整个操作,nth-child 万岁!
还有一件事……为什么每次都用 jQuery?你有没有尝试过其他 js 框架(好吧,jQuery 不是框架,而是一个工具包……)?显然没有……这个网站的名字不是“jQuery-Tricks”,对吧?
抱歉,但我每次看到这里愚蠢的 jQuery 而不是流畅的 CSS 时,都会感到非常恼火,一次又一次……
非常同意——让我们多用一些 CSS,少用一些图像替换,以及少用 jQuery——如果你真的必须用 JavaScript 做一些事情,那么至少用纯 JavaScript 来做,以便任何人都可以使用它。
我知道,真的,这个博客真的变得一团糟了。作者总是发布他个人感兴趣的东西,使用与他所了解的技术相关的技术,并将其与他的工作生活联系起来。他应该闭嘴,开始像任何体面的网页设计博客一样做汇总。我们都应该取消订阅,并重新开始在 Digg 上发帖。
哈哈,做得好,Chris,做得好
我认为 tom317 说得有道理。尽管如此,这篇文章确实包含了“CSS 技巧”,以及其他一些东西。
是的,它包含了不止几个“CSS 技巧”,这使得它看起来像是该网站的脱节内容,但如果你从 CSS 技巧开始,看看与这些技巧相关的其他内容很有趣:脚本和模仿我们在网络上看到的事物的教学。
我认为扼杀 Chris 网站的是名称:它不再仅仅是关于 CSS 技巧,而是关于 CSS 技巧、脚本、一般网页设计建议(有时还包括详细内容)。
换句话说,Chris 创建了网页设计内容,但将其框架在“CSS 技巧”这个词中,我认为这就是 tom317 有道理的地方。
格尔,博客名称!Smashing Magazine 绝对应该写关于粉碎东西的文章。Noupe 应该更加专注于“noupe”东西。
这是一个名字,伙计们。建造那座桥,然后走过去。
Chris,不要停止你正在做的事情,伙计,我喜欢你的 jQuery 教程、技巧和 TRICKS。
感谢分享。虽然我会将这种数据放在定义列表中。
@tom317:我相信你会在 css-tricks 上找到足够多的纯 css 文章 nth-child/odd 相关内容 :-D
非常好,但我认为我更佩服你的演示页面,哈哈。
Chris,
我喜欢你关于向他人学习的理念。作为一名试图在这个网页编程世界中找到自己方向的音乐家,我喜欢 37signals 链接中关于当你开始时学习曲调部分的类比。
我觉得网络上的东西在某种程度上与音乐非常相似。不同之处在于网络上有很多垃圾。感谢你回馈你所学习的社区,并为我们这些网络黑客提供你的“网络乐谱”。
我喜欢看到制作精良的表格。简洁明了。
嗨,Chris,
我是一位长期关注者,第一次评论。
在 IE 中与 Firefox 中看起来有所不同。此外,如果你想要在最后一行显示阴影,我该如何操作。
新手
没关系,我搞定了。
修改了 JavaScript 值。
很棒的文章
你好,
很棒的小文章。我通过对 jQuery 手风琴进行一些研究找到了你,并找到了你关于网格手风琴的小片段。决定进一步浏览该网站,然后我就来了……
不过,一个问题:你的解决方案使用了带有类名的 TH 来定义背景图像和一个将文本(供屏幕阅读器使用)放置在页面外的 span。为什么使用类和 span,而仅仅使用带有标题的 IMG 标签(例如“title='$15 Basic'”)就可以满足屏幕阅读器的需求?
我是不是错过了什么?
Colgroups 似乎非常适合设置背景并通过 JavaScript 访问,但令我惊讶的是,当使用字体粗细、颜色等进行样式设置时,它们存在局限性。
我们是否只能为想要设置样式的特定列添加类来设置该列文本的样式?
这真是很棒的建议,非常感谢。