Skip to main content

Table

The table component is an effective way of organizing complex information to be concise and easy to consume and compare across categories. Tables are adaptive. The MWF framework provides the markup needed and the CSS to render sorted tables properly. **Caution:** our framework does NOT deliver the functionality for sorting that is outside its scope. A team using this component must take on the burden of delivering the sorted content to the client and applying the data attributes and classes where needed as discussed under the *Options* section below.

Example

Basic table
Price
Gadget Alpha This is the amazing new Gadget Alpha.
$ 1,000
Gadget Bravo Also available is the Gadget Bravo which provides B.
$ 1,000
Gadget Charlie This is the lorem ipsumist Gadget Charlie.
$ 1,000
Gadget Delta Gadget Delta is a solor dit lipsum for consumers.
$ 1,000
Gadget Echo Gadget Echo provides solor dit for professionals.
$ 1,000
Gadget Foxtrot Another description for Foxtrot.
$ 1,000


Basic table (sortable) on a default theme

Best practices

Use a table component when you want the user to be able to quickly parse through a set of data items and compare similar data items side-by-side.

Use an action bar above the table when you want to allow the user to perform an action on one or more selected items.

Use a sortable table when the amount of data presented is overwhelming and difficult to parse. You can make columns sortable in descending and ascending order. This makes it easier to find particular items, spot trends and outliers, as well as groups of items.

Do

  • Use <h4> or <h5> headings to create an optional title for your table. Use <h4> when the table is the main content on the page. Use <h5> when it is just one of several pieces of content.
  • Tables are a good choice for presenting complex structured lists without column headers. Category headers appear as the items in the first column. You can also have sub-category headers.
  • Actions located on the action bar may be applied to one or more selected items. Other actions on the bar may affect the table as a whole, such as adding a new row.
  • Use the divider option to strengthen the visual boundaries of the row, particularly when there is a lot of horizontal space between items in columns. This helps the viewer’s eye to associate data within the same row.
  • Individual items in each row may have multiple actions available through a contextual action menu with an ellipse entry point.
  • Adding a single button for each row is another way to initiate action. Use this approach when there is only 1 available action per row. Otherwise, use an ellipse to trigger a contextual action menu.
  • Use a play icon action trigger in rows to allow inline play function for media items.
  • Rows can contain other special elements such as an explicit tag for items that kids should not see, a ratings component, a checkbox, or a call to action (to buy an item for example).
  • Have data line up wherever possible, which will help users to parse through dense data sets quickly. Generally, this means having items vertically aligned to the top so that when rows contain multiple lines, we still have a consistent flow of data within the row. Be mindful of left and right horizontal alignments for differing data types, and avoid center-aligned columns, which impede usability.
  • Right-align monetary data, numeric data and quantifier labels such as MB, GB, TB, etc.
  • Left-align text strings and mixed text/numeric strings by default. Be mindful of cases where the data types are overwhelmingly numerical, with text interspersed.

Don’t

  • Do not use tables for page layout.
  • Do not use more than one button per row in a table.
  • Do not overwhelm the user with too many columns in your table.
  • Do not forget that tables are reactive. As the viewport size diminishes, so does the width of each column. If the viewport width is less than the table minimum width, then the table will scroll horizontally.
  • Do not block horizontally scrolling tables in small viewports.

Also known as

Sort table
Sortable table
Structured list

Related

Action trigger
Button
Checkbox
Image

Accessibility

  • When sorting is set to “true,” the attributes data-f-loc-ascending="Sorted by {0} - ascending" and data-f-loc-descending="Sorted by {0} - descending" to the parent div (with class c-table) are required to inform text readers what is happening with the sort.

    Note: If you explore the rendered code for the table after sorting, there is a <p> tag at the bottom of the table with an aria-live attribute. When sorting occurs, the table writes to that <p> tag the appropriate sorting state (ascending or descending) with the header of the sorted column.
  • Each heading item has an aria-sort attribute that is set to indicate the sort state of that column. The default value is “none.”

Options

  • Sort: Add the attribute data-f-sort="true" to the <table> element to make the table sortable and style it appropriately.
  • Sort Columns: Add the class f-sortable to each sortable column header.
  • Sort Direction: Add class f-ascending or f-descending to each header to control the initial state of the up and down arrow icons.
  • Right Align: Add class f-numerical on <td> and <th> tags to right-align numerical data.
  • Row Dividers: Add class f-divided on the <div> with the class c-table to add lines between rows.
  • Column Group Breaks: Add an empty <th> and/or <td> element to separate column groups.
  • Column span: It is good practice to set the colspan value, even if it is just 1.

Development

  • Schema definition: The table schema defines the acceptable configurations, requirements, and options for each component.

Code and preview

Simple table

Table caption
 
Gadget AlphaDescription sentence.
$ 1,000
Gadget BravoDescription sentence.
$ 1,000
Gadget CharlieDescription sentence.
$ 1,000
Gadget DeltaDescription sentence.
$ 1,000
Gadget EchoDescription sentence.
$ 1,000
Gadget FoxtrotDescription sentence.
$ 1,000
<div class="c-table" data-f-loc-ascending="Sorted by {0} - ascending" data-f-loc-descending="Sorted by {0} - descending">
    <table data-f-sort="true">
        <caption>Table caption</caption>
        <thead>
            <tr>
                <th scope="col">&nbsp;</th>
                <th id="defaultDesc" scope="col" class="f-sortable" colspan="1" aria-sort="none">
                    <button aria-label="Sort by Description">Description</button>
                </th>
                <th id="defaultPrice" scope="col" class="f-sortable f-numerical" colspan="1" aria-sort="none">
                    <button aria-label="Sort by Price">Price</button>
                </th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <th scope="row">Gadget Alpha</th>
                <td>Description sentence.</td>
                <td class="f-numerical">
                    <div class="c-price" itemprop="offers" itemscope itemtype="http://schema.org/Offer">
                        <meta itemprop="priceCurrency" content="USD">
                        <span>$</span>
                        <span itemprop="price">1,000</span>
                        <link itemprop="availability" href="http://schema.org/InStock">
                    </div>
                </td>
            </tr>
            <tr>
                <th scope="row">Gadget Bravo</th>
                <td>Description sentence.</td>
                <td class="f-numerical">
                    <div class="c-price" itemprop="offers" itemscope itemtype="http://schema.org/Offer">
                        <meta itemprop="priceCurrency" content="USD">
                        <span>$</span>
                        <span itemprop="price">1,000</span>
                        <link itemprop="availability" href="http://schema.org/InStock">
                    </div>
                </td>
            </tr>
            <tr>
                <th scope="row">Gadget Charlie</th>
                <td>Description sentence.</td>
                <td class="f-numerical">
                    <div class="c-price" itemprop="offers" itemscope itemtype="http://schema.org/Offer">
                        <meta itemprop="priceCurrency" content="USD">
                        <span>$</span>
                        <span itemprop="price">1,000</span>
                        <link itemprop="availability" href="http://schema.org/InStock">
                    </div>
                </td>
            </tr>
            <tr>
                <th scope="row">Gadget Delta</th>
                <td>Description sentence.</td>
                <td class="f-numerical">
                    <div class="c-price" itemprop="offers" itemscope itemtype="http://schema.org/Offer">
                        <meta itemprop="priceCurrency" content="USD">
                        <span>$</span>
                        <span itemprop="price">1,000</span>
                        <link itemprop="availability" href="http://schema.org/InStock">
                    </div>
                </td>
            </tr>
            <tr>
                <th scope="row">Gadget Echo</th>
                <td>Description sentence.</td>
                <td class="f-numerical">
                    <div class="c-price" itemprop="offers" itemscope itemtype="http://schema.org/Offer">
                        <meta itemprop="priceCurrency" content="USD">
                        <span>$</span>
                        <span itemprop="price">1,000</span>
                        <link itemprop="availability" href="http://schema.org/InStock">
                    </div>
                </td>
            </tr>
            <tr>
                <th scope="row">Gadget Foxtrot</th>
                <td>Description sentence.</td>
                <td class="f-numerical">
                    <div class="c-price" itemprop="offers" itemscope itemtype="http://schema.org/Offer">
                        <meta itemprop="priceCurrency" content="USD">
                        <span>$</span>
                        <span itemprop="price">1,000</span>
                        <link itemprop="availability" href="http://schema.org/InStock">
                    </div>
                </td>
            </tr>
        </tbody>
    </table>
</div>

Sortable table with sub-categories

Table caption
DimensionsConnectivity
Gadget Alpha30cm2cm30cmYes3GYes
$ 1,000
Gadget Bravo20cm2cm30cmNoLTEYes
$ 1,000
Gadget Charlie30cm2cm30cmYes3GYes
$ 1,000
Gadget Delta15cm2cm30cmNoLTENo
$ 1,000
Gadget Echo30cm2cm30cmYes3GYes
$ 1,000
Gadget Foxtrot30cm2cm30cmYes3GNo
$ 1,000
<div class="c-table" data-f-loc-ascending="Sorted by {0} - ascending" data-f-loc-descending="Sorted by {0} - descending">
    <table data-f-sort="true">
        <caption>Table caption</caption>
        <thead>
            <tr>
                <th id="subcategoryItem" scope="col" class="f-sortable" colspan="1" rowspan="2" aria-sort="none">
                    <button aria-label="Sort by Item">Item</button>
                </th>
                <th id="subcategoryDimensions" scope="colgroup" colspan="3" rowspan="1">Dimensions</th>
                <th scope="colgroup"></th>
                <th id="subcategoryConnectivity" scope="colgroup" colspan="3" rowspan="1">Connectivity</th>
                <th id="subcategoryPrice" scope="col" class="f-sortable f-numerical" colspan="1" rowspan="2" aria-sort="none">
                    <button aria-label="Sort by Price">Price</button>
                </th>
            </tr>
            <tr>
                <th id="subcategoryLength" scope="col" class="f-sortable f-numerical" colspan="1" aria-sort="none">
                    <button aria-label="Sort by Length">Length</button>
                </th>
                <th id="subcategoryWidth" scope="col" class="f-sortable f-numerical" colspan="1" aria-sort="none">
                    <button aria-label="Sort by Width">Width</button>
                </th>
                <th id="subcategoryHeight" scope="col" class="f-sortable f-numerical" colspan="1" aria-sort="none">
                    <button aria-label="Sort by Height">Height</button>
                </th>
                <th scope="colgroup"></th>
                <th id="subcategoryWifi" scope="colgroup" class="f-sortable" aria-sort="none">
                    <button aria-label="Sort by Wi-Fi">Wi-Fi</button>
                </th>
                <th id="subcategory3gLTE" scope="col" class="f-sortable" colspan="1" aria-sort="none">
                    <button aria-label="Sort by 3G/LTE">3G/LTE</button>
                </th>
                <th id="subcategoryBluetooth" scope="colgroup" class="f-sortable" aria-sort="none">
                    <button aria-label="Sort by Bluetooth">Bluetooth</button>
                </th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td headers="subcategoryItem">Gadget Alpha</td>
                <td class="f-numerical f-sub-categorical" headers="subcategoryDimensions subcategoryLength">30cm</td>
                <td class="f-numerical f-sub-categorical" headers="subcategoryDimensions subcategoryWidth">2cm</td>
                <td class="f-numerical f-sub-categorical" headers="subcategoryDimensions subcategoryHeight">30cm</td>
                <td></td>
                <td class="f-sub-categorical" headers="subcategoryConnectivity subcategoryWifi">Yes</td>
                <td class="f-sub-categorical" headers="subcategoryConnectivity subcategory3gLTE">3G</td>
                <td class="f-sub-categorical" headers="subcategoryConnectivity subcategoryBluetooth">Yes</td>
                <td class="f-numerical" headers="subcategoryPrice">
                    <div class="c-price" itemprop="offers" itemscope itemtype="http://schema.org/Offer">
                        <meta itemprop="priceCurrency" content="USD">
                        <span>$</span>
                        <span itemprop="price">1,000</span>
                        <link itemprop="availability" href="http://schema.org/InStock">
                    </div>
                </td>
            </tr>
            <tr>
                <td headers="subcategoryItem">Gadget Bravo</td>
                <td class="f-numerical f-sub-categorical" headers="subcategoryDimensions subcategoryLength">20cm</td>
                <td class="f-numerical f-sub-categorical" headers="subcategoryDimensions subcategoryWidth">2cm</td>
                <td class="f-numerical f-sub-categorical" headers="subcategoryDimensions subcategoryHeight">30cm</td>
                <td></td>
                <td class="f-sub-categorical" headers="subcategoryConnectivity subcategoryWifi">No</td>
                <td class="f-sub-categorical" headers="subcategoryConnectivity subcategory3gLTE">LTE</td>
                <td class="f-sub-categorical" headers="subcategoryConnectivity subcategoryBluetooth">Yes</td>
                <td class="f-numerical" headers="subcategoryPrice">
                    <div class="c-price" itemprop="offers" itemscope itemtype="http://schema.org/Offer">
                        <meta itemprop="priceCurrency" content="USD">
                        <span>$</span>
                        <span itemprop="price">1,000</span>
                        <link itemprop="availability" href="http://schema.org/InStock">
                    </div>
                </td>
            </tr>
            <tr>
                <td headers="subcategoryItem">Gadget Charlie</td>
                <td class="f-numerical f-sub-categorical" headers="subcategoryDimensions subcategoryLength">30cm</td>
                <td class="f-numerical f-sub-categorical" headers="subcategoryDimensions subcategoryWidth">2cm</td>
                <td class="f-numerical f-sub-categorical" headers="subcategoryDimensions subcategoryHeight">30cm</td>
                <td></td>
                <td class="f-sub-categorical" headers="subcategoryConnectivity subcategoryWifi">Yes</td>
                <td class="f-sub-categorical" headers="subcategoryConnectivity subcategory3gLTE">3G</td>
                <td class="f-sub-categorical" headers="subcategoryConnectivity subcategoryBluetooth">Yes</td>
                <td class="f-numerical" headers="subcategoryPrice">
                    <div class="c-price" itemprop="offers" itemscope itemtype="http://schema.org/Offer">
                        <meta itemprop="priceCurrency" content="USD">
                        <span>$</span>
                        <span itemprop="price">1,000</span>
                        <link itemprop="availability" href="http://schema.org/InStock">
                    </div>
                </td>
            </tr>
            <tr>
                <td headers="subcategoryItem">Gadget Delta</td>
                <td class="f-numerical f-sub-categorical" headers="subcategoryDimensions subcategoryLength">15cm</td>
                <td class="f-numerical f-sub-categorical" headers="subcategoryDimensions subcategoryWidth">2cm</td>
                <td class="f-numerical f-sub-categorical" headers="subcategoryDimensions subcategoryHeight">30cm</td>
                <td></td>
                <td class="f-sub-categorical" headers="subcategoryConnectivity subcategoryWifi">No</td>
                <td class="f-sub-categorical" headers="subcategoryConnectivity subcategory3gLTE">LTE</td>
                <td class="f-sub-categorical" headers="subcategoryConnectivity subcategoryBluetooth">No</td>
                <td class="f-numerical" headers="subcategoryPrice">
                    <div class="c-price" itemprop="offers" itemscope itemtype="http://schema.org/Offer">
                        <meta itemprop="priceCurrency" content="USD">
                        <span>$</span>
                        <span itemprop="price">1,000</span>
                        <link itemprop="availability" href="http://schema.org/InStock">
                    </div>
                </td>
            </tr>
            <tr>
                <td headers="subcategoryItem">Gadget Echo</td>
                <td class="f-numerical f-sub-categorical" headers="subcategoryDimensions subcategoryLength">30cm</td>
                <td class="f-numerical f-sub-categorical" headers="subcategoryDimensions subcategoryWidth">2cm</td>
                <td class="f-numerical f-sub-categorical" headers="subcategoryDimensions subcategoryHeight">30cm</td>
                <td></td>
                <td class="f-sub-categorical" headers="subcategoryConnectivity subcategoryWifi">Yes</td>
                <td class="f-sub-categorical" headers="subcategoryConnectivity subcategory3gLTE">3G</td>
                <td class="f-sub-categorical" headers="subcategoryConnectivity subcategoryBluetooth">Yes</td>
                <td class="f-numerical" headers="subcategoryPrice">
                    <div class="c-price" itemprop="offers" itemscope itemtype="http://schema.org/Offer">
                        <meta itemprop="priceCurrency" content="USD">
                        <span>$</span>
                        <span itemprop="price">1,000</span>
                        <link itemprop="availability" href="http://schema.org/InStock">
                    </div>
                </td>
            </tr>
            <tr>
                <td headers="subcategoryItem">Gadget Foxtrot</td>
                <td class="f-numerical f-sub-categorical" headers="subcategoryDimensions subcategoryLength">30cm</td>
                <td class="f-numerical f-sub-categorical" headers="subcategoryDimensions subcategoryWidth">2cm</td>
                <td class="f-numerical f-sub-categorical" headers="subcategoryDimensions subcategoryHeight">30cm</td>
                <td></td>
                <td class="f-sub-categorical" headers="subcategoryConnectivity subcategoryWifi">Yes</td>
                <td class="f-sub-categorical" headers="subcategoryConnectivity subcategory3gLTE">3G</td>
                <td class="f-sub-categorical" headers="subcategoryConnectivity subcategoryBluetooth">No</td>
                <td class="f-numerical" headers="subcategoryPrice">
                    <div class="c-price" itemprop="offers" itemscope itemtype="http://schema.org/Offer">
                        <meta itemprop="priceCurrency" content="USD">
                        <span>$</span>
                        <span itemprop="price">1,000</span>
                        <link itemprop="availability" href="http://schema.org/InStock">
                    </div>
                </td>
            </tr>
        </tbody>
    </table>
</div>

Sortable table with dividers

Table caption
Height
Gadget Alpha30cm2cm30cm
$ 1,000
Gadget Bravo30cm2cm30cm
$ 1,000
Gadget Charlie30cm2cm30cm
$ 1,000
Gadget Delta30cm2cm30cm
$ 1,000
Gadget Echo30cm2cm30cm
$ 1,000
Gadget Foxtrot30cm2cm30cm
$ 1,000
<div class="c-table f-divided" data-f-loc-ascending="Sorted by {0} - ascending" data-f-loc-descending="Sorted by {0} - descending">
    <table data-f-sort="true">
        <caption>Table caption</caption>
        <thead>
            <tr>
                <th scope="col" class="f-sortable" colspan="1" aria-sort="none">
                    <button aria-label="Sort by Item">Item</button>
                </th>
                <th scope="col" class="f-sortable f-numerical" colspan="1" aria-sort="none">
                    <button aria-label="Sort by Length">Length</button>
                </th>
                <th scope="col" class="f-sortable f-numerical" colspan="1" aria-sort="none">
                    <button aria-label="Sort by Width">Width</button>
                </th>
                <th scope="col" class="f-numerical" colspan="1">Height</th>
                <th scope="col" class="f-sortable f-numerical" colspan="1" aria-sort="none">
                    <button aria-label="Sort by Price">Price</button>
                </th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>Gadget Alpha</td>
                <td class="f-numerical f-sub-categorical">30cm</td>
                <td class="f-numerical f-sub-categorical">2cm</td>
                <td class="f-numerical f-sub-categorical">30cm</td>
                <td class="f-numerical">
                    <div class="c-price" itemprop="offers" itemscope itemtype="http://schema.org/Offer">
                        <meta itemprop="priceCurrency" content="USD">
                        <span>$</span>
                        <span itemprop="price">1,000</span>
                        <link itemprop="availability" href="http://schema.org/InStock">
                    </div>
                </td>
            </tr>
            <tr>
                <td>Gadget Bravo</td>
                <td class="f-numerical f-sub-categorical">30cm</td>
                <td class="f-numerical f-sub-categorical">2cm</td>
                <td class="f-numerical f-sub-categorical">30cm</td>
                <td class="f-numerical">
                    <div class="c-price" itemprop="offers" itemscope itemtype="http://schema.org/Offer">
                        <meta itemprop="priceCurrency" content="USD">
                        <span>$</span>
                        <span itemprop="price">1,000</span>
                        <link itemprop="availability" href="http://schema.org/InStock">
                    </div>
                </td>
            </tr>
            <tr>
                <td>Gadget Charlie</td>
                <td class="f-numerical f-sub-categorical">30cm</td>
                <td class="f-numerical f-sub-categorical">2cm</td>
                <td class="f-numerical f-sub-categorical">30cm</td>
                <td class="f-numerical">
                    <div class="c-price" itemprop="offers" itemscope itemtype="http://schema.org/Offer">
                        <meta itemprop="priceCurrency" content="USD">
                        <span>$</span>
                        <span itemprop="price">1,000</span>
                        <link itemprop="availability" href="http://schema.org/InStock">
                    </div>
                </td>
            </tr>
            <tr>
                <td>Gadget Delta</td>
                <td class="f-numerical f-sub-categorical">30cm</td>
                <td class="f-numerical f-sub-categorical">2cm</td>
                <td class="f-numerical f-sub-categorical">30cm</td>
                <td class="f-numerical">
                    <div class="c-price" itemprop="offers" itemscope itemtype="http://schema.org/Offer">
                        <meta itemprop="priceCurrency" content="USD">
                        <span>$</span>
                        <span itemprop="price">1,000</span>
                        <link itemprop="availability" href="http://schema.org/InStock">
                    </div>
                </td>
            </tr>
            <tr>
                <td>Gadget Echo</td>
                <td class="f-numerical f-sub-categorical">30cm</td>
                <td class="f-numerical f-sub-categorical">2cm</td>
                <td class="f-numerical f-sub-categorical">30cm</td>
                <td class="f-numerical">
                    <div class="c-price" itemprop="offers" itemscope itemtype="http://schema.org/Offer">
                        <meta itemprop="priceCurrency" content="USD">
                        <span>$</span>
                        <span itemprop="price">1,000</span>
                        <link itemprop="availability" href="http://schema.org/InStock">
                    </div>
                </td>
            </tr>
            <tr>
                <td>Gadget Foxtrot</td>
                <td class="f-numerical f-sub-categorical">30cm</td>
                <td class="f-numerical f-sub-categorical">2cm</td>
                <td class="f-numerical f-sub-categorical">30cm</td>
                <td class="f-numerical">
                    <div class="c-price" itemprop="offers" itemscope itemtype="http://schema.org/Offer">
                        <meta itemprop="priceCurrency" content="USD">
                        <span>$</span>
                        <span itemprop="price">1,000</span>
                        <link itemprop="availability" href="http://schema.org/InStock">
                    </div>
                </td>
            </tr>
        </tbody>
    </table>
</div>