{"id":6557,"date":"2010-06-21T05:12:58","date_gmt":"2010-06-21T12:12:58","guid":{"rendered":"http:\/\/css-tricks.com\/?p=6557"},"modified":"2011-06-18T09:49:15","modified_gmt":"2011-06-18T16:49:15","slug":"feature-table-design","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/feature-table-design\/","title":{"rendered":"Feature Table Design"},"content":{"rendered":"

I ran into the feature table design from Shopify<\/a> over on Pattern Tap<\/a> and I was like DAMN SHOPIFY, that is one sexy table. I was inspired to try and replicate it. First in Photoshop, then in HTML\/CSS. Recreating cool stuff you find on the web is definitely an excercise I recommend (a few days after, I read this<\/a> – couldn’t agree more). As these exercises typically do, it lead me down some interesting paths. <\/p>\n

Here’s my knockoff:<\/p>\n

\"\"<\/p>\n

View Demo<\/a>   Download Files<\/a><\/p>\n

<\/p>\n

The Markup<\/h3>\n

Here is the abreiveated HTML:<\/p>\n

<table id=\"feature-table\">\r\n  <colgroup class=\"basic\"><\/colgroup>\r\n  <colgroup class=\"plus\"><\/colgroup>\r\n  <colgroup class=\"premium\" id=\"featured\"><\/colgroup>\r\n  <colgroup class=\"pro\"><\/colgroup>\r\n\t<thead>\r\n\t\t<tr>\r\n\t\t\t<th id=\"header-basic\"><span>$15 Basic<\/span> <a class=\"button\" href=\"#\">Sign Up<\/a><\/th>\r\n\t\t\t<th id=\"header-plus\"><span>$35 Plus<\/span><a class=\"button\" href=\"#\">Sign Up<\/a><\/th>\r\n\t\t\t<th id=\"header-premium\"><span>$99 Premium<\/span><a class=\"button\" href=\"#\">Sign Up<\/a><\/th>\r\n\t\t\t<th id=\"header-pro\"><span>$150 Pro<\/span><a class=\"button\" href=\"#\">Sign Up<\/a><\/th>\r\n\t\t<\/tr>\r\n\t<\/thead>\r\n\t<tbody>\r\n\t\t<tr>\r\n\t\t\t<td>50 pages<\/td>\r\n\t\t\t<td>75 pages<\/td>\r\n\t\t\t<td>Unlimited<\/td>\r\n\t\t\t<td>Unlimited<\/td>\r\n\t\t<\/tr>\r\n    <!-- More rows here -->\r\n\t<\/tbody>\r\n<\/table><\/code><\/pre>\n

Pretty clean. The only thing that isn’t perfectly clean is the <span> in the header. There is all that fancy gradient fancy font stuff going on. Theoretically, it could be done with a boatload of CSS3, but you know, sometimes an image is just fine dang nabbit, especially when it’s perfectly accessible CSS image replacement<\/a>.<\/p>\n

Of note is the <colgroup> element which I feel is underutilized. Colgroups allow you to target an entire column of table cells and apply styling, even though those table cells aren’t actually descendants of the <colgroup>. Kind of a weird concept, but it works, and it’s easier than applying a class name to every single table cell signifying what column it’s in.<\/p>\n

If you need some quick markup, I have some you can copy and paste on HTML-Ipsum<\/a>.<\/p>\n

The CSS<\/h3>\n

Each header cell (<th>) has an ID. We’ll set a static height on those and set background images for them. Vertically aligning to the bottom with a bit of bottom padding allows us to place the link button evenly. The span in those headers is kicked off the page via absolute positioning (i.e. accessible hiding).<\/p>\n

#feature-table th { height: 120px; padding-bottom: 14px; vertical-align: bottom; }\r\n#header-basic { background: url(..\/images\/header-15.png) no-repeat; }\r\n#header-plus { background: url(..\/images\/header-35.png) no-repeat; }\r\n#header-premium { background: url(..\/images\/header-99.png) no-repeat; }\r\n#header-pro { background: url(..\/images\/header-150.png) no-repeat; }\r\n#feature-table th span { position: absolute; top: -9999px; left: -9999px; }<\/code><\/pre>\n

\"\"<\/p>\n

Speaking of those buttons. I just used the CSS Button Maker<\/a> to quickly design a button I thought looked nice and fit with the color scheme, and copy and pasted the CSS into this demo.<\/p>\n

To color the cells, I set a fallback hex code color and then an HSLa color value<\/a>. These class names are targeting the colgroup elements.<\/p>\n

.basic   { background-color: #d5e4bc; background-color: hsla(85,  30%, 80%, 1); }\r\n.plus    { background-color: #c1dcb7; background-color: hsla(110, 30%, 80%, 1); }\r\n.premium { background-color: #bad6c8; background-color: hsla(150, 30%, 80%, 1); }\r\n.pro     { background-color: #bbd3dc; background-color: hsla(190, 30%, 80%, 1); }<\/code><\/pre>\n

\"\"<\/p>\n

The final product is zebra striped and has that “featured column” thing going on. but we can approach that with JavaScript…<\/p>\n

The JavaScript<\/h3>\n

jQuery<\/a>, obviously. We can apply the “odd” class to odd table rows, as well as a “final-row” class with jQuery super easily:<\/p>\n

$(\"tr:odd\").addClass(\"odd\");  \/\/ Zebra action\r\n$(\"tr:last\").addClass(\"final-row\");  \/\/ For extra padding<\/code><\/pre>\n
\n\"\"<\/p>\n

The final row has extra padding<\/p>\n<\/div>\n

To handle the “featured” column, and keep things semantic, we just apply an ID to the colgroup:<\/p>\n

<colgroup class=\"premium\" id=\"featured\"><\/colgroup><\/code><\/pre>\n

Now the JavaScript needs to figure out which number column that is.<\/p>\n

\/\/ Figure out which column # is featured.\r\nvar featuredCol;\r\n$(\"colgroup\").each(function(i) {\r\n    if (this.id == \"featured\") featuredCol = i+1;\r\n});<\/code><\/pre>\n

Now we’re going to loop through all the table cells and figure out if the cell is in the column right before the featured column (if it is, apply a “leftOfFeatured” class) or in the column right after the featured column (if it is, apply a “rightOfFeatured” class). <\/p>\n

While we are at it, we might as well apply class names to all table cells indicating their column. Colgroups were supposed to eliminate that need, but it turns out they have a fairly significant weakness. You can’t do something like:<\/p>\n

.basic .odd { \r\n   \/* \r\n      .basic is the colgroup, .odd is the row\r\n      the row really isn't a descendant of the colgroup \r\n      in other words, this doen't work\r\n   *\/\r\n}<\/code><\/pre>\n

This design calls for different color alterations depending on the column. So while we are running that loop, we’ll just apply class names to the table cells and use those class names to do our bidding.<\/p>\n

\/\/ Apply classes to each table cell indicating column\r\n\/\/ Also applies classes if cell is right or left of featured column\r\n\r\nvar numCols = $(\"colgroup\").length;\r\n\r\n$(\"td, th\").each(function(i) {\r\n    $(this).addClass(\"table-col-\" + ((i % numCols) + 1));\r\n    if (((i%numCols)+1) == (featuredCol-1)) $(this).addClass(\"leftOfFeatured\");\r\n    if (((i%numCols)+1) == (featuredCol+1)) $(this).addClass(\"rightOfFeatured\");\r\n});<\/code><\/pre>\n

The variable i in this function is the index. It basically tells us what iteration of the loop we are on. So the 50th table cell it finds, the index will be 49 (index is zero-indexed). So if we take the index modulus the number of columns (determined by testing the length of the jQuery set) and add one, we’ll have what number column the cell is in. Example: 4 columns, 10th cell found. 9 % 4 = 1<\/a>, plus 1 is 2, so the 10th cell is in the 2nd column. And thus, that cell gets the class “table-col-2”.<\/p>\n

With the row .odd classes and the new table-col-x classes, we can now truly zebra stripe as the design demands:<\/p>\n

.odd .table-col-1 { background-color: #edf3e2; background-color: hsla(85,  30%, 94%, 1); }\r\n.odd .table-col-2 { background-color: #edf3e2; background-color: hsla(110, 30%, 94%, 1); }\r\n.odd .table-col-3 { background-color: #edf3e2; background-color: hsla(150, 30%, 94%, 1); }\r\n.odd .table-col-4 { background-color: #e2ecf0; background-color: hsla(190, 30%, 94%, 1); }<\/code><\/pre>\n
\n\"\"<\/p>\n

Zebra action complete.<\/p>\n<\/div>\n

Notice it’s hex code fallbacks and HSLa again. The fun of using HSLa here was that the values are exactly the same except for the third value (the “lightness”). We increase that value 14% and that is the noticeable difference in tone.<\/p>\n

The “leftOfFeatured” and “rightOfFeatured” classes apply a background image, just an alpha-transparent PNG shadow aligned and repeating to the left or right respectively.<\/p>\n

\n\"\"\n<\/div>\n
.leftOfFeatured  { background-image: url(..\/images\/shadow-left.png);  background-repeat: repeat-y; background-position: right center; }\r\n.rightOfFeatured { background-image: url(..\/images\/shadow-right.png); background-repeat: repeat-y; background-position: left  center; }<\/code><\/pre>\n

Conclusion<\/h3>\n

So that’s it folks. It was fun for me to try and recreate something I thought was awesome, but just in a “this is how I would do it” kinda way rather than peaking at any of their code. I highly recommend this kind of exercise, if your schedule allows.<\/p>\n

View Demo<\/a>   Download Files<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"

I ran into the feature table design from Shopify over on Pattern Tap and I was like DAMN SHOPIFY, that is one sexy table. I was inspired to try and replicate it. First in Photoshop, then in HTML\/CSS. Recreating cool stuff you find on the web is definitely an excercise I recommend (a few days […]<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0,"sig_custom_text":"","sig_image_type":"featured-image","sig_custom_image":0,"sig_is_disabled":false,"inline_featured_image":false,"c2c_always_allow_admin_comments":false,"footnotes":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":[]},"categories":[4],"tags":[],"jetpack_publicize_connections":[],"acf":[],"jetpack_featured_media_url":"","jetpack-related-posts":[{"id":153095,"url":"https:\/\/css-tricks.com\/new-t-shirts-new-store\/","url_meta":{"origin":6557,"position":0},"title":"New T-Shirts! New Store!","date":"October 16, 2013","format":false,"excerpt":"Hey hey everybody, I made some new shirts! I wanted some T-Shirts that were more of just the straight CSS-Tricks logo type. So I had some made up. While I was at it, I moved the entire store system (as you do). Now on Shopify The store is now hosted\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":236836,"url":"https:\/\/css-tricks.com\/designing-a-product-page-layout-with-flexbox\/","url_meta":{"origin":6557,"position":1},"title":"Designing A Product Page Layout with Flexbox","date":"January 15, 2016","format":false,"excerpt":"Every day at Shopify I speak with Partners who are constantly pushing the boundaries of what's possible in ecommerce design. Recently, I've noticed a number of designers are experimenting with Flexbox in their stores. As web designers and developers, one of our primary goals is to bring focus to content\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":247100,"url":"https:\/\/css-tricks.com\/designing-svg-scalable-vector-graphics-can-increase-visitor-engagement\/","url_meta":{"origin":6557,"position":2},"title":"Designing with SVG: How Scalable Vector Graphics Can Increase Visitor Engagement","date":"October 27, 2016","format":false,"excerpt":"I did an online seminar (organized by Shopify) in which I gave my \"10 Things You Can & Should Do With SVG\" talk. You can watch the video at this link. Sara Chisholm busted it out into an article that covers some of my points and embeds some of the\u2026","rel":"","context":"In "Link"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":358344,"url":"https:\/\/css-tricks.com\/links-on-wordpress-i\/","url_meta":{"origin":6557,"position":3},"title":"Links on WordPress I","date":"December 8, 2021","format":false,"excerpt":"I try to keep up with WordPress news because I'm a big WordPress user and have many production sites that run on it. WordPress has been good to me as a site builder for literally my entire career. So, like we do with typography (example), accessibility (example), and JavaScript (example),\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2021\/06\/wordpress-logo-sketch.png?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":259782,"url":"https:\/\/css-tricks.com\/upgrade-javascript-error-monitoring\/","url_meta":{"origin":6557,"position":4},"title":"Upgrade Your JavaScript Error Monitoring","date":"September 7, 2017","format":false,"excerpt":"Automatically detect and diagnose JavaScript errors impacting your users with Bugsnag. Get comprehensive diagnostic reports, know immediately which errors are worth fixing, and debug in a fraction of the time compared to traditional tools. Bugsnag detects every single error and prioritizes errors with the greatest impact on your users. Get\u2026","rel":"","context":"In "Link"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2017\/09\/bugsnag.jpg?fit=450%2C325&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":254868,"url":"https:\/\/css-tricks.com\/websites-like-may-2017\/","url_meta":{"origin":6557,"position":5},"title":"Websites We Like: May 2017","date":"May 18, 2017","format":false,"excerpt":"It\u2019s been far too long since we rounded up some of the most interesting websites out there. But this time we have a diverse round-up of whacky interfaces and beautiful layouts to look at. Let's dive straight in! Nick Jones' Portfolio The portfolio of Nick Jones is one of the\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"featured_media_src_url":null,"_links":{"self":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/6557"}],"collection":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/comments?post=6557"}],"version-history":[{"count":15,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/6557\/revisions"}],"predecessor-version":[{"id":9840,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/6557\/revisions\/9840"}],"wp:attachment":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/media?parent=6557"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/categories?post=6557"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/tags?post=6557"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}