Reflow Table Widget


Reflow Table Widgetversion added: 1.3

Description: Creates a responsive table in reflow mode

QuickNavExamples

Methods

Events

The reflow table mode works by collapsing the table columns into a stacked presentation that looks like blocks of label/data pairs for each row. Since the HTML source order of a table prohibits styling a table to look like this, the plugin dynamically adds a bit of markup to make the display work (without affecting accessibility). Here is a demo of a basic table using reflow mode:

Applying reflow mode to a table

The reflow responsive table mode is the simplest in terms of markup requirements because it only requires a table with a data-role="table" on the table element. There is no need to set the data-mode attribute since reflow is the default.

1
<table data-role="table" id="my-table">

How reflow mode works

The plugin works by parsing the values (or abbr title) of the first row of header (th) elements found in the table. For example, in the table above, the third table header is parsed to grab the contents ("Year"):

1
<th>Year</th>

The script then appends an element with the table header text before the contents of every cell in that column. For example, for every table cell in the year column:

1
<td>1941</td>

An element is added before the text of each cell with a class of ui-table-cell-label:

1
<td><b class="ui-table-cell-label">Year</b>1941</td>

With our mobile-first approach, the base styles for a reflow table stacks each row and presents each cell in the label/data style format. This is done by hiding the table header rows, making each table cell display:block so they are stacked. The the label element injected into each cell is styled as display:inline-block with a min-width:30% rule to place the labels on the same line as the content at a consistent width to form a two column presentation.

It is important to note that you are required to wrap your table headers in a <thead> ... </thead> block, and the table body in a <tbody> ... </tbody> block, as shown in the full demo Example.

Making the table responsive

By default, a table with reflow mode will display the stacked presentation style on all screen widths. The styles to make the table responsive are added by applying a media query with rules to switch to the tabular style presentation above a specific screen width.

This is done by wrapping a few simple CSS rules in and a media query that only applies the rules above a certain width breakpoint. The styles make the table header rows visible, display the cells in a tabular format, and hide the generated label elements within each. Here is an example media query that swaps the presentation at 40em (640 pixels):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@media ( min-width: 40em ) {
/* Show the table header rows and set all cells to display: table-cell */
.my-custom-breakpoint td,
.my-custom-breakpoint th,
.my-custom-breakpoint tbody th,
.my-custom-breakpoint tbody td,
.my-custom-breakpoint thead td,
.my-custom-breakpoint thead th {
display: table-cell;
margin: 0;
}
/* Hide the labels in each cell */
.my-custom-breakpoint td .ui-table-cell-label,
.my-custom-breakpoint th .ui-table-cell-label {
display: none;
}
}

It's best to use a class on the table to apply the breakpoint. Add these rules to your custom stylesheet that is included in the head of the page. We recommend creating a set of custom breakpoint classes that can be used to apply standard table breakpoints in your project.

In the example above, we're assuming there is a class of my-custom-breakpoint added to the table to apply the breakpoint. Each of the rules in the custom media query are scoped against that table class to target only tables that have the my-custom-breakpoint class.

In order for this technique to work, a browser must support media queries and the ability to style table cells as block-level elements. In testing, most popular desktop and mobile browsers meet these criteria, but older versions of Internet Explorer (8 and older) fall back to a normal table presentation. IE 9 can support this technique but there are a few additional styles needed so we recommend applying these in a max-width media query to only apply them below the table presentation because they are hard to negate.

Choosing a breakpoint

The goal is to determine the minimum width at which the entire table will fit comfortably within the screen. Find this width by populating a table with realistic sample data, then adjust the browser window until the table completely fits and has a bit of extra space to account for rendering differences across devices. This is the natural place to set the breakpoint that switches between the stacked and tabular presentation modes.

The breakpoint width is highly dependent on the number of columns in the table and content within each cell. On some sites, this may be as low as 30em (480px) and on others, it could be as wide as 100em (1,600px). There is no way for the framework to decide on a "standard breakpoint" that will work for everyone — that's why there isn't a breakpoint built into the table by default.

We recommend writing media query widths are in em's so they respond to font size changes. To convert a pixel width into em's, divide the target width by 16 (pixels). Use this value for the min-width value in the media query above.

Applying a preset breakpoint

Even though we strongly encourage you to write custom breakpoints yourself, the framework includes a single pre-configured breakpoint that targets the stacked style to smaller phones and swaps to a tabular prsentation on larger phones, tablet and desktop devices. To use this preset breakpoint, add the ui-responsive class to the table to convert from the stacked presentation to a tabular presentation at 560px (35em). If this breakpoint doesn't work for your content, we encourage you to write a custom breakpoint as descibed above.

1
<table data-role="table" class="ui-responsive">

Working with grouped column headers

It's fairly common to need to logically group multiple columns together under a heading group for financial or scientific data. The framework can support the most simple version of this by allowing for two rows of table headers (TH), with the first row containing simple colspan attributes to group the columns below. In this configuration, the framework will add a class to the label of the first cell in each group to allow you to style these differently and provide aditional visual hierarchy.

Options

classes.cellLabelsType: String

Default: "ui-table-cell-label"
Class added to the first cell within each grouped header's column. This makes it easy to style these differently to visually delineate the column groups.

Note: The reflow mode has one option, classes, which is only configurable via JavaScript because it expects an object literal value. The classes option has two properties that define the structural classnames that the plugin uses.

classes.reflowTableType: String

Default: "ui-table-reflow"
Class added to the generated label content added to each table cell based on the header name.

Note: The reflow mode has one option, classes, which is only configurable via JavaScript because it expects an object literal value. The classes option has two properties that define the structural classnames that the plugin uses.

initSelectorType: CSS selector string

Default: ":jqmData(role='table')"
This is used to define the selectors (element types, data roles, etc.) that will automatically be initialized as tables. To change which elements are initialized, bind this option to the mobileinit event:
1
2
3
$( document ).on( "mobileinit", function() {
$.mobile.table.prototype.options.initSelector = ".mytable";
});

Methods

refresh()Returns: jQuery (plugin only)

Updates the labels in the cells.
  • This method does not accept any arguments.
Code examples:

Invoke the refresh method:

1
$( ".selector" ).table( "refresh" );

Events

create( event, ui )Type: tablecreate

Since this plugin is written as an extension to the core table plugin, it binds to the tablecreate event but does not issue any additional events.

Note: The ui object is empty but included for consistency with other events.

Code examples:

Initialize the table with the create callback specified:

1
2
3
$( ".selector" ).table({
create: function( event, ui ) {}
});

Bind an event listener to the tablecreate event:

1
$( ".selector" ).on( "tablecreate", function( event, ui ) {} );

Example:

A basic example of a responsive table in reflow mode.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>table demo</title>
<link rel="stylesheet" href="//code.jquery.com/mobile/1.4.2/jquery.mobile-1.4.2.min.css">
<script src="//code.jquery.com/jquery-1.10.2.min.js"></script>
<script src="//code.jquery.com/mobile/1.4.2/jquery.mobile-1.4.2.min.js"></script>
</head>
<body>
<div data-role="page" id="page1">
<div data-role="header">
<h1>jQuery Mobile Example</h1>
</div>
<div role="main" class="ui-content">
<table data-role="table" id="movie-table" data-mode="reflow" class="ui-responsive table-stroke">
<thead>
<tr>
<th data-priority="1">Rank</th>
<th data-priority="persist">Movie Title</th>
<th data-priority="2">Year</th>
<th data-priority="3"><abbr title="Rotten Tomato Rating">Rating</abbr></th>
<th data-priority="4">Reviews</th>
</tr>
</thead>
<tbody>
<tr>
<th>1</th>
<td><a href="http://en.wikipedia.org/wiki/Citizen_Kane" data-rel="external">Citizen Kane</a></td>
<td>1941</td>
<td>100%</td>
<td>74</td>
</tr>
<tr>
<th>2</th>
<td><a href="http://en.wikipedia.org/wiki/Casablanca_(film)" data-rel="external">Casablanca</a></td>
<td>1942</td>
<td>97%</td>
<td>64</td>
</tr>
<tr>
<th>3</th>
<td><a href="http://en.wikipedia.org/wiki/The_Godfather" data-rel="external">The Godfather</a></td>
<td>1972</td>
<td>97%</td>
<td>87</td>
</tr>
<tr>
<th>4</th>
<td><a href="http://en.wikipedia.org/wiki/Gone_with_the_Wind_(film)" data-rel="external">Gone with the Wind</a></td>
<td>1939</td>
<td>96%</td>
<td>87</td>
</tr>
<tr>
<th>5</th>
<td><a href="http://en.wikipedia.org/wiki/Lawrence_of_Arabia_(film)" data-rel="external">Lawrence of Arabia</a></td>
<td>1962</td>
<td>94%</td>
<td>87</td>
</tr>
<tr>
<th>6</th>
<td><a href="http://en.wikipedia.org/wiki/Dr._Strangelove" data-rel="external">Dr. Strangelove Or How I Learned to Stop Worrying and Love the Bomb</a></td>
<td>1964</td>
<td>92%</td>
<td>74</td>
</tr>
<tr>
<th>7</th>
<td><a href="http://en.wikipedia.org/wiki/The_Graduate" data-rel="external">The Graduate</a></td>
<td>1967</td>
<td>91%</td>
<td>122</td>
</tr>
<tr>
<th>8</th>
<td><a href="http://en.wikipedia.org/wiki/The_Wizard_of_Oz_(1939_film)" data-rel="external">The Wizard of Oz</a></td>
<td>1939</td>
<td>90%</td>
<td>72</td>
</tr>
<tr>
<th>9</th>
<td><a href="http://en.wikipedia.org/wiki/Singin%27_in_the_Rain" data-rel="external">Singin' in the Rain</a></td>
<td>1952</td>
<td>89%</td>
<td>85</td>
</tr>
<tr>
<th>10</th>
<td class="title"><a href="http://en.wikipedia.org/wiki/Inception" data-rel="external">Inception</a></td>
<td>2010</td>
<td>84%</td>
<td>78</td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
</html>

Demo: