Data Table

Data tables display sets of raw data. They usually appear in desktop enterprise products

Data Table Layout

Common Data Table layout could be treated as the following:

<div class="data-table">
  <table>
    <thead>
      <tr>
        <th class="label-cell">Dessert (100g serving)</th>
        <th class="numeric-cell">Calories</th>
        ...
        <th class="medium-only">Comment</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td class="label-cell">Frozen yogurt</td>
        <td class="numeric-cell">159</td>
        ...
        <td class="medium-only">I like it!</td>
      </tr>
      ...
    </tbody>
  </table>
</div>

Within Card:

<div class="data-table card">
  <table>
    <thead>
    ...
    </thead>
    <tbody>
    ...
    </tbody>
  </table>
</div>

Where

  • data-table - main Data Table wrapper. Required
    • table - table itself. Required
      • thead - table head
      • tbody - table body. Required
      • label-cell - main label cell (only one such kind of cell per row, usually first cell)
      • numeric-cell - cell to display numeric data (right-aligned)
      • medium-only - additional class to show this cell/column only when app width >= 768px. For full set of such responsive classes check Grid docs. They are xsmall-only, small-only, medium-only, large-only, xlarge-only.
<div class="card data-table">
  <table>
    <thead>
      <tr>
        <th class="label-cell">Dessert (100g serving)</th>
        <th class="numeric-cell">Calories</th>
        <th class="numeric-cell">Fat (g)</th>
        <th class="numeric-cell">Carbs</th>
        <th class="numeric-cell">Protein (g)</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td class="label-cell">Frozen yogurt</td>
        <td class="numeric-cell">159</td>
        <td class="numeric-cell">6.0</td>
        <td class="numeric-cell">24</td>
        <td class="numeric-cell">4.0</td>
      </tr>
      ...
    </tbody>
  </table>
  <div class="data-table-footer">
    <div class="data-table-rows-select">
      Per page:
      <div class="input input-dropdown">
        <select>
          <option value="5">5</option>
          <option value="10">10</option>
          <option value="25">25</option>
          <option value="all">All</option>
        </select>
      </div>
    </div>
    <div class="data-table-pagination">
      <span class="data-table-pagination-label">1-5 of 10</span>
      <a href="#" class="link disabled">
        <i class="icon icon-prev color-gray"></i>
      </a>
      <a href="#" class="link">
        <i class="icon icon-next color-gray"></i>
      </a>
    </div>
  </div>
</div>

Where

  • data-table-footer - data table footer main element
    • data-table-rows-select - container with amount per page select
    • data-table-pagination - container with information about current page and prev/next navigation buttons
      • data-table-pagination-label - current paging label

Selectable Rows

<div class="data-table data-table-init card">
  <table>
    <thead>
      <tr>
        <th class="checkbox-cell">
          <label class="checkbox">
            <input type="checkbox"/>
            <i class="icon-checkbox"></i>
          </label>
        </th>
        <th class="label-cell">Dessert (100g serving)</th>
        <th class="numeric-cell">Calories</th>
        ...
        <th class="numeric-cell">Protein (g)</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td class="checkbox-cell">
          <label class="checkbox">
            <input type="checkbox"/>
            <i class="icon-checkbox"></i>
          </label>
        </td>
        <td class="label-cell">Frozen yogurt</td>
        <td class="numeric-cell">159</td>
        ...
        <td class="numeric-cell">4.0</td>
      </tr>
      ...
    </tbody>
  </table>
</div>

Where

  • data-table-init - additional class to enable JavaScript action required for selectable rows
  • Checkbox cell. Such cell in table header will select/deselect all rows in table body:

    <td class="checkbox-cell">
      <label class="checkbox">
        <input type="checkbox"/>
        <i class="icon-checkbox"></i>
      </label>
    </td>

Inputs In Table Head

Such tables are widely used in admin interfaces for filtering or search data

<div class="card data-table">
  <table>
    <thead>
      <tr>
        <th class="input-cell">
          <span class="table-head-label">ID</span>
          <div class="input" style="width: 50px">
            <input type="number" placeholder="Filter" />
          </div>
        </th>
        <th class="input-cell">
          <span class="table-head-label">Name</span>
          <div class="input">
            <input type="text" placeholder="Filter" />
          </div>
        </th>
        ...
        <th class="input-cell">
          <span class="table-head-label">Gender</span>
          <div class="input input-dropdown">
            <select>
              <option value="All">All</option>
              <option value="Male">Male</option>
              <option value="Female">Female</option>
            </select>
          </div>
        </th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>1</td>
        <td>John Doe</td>
        <td>[email protected]</td>
        <td>Male</td>
      </tr>
      ...
    </tbody>
  </table>
</div>

Where

  • input-cell - additional class on table cell required to display input

  • <span class="table-head-label"> - input label

  • <div class="input"> - input container

Table Title/Header

When data table is used within Card it is possible to use additional data table title with actions in card header.

With title and actions

<div class="data-table data-table-init card">
  <!-- Card Header -->
  <div class="card-header">
    <!-- Table title -->
    <div class="data-table-title">Nutrition</div>
    <!-- Table actions -->
    <div class="data-table-actions">
      <a class="link icon-only">
        <i class="icon f7-icons if-not-md">line_horizontal_3_decrease</i>
        <i class="icon material-icons md-only">sort</i>
      </a>
      <a class="link icon-only">
        <i class="icon f7-icons if-not-md">ellipsis_vertical_circle</i>
        <i class="icon material-icons md-only">more_vert</i>
      </a>
    </div>
  </div>
  <!-- Card Content -->
  <div class="card-content">
    <table>
      <thead>
        <tr>
          <th class="checkbox-cell">
            <label class="checkbox">
              <input type="checkbox" />
              <i class="icon-checkbox"></i>
            </label>
          </th>
          <th class="label-cell">Dessert (100g serving)</th>
          <th class="numeric-cell">Calories</th>
          ...
        </tr>
      </thead>
      <tbody>
        <tr>
          <td class="checkbox-cell">
            <label class="checkbox">
              <input type="checkbox" />
              <i class="icon-checkbox"></i>
            </label>
          </td>
          <td class="label-cell">Frozen yogurt</td>
          <td class="numeric-cell">159</td>
          ...
        </tr>
        ...
      </tbody>
    </table>
  </div>
</div>

Where

  • data-table-title - table title
  • data-table-actions - main table actions

Different actions on select

<div class="data-table data-table-init card">
  <!-- Card header -->
  <div class="card-header">
    <!-- Default table header -->
    <div class="data-table-header">
      <!-- Default table title -->
      <div class="data-table-title">Nutrition</div>
      <!-- Default table actions -->
      <div class="data-table-actions">
        <a class="link icon-only">
          <i class="icon f7-icons if-not-md">line_horizontal_3_decrease</i>
          <i class="icon material-icons md-only">sort</i>
        </a>
        <a class="link icon-only">
          <i class="icon f7-icons if-not-md">ellipsis_vertical_circle</i>
          <i class="icon material-icons md-only">more_vert</i>
        </a>
      </div>
    </div>
    <!-- Selected table header -->
    <div class="data-table-header-selected">
      <!-- Selected table title -->
      <div class="data-table-title-selected"><span class="data-table-selected-count"></span> items selected</div>
      <!-- Selected table actions -->
      <div class="data-table-actions">
        <a class="link icon-only">
          <i class="icon f7-icons if-not-md">trash</i>
          <i class="icon material-icons md-only">delete</i>
        </a>
        <a class="link icon-only">
          <i class="icon f7-icons if-not-md">ellipsis_vertical_circle</i>
          <i class="icon material-icons md-only">more_vert</i>
        </a>
      </div>
    </div>
  </div>
  <div class="card-content">
    <table>
      <thead>
        <tr>
          <th class="checkbox-cell">
            <label class="checkbox">
              <input type="checkbox" />
              <i class="icon-checkbox"></i>
            </label>
          </th>
          <th class="label-cell">Dessert (100g serving)</th>
          <th class="numeric-cell">Calories</th>
          ...
        </tr>
      </thead>
      <tbody>
        <tr>
          <td class="checkbox-cell">
            <label class="checkbox">
              <input type="checkbox" />
              <i class="icon-checkbox"></i>
            </label>
          </td>
          <td class="label-cell">Frozen yogurt</td>
          <td class="numeric-cell">159</td>
          ...
        </tr>
        ...
      </tbody>
    </table>
  </div>
</div>

Where

  • data-table-header - default table header. Visible when there are no selected rows
  • data-table-header-selected - selected table header. Visible when there are selected rows
  • data-table-selected-count - count of selected table rows. Number will be placed here by JavaScript

Alternate header with row actions

<div class="data-table data-table-init card">
  <div class="card-header">
    <!-- Table links/actions -->
    <div class="data-table-links">
      <a class="link">Add</a>
      <a class="link">Remove</a>
    </div>
    <!-- Table actions -->
    <div class="data-table-actions">
      <a class="link icon-only">
        <i class="icon f7-icons if-not-md">line_horizontal_3_decrease</i>
        <i class="icon material-icons md-only">sort</i>
      </a>
      <a class="link icon-only">
        <i class="icon f7-icons if-not-md">ellipsis_vertical_circle</i>
        <i class="icon material-icons md-only">more_vert</i>
      </a>
    </div>
  </div>
  <div class="card-content">
    <table>
      <thead>
        <tr>
          <th class="checkbox-cell">
            <label class="checkbox">
              <input type="checkbox" />
              <i class="icon-checkbox"></i>
            </label>
          </th>
          <th class="label-cell">Dessert (100g serving)</th>
          <th class="numeric-cell">Calories</th>
          ...
          <th></th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td class="checkbox-cell">
            <label class="checkbox">
              <input type="checkbox" />
              <i class="icon-checkbox"></i>
            </label>
          </td>
          <td class="label-cell">Frozen yogurt</td>
          <td class="numeric-cell">159</td>
          ...
          <td class="actions-cell">
            <a class="link icon-only">
              <i class="icon f7-icons if-not-md">square_pencil</i>
              <i class="icon material-icons md-only">edit</i>
            </a>
            <a class="link icon-only">
              <i class="icon f7-icons if-not-md">trash</i>
              <i class="icon material-icons md-only">delete</i>
            </a>
          </td>
        </tr>
        ...
      </tbody>
    </table>
  </div>
</div>

Where

  • data-table-links - alternate/additional table actions
  • actions-cell - action links/icons cell

Sortable

<div class="data-table data-table-init card">
  <div class="card-header">
    <div class="data-table-title">Nutrition</div>
    <div class="data-table-actions">
      <a class="link icon-only">
        <i class="icon f7-icons if-not-md">line_horizontal_3_decrease</i>
        <i class="icon material-icons md-only">sort</i>
      </a>
      <a class="link icon-only">
        <i class="icon f7-icons if-not-md">ellipsis_vertical_circle</i>
        <i class="icon material-icons md-only">more_vert</i>
      </a>
    </div>
  </div>
  <div class="card-content">
    <table>
      <thead>
        <tr>
          <th class="checkbox-cell">
            <label class="checkbox">
              <input type="checkbox" />
              <i class="icon-checkbox"></i>
            </label>
          </th>
          <th class="label-cell sortable-cell sortable-cell-active">Dessert (100g serving)</th>
          <th class="numeric-cell sortable-cell">Calories</th>
          <th class="numeric-cell sortable-cell">Fat (g)</th>
          <th class="numeric-cell sortable-cell">Carbs</th>
          <th class="numeric-cell sortable-cell">Protein (g)</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td class="checkbox-cell">
            <label class="checkbox">
              <input type="checkbox" />
              <i class="icon-checkbox"></i>
            </label>
          </td>
          <td class="label-cell">Frozen yogurt</td>
          <td class="numeric-cell">159</td>
          <td class="numeric-cell">6.0</td>
          <td class="numeric-cell">24</td>
          <td class="numeric-cell">4.0</td>
        </tr>
        ...
      </tbody>
    </table>
  </div>
</div>

Where

  • sortable-cell - additional class to make cell/column is sortable
  • sortable-cell-active - additional class to specify active/default sortable cell/column
  • sortable-asc - additional class to specify current sorting as ascending (default)
  • sortable-desc - additional class to specify current sorting as descending

Note, there is no actual sortable logic provided by framework. Actual sorting logic should be realized manually

Collapsible

The following table will be collapsed to kind of List View on small screens:

<div class="card data-table data-table-collapsible data-table-init">
  <div class="card-header">
    <div class="data-table-title">Nutrition</div>
    <div class="data-table-actions">
      <a class="link icon-only">
        <i class="icon f7-icons if-not-md">line_horizontal_3_decrease</i>
        <i class="icon material-icons md-only">sort</i>
      </a>
      <a class="link icon-only">
        <i class="icon f7-icons if-not-md">ellipsis_vertical_circle</i>
        <i class="icon material-icons md-only">more_vert</i>
      </a>
    </div>
  </div>
  <div class="card-content">
    <table>
      <thead>
        <tr>
          <th class="label-cell">Dessert (100g serving)</th>
          <th class="numeric-cell">Calories</th>
          ...
          <th class="numeric-cell">Protein (g)</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td class="label-cell">Frozen yogurt</td>
          <td class="numeric-cell">159</td>
          ...
          <td class="numeric-cell">4.0</td>
        </tr>
        ...
      </tbody>
    </table>
  </div>
</div>

Where

  • data-table-collapsible - additional table class to enable collapsible logic. Note that "data-table-init" class is also required for this.

Data Table App Methods

In case you add data table dynamically and you need such selecting rows or switching headers logic you need to init it manually. Let's look at related app methods to work with data table:

app.dataTable.create(parameters)- create Data Table instance

  • parameters - object. Object with data table parameters

Method returns created Data Table's instance

app.dataTable.destroy(el)- destroy Data Table instance

  • el - HTMLElement or string (with CSS Selector) or object. Data Table element or Data Table instance to destroy.

app.dataTable.get(el)- get Data Table instance by HTML element

  • el - HTMLElement or string (with CSS Selector). Data Table element.

Method returns Data Table's instance

Data Table Parameters

Now let's look at list of available parameters we need to create Data Table:

ParameterTypeDefaultDescription
elHTMLElement
string
Data Table element. Can be useful if you already have Data Table element in your HTML and want to create new instance using this element

Data Table Events

Data Table will fire the following DOM events on data table element and events on app and data table instance:

DOM Events

EventTargetDescription
datatable:sortData Table Element<div class="data-table">Event will be triggered data table sort changed
datatable:beforedestroyData Table Element<div class="data-table">Event will be triggered right before Data Table instance will be destroyed

App and Data Table Instance Events

Data Table instance emits events on both self instance and app instance. App instance events has same names prefixed with dataTable.

EventArgumentsTargetDescription
sortdataTable, sortdataTableEvent will be triggered data table sort changed
dataTableSortdataTable, sortapp
beforeDestroydataTabledataTableEvent will be triggered right before Data Table instance will be destroyed
dataTableBeforeDestroydataTableapp

CSS Variables

Below is the list of related CSS variables (CSS custom properties).

Note that commented variables are not specified by default and their values is what they fallback to in this case.

:root {
  --f7-table-head-font-size: 12px;
  --f7-table-body-font-size: 14px;
  --f7-table-footer-font-size: 12px;
  --f7-table-input-height: 24px;
  --f7-table-input-font-size: 14px;
  --f7-table-collapsible-cell-padding: 16px;
  --f7-table-link-icon-only-icon-size: 20px;
  --f7-table-head-bg-color: transparent;
  --f7-table-card-header-bg-color: transparent;
  --f7-table-card-header-height: 64px;
  --f7-table-cell-padding-vertical: 0px;
  --f7-table-sortable-icon-color: #000;
}
:root .theme-dark,
:root.theme-dark {
  --f7-table-cell-border-color: rgba(255, 255, 255, 0.15);
  --f7-table-sortable-icon-color: #fff;
  --f7-table-input-text-color: #fff;
}
.ios {
  --f7-table-head-font-weight: 600;
  --f7-table-head-cell-height: 44px;
  --f7-table-head-icon-size: 18px;
  --f7-table-body-cell-height: 44px;
  --f7-table-cell-padding-horizontal: 16px;
  --f7-table-edge-cell-padding-horizontal: 16px;
  --f7-table-label-cell-padding-horizontal: 16px;
  --f7-table-checkbox-cell-width: 22px;
  /* --f7-table-actions-cell-link-color: var(--f7-theme-color); */
  /* --f7-table-actions-link-color: var(--f7-theme-color); */
  --f7-table-title-font-size: 17px;
  --f7-table-title-font-weight: 600;
  --f7-table-footer-height: 44px;
  --f7-table-head-text-color: rgba(0, 0, 0, 0.45);
  --f7-table-cell-border-color: rgba(0, 0, 0, 0.22);
  --f7-table-selected-row-bg-color: rgba(0, 0, 0, 0.03);
  --f7-table-footer-text-color: rgba(0, 0, 0, 0.45);
  --f7-table-input-text-color: #000;
}
.ios .theme-dark,
.ios.theme-dark {
  --f7-table-head-text-color: rgba(255, 255, 255, 0.55);
  --f7-table-footer-text-color: rgba(255, 255, 255, 0.55);
  --f7-table-selected-row-bg-color: rgba(255, 255, 255, 0.08);
}
.md {
  --f7-table-head-font-weight: 500;
  --f7-table-head-cell-height: 56px;
  --f7-table-head-icon-size: 16px;
  --f7-table-body-cell-height: 48px;
  --f7-table-cell-padding-horizontal: 28px;
  --f7-table-edge-cell-padding-horizontal: 24px;
  --f7-table-label-cell-padding-horizontal: 24px;
  --f7-table-checkbox-cell-width: 18px;
  --f7-table-title-font-size: 20px;
  --f7-table-title-font-weight: 400;
  --f7-table-footer-height: 56px;
  --f7-table-head-text-color: rgba(0, 0, 0, 0.54);
  --f7-table-cell-border-color: rgba(0, 0, 0, 0.12);
  --f7-table-actions-cell-link-color: rgba(0, 0, 0, 0.54);
  --f7-table-selected-row-bg-color: #f5f5f5;
  --f7-table-actions-link-color: rgba(0, 0, 0, 0.54);
  --f7-table-footer-text-color: rgba(0, 0, 0, 0.54);
  --f7-table-input-text-color: #212121;
}
.md .theme-dark,
.md.theme-dark {
  --f7-table-head-text-color: rgba(255, 255, 255, 0.54);
  --f7-table-footer-text-color: rgba(255, 255, 255, 0.54);
  --f7-table-selected-row-bg-color: rgba(255, 255, 255, 0.05);
  --f7-table-actions-cell-link-color: rgba(255, 255, 255, 0.54);
  --f7-table-actions-link-color: rgba(255, 255, 255, 0.54);
}
.aurora {
  --f7-table-input-height: 32px;
  --f7-table-head-font-weight: 600;
  --f7-table-head-cell-height: 56px;
  --f7-table-head-icon-size: 18px;
  --f7-table-body-cell-height: 48px;
  --f7-table-cell-padding-horizontal: 16px;
  --f7-table-edge-cell-padding-horizontal: 16px;
  --f7-table-label-cell-padding-horizontal: 16px;
  --f7-table-checkbox-cell-width: 22px;
  /* --f7-table-actions-cell-link-color: var(--f7-theme-color); */
  /* --f7-table-actions-link-color: var(--f7-theme-color); */
  --f7-table-title-font-size: 20px;
  --f7-table-title-font-weight: 600;
  --f7-table-footer-height: 56px;
  --f7-table-head-text-color: rgba(0, 0, 0, 0.6);
  --f7-table-cell-border-color: rgba(0, 0, 0, 0.12);
  --f7-table-selected-row-bg-color: rgba(0, 0, 0, 0.03);
  --f7-table-footer-text-color: rgba(0, 0, 0, 0.5);
  --f7-table-input-text-color: #000;
  --f7-table-head-bg-color: #f6f6f7;
  --f7-table-card-header-bg-color: #f6f6f7;
}
.aurora .theme-dark,
.aurora.theme-dark {
  --f7-table-selected-row-bg-color: rgba(255, 255, 255, 0.03);
  --f7-table-head-text-color: rgba(255, 255, 255, 0.54);
  --f7-table-footer-text-color: rgba(255, 255, 255, 0.54);
  --f7-table-head-bg-color: rgba(255, 255, 255, 0.05);
  --f7-table-card-header-bg-color: rgba(255, 255, 255, 0.05);
}