Developer Programs

Learn

Docs

Responsive Table

Components > Displaying Data > Responsive Table
Use this component to...
Display simple data in rows and columns at large screen sizes and in a vertically scrolling list at mobile size

Overview

Responsive UI offers three approaches for displaying table data (i.e. data in rows and columns):

  • Responsive table: Used for simple table data, with limited functionality
  • Data grid: Used for complex table data, with more sophisticated functionality for interacting with the data
  • Tree grid: Used for hierarchical table data

This document describes the responsive table. Use the responsive table to display a table with a relatively small number of rows of data that don’t need complex behaviors like filtering or grouping. This is a lighter weight option than a data grid.

The responsive table works well on large and small devices: it displays the data in rows and columns at larger sizes, collapsing to a vertically scrolling list of cards at mobile size.

Behaviors such as sorting, filtering, and paging can be added, but you must add custom logic for that functionality to your application’s logic yourself.

The responsive table displays data in rows and columns at larger sizes…
Responsive table at larger size
… dropping into a vertically scrolling list at mobile size
Responsive table at mobile size

Grid Buttons

Use the grid button component if you need to include one or more buttons in a responsive table cell. It uses minimal, lightweight formatting that fits well into a table cell.


Development

Web component development

Component reference

rui-sort-button
rui-sort-button
Module: rui-buttons - Package: @jkhy/responsive-ui-wc

Displays buttons in responsive table header for sorting table content

NameTypeDefaultDescription
textstring''Column header name; displayed as the button text
showArrowbooleanfalseBind to expression that evaluates to true if this column is the one being sorted and false otherwise
arrowDirectionstring'up'Indicates column sort direction: one of “up” or “down”
rui-clickeventClick event for the sort button

Implementation

The responsive table is an HTML table that displays data in rows and columns at larger screen sizes and a vertically scrolling list of records at mobile size.

  • Add the rui-responsive-table and rui-table-minimal CSS classes to the table element.
  • Iterate through a list of business objects in your controller, emitting a tr element for each object in the list. Angular applications use *ngFor to do this.
  • Add a data-title attribute to each td whose value is the text title displayed at the top of the corresponding column. This allows the column header title to be displayed for each td when the table is collapsed to a vertically scrolling list of cards at mobile size.
  • It can be helpful to wrap a responsive table within a div that has overflow-x:auto so that horizontal scrollbars display at smaller screen widths. The responsive table drops into a list of vertically scrolling cards at screen widths less than 768 pixels, but the data in your table may not fit into the allocated space at widths greater than 768 pixels, so horizontal scrolling may be the best compromise.

Cell alignment

HTML table cells are left-aligned by default, but it’s best to right-align currency and numeric values so the decimal points and commas line up on the right, helping the user compare numeric values across rows.

Our first thought might be to force center and right alignment by adding inline styles to the cells. This works well at larger screen widths, but not always as well at mobile size. When the responsive table collapses to a vertical list at mobile size, we want to see all values right-aligned. Adding an inline style to force center-alignment will override the CSS and force center alignment even at mobile size, when all other values are right-aligned, which looks odd.

Here are CSS classes that you can add to responsive table cells to maintain proper horizontal alignment at different screen widths:

  • rui-responsive-cell-right: Right-aligns the cell’s content at all screen widths.
  • rui-responsive-cell-center: Center-aligns the cell’s content at larger screen widths and right-aligns it at mobile size.
  • rui-responsive-cell-left: Left-aligns the cell’s content at larger screen widths and right-aligns it at mobile size. (This CSS class is redundant since this is the default behavior, but is included for completeness.)

If a table cell tends to contain larger amounts of text that break to multiple lines at mobile size, the ragged left edge of this multi-line data can make the text harder to read. Add the rui-responsive-cell-large CSS class to cells that tend to contain larger amounts of data. This CSS class keeps the data left-aligned at all screen widths, making the long data easier to read.

Additionally, responsive tables vertically align content to the top of cells by default. Typically this is ideal so if the content wraps, all cells in a row are aligned along the top of the cell making the row shape easier to see. However, this may not always be desired, so there are classes that can be applied to the table rows that will vertically align the content that best fits your scenario.

  • rui-responsive-row-top: Top-aligns the cell’s content at all screen widths.
  • rui-responsive-row-middle: Middle-aligns the cell’s content at all screen widths.
  • rui-responsive-row-bottom: Bottom-aligns the cell’s content at all screen widths.

Responsive table example

Here is an example of a simple HTML table with a few attributes added (highlighted below) to set it up as a responsive table, running in an Angular application.

Responsive table example
<div style="overflow-x:auto">
    <table class="rui-responsive-table rui-table-minimal">
        <thead>
            <tr>
                <th class="rui-responsive-cell-center">Date</th>
                <th class="rui-responsive-cell-center">Effective</th>
                <th>Payee</th>
                <th class="rui-responsive-cell-right">Amount</th>
                <th class="rui-responsive-cell-right">New Balance</th>
            </tr>
        </thead>
        <tbody>
            <tr class="rui-responsive-row-middle" *ngFor="let transaction of sortedTransactionList">
                <td data-title="Date" class="rui-responsive-cell-center">{{ transaction.TranDate | jhaDate }}</td>
                <td data-title="Effective" class="rui-responsive-cell-center">{{ transaction.EffDate | jhaDate }}</td>
                <td data-title="Payee">{{ transaction.Payee }}</td>
                <td data-title="Amount" class="rui-responsive-cell-right">{{ transaction.AbsoluteAmount | jhaCurrency }}</td>
                <td data-title="New Balance" class="rui-responsive-cell-right">{{ transaction.NewBalance | jhaCurrency }}</td>
            </tr>
        </tbody>
    </table>
</div>

Sorting the responsive table

If you’re adding simple sorting for your responsive table, you’ll need to use an instance of rui-sort-button instead of text for each column header that is sortable. Each time the user presses the rui-sort-button, your application will sort the table on the column that was clicked, reversing the existing sort direction. The rui-sort-button component displays an up/down arrow icon to the right of the text in the button for the sorted column; this indicates which column the table is sorted by and the current sort direction.

Begin by importing the rui-buttons module into your application.

Import the module for sort buttons
// import into app.module
import '@jkhy/responsive-ui-wc/components/rui-buttons/rui-buttons-imports';

At mobile size, the table header that contains the sort buttons is hidden and the table rows are displayed in a vertical list, so your sort buttons are no longer visible. To implement sorting at mobile size, include a rui-dropdown-button that only displays at mobile size, whose content is a description of the sorted column and direction, with dropdown options for sorting each column.

The next example is the same, with buttons for column headers that sort the table on that column for larger screen widths and a dropdown button with sort options for mobile width.

Sortable responsive table example
<rui-toolbar slot="display-block-toolbar-below" class="rui-visible-mobile">

    <rui-dropdown-button [text]="sortDescription">
        <rui-button-menu-option text="Date" (rui-menu-option-click)="sortHistory('TranDate')">
        </rui-button-menu-option>
        <rui-button-menu-option text="Effective" (rui-menu-option-click)="sortHistory('EffDate')">
        </rui-button-menu-option>
        <rui-button-menu-option text="Payee" (rui-menu-option-click)="sortHistory('Payee')">
        </rui-button-menu-option>
        <rui-button-menu-option text="Amount" (rui-menu-option-click)="sortHistory('AbsoluteAmount')">
        </rui-button-menu-option>
        <rui-button-menu-option text="New Balance" (rui-menu-option-click)="sortHistory('NewBalance')">
        </rui-button-menu-option>
    </rui-dropdown-button>

</rui-toolbar>

<table class="rui-responsive-table rui-table-minimal">
    <thead>
        <tr>
            <th>
                <rui-sort-button text="Date"
                    [showArrow]="sortColumn == 'TranDate'"
                    arrowDirection="{{ sortDirection == -1 ? 'Down' : 'Up'}}"
                    (rui-click)="sortHistory('TranDate')">
                </rui-sort-button>
            </th>
            <th>
                <rui-sort-button text="Effective"
                    [showArrow]="sortColumn == 'EffDate'"
                    arrowDirection="{{ sortDirection == -1 ? 'Down' : 'Up'}}"
                    (rui-click)="sortHistory('EffDate')">
                </rui-sort-button>
            </th>
            <th>
                <rui-sort-button text="Payee"
                    [showArrow]="sortColumn == 'Payee'"
                    arrowDirection="{{ sortDirection == -1 ? 'Down' : 'Up'}}"
                    (rui-click)="sortHistory('Payee')">
                </rui-sort-button>
            </th>
            <th class="rui-responsive-cell-right">
                <rui-sort-button text="Amount"
                    [showArrow]="sortColumn == 'AbsoluteAmount'"
                    arrowDirection="{{ sortDirection == -1 ? 'Down' : 'Up'}}"
                    (rui-click)="sortHistory('AbsoluteAmount')">
                </rui-sort-button>
            </th>
            <th class="rui-responsive-cell-right">
                <rui-sort-button text="New Balance"
                    [showArrow]="sortColumn == 'NewBalance'"
                    arrowDirection="{{ sortDirection == -1 ? 'Down' : 'Up'}}"
                    (rui-click)="sortHistory('NewBalance')">
                </rui-sort-button>
            </th>
            <th class="rui-responsive-cell-center">
                Edit
            </th>
        </tr>
    </thead>
    <tbody>
        <tr *ngFor="let transaction of sortedTransactionList">
            <td data-title="Date">{{ transaction.TranDate | jhaDate }}</td>
            <td data-title="Effective">{{ transaction.EffDate | jhaDate }}</td>
            <td data-title="Payee">{{ transaction.Payee }}</td>
            <td data-title="Amount" class="rui-responsive-cell-right">{{ transaction.AbsoluteAmount | jhaCurrency }}</td>
            <td data-title="New Balance" class="rui-responsive-cell-right">{{ transaction.NewBalance | jhaCurrency }}</td>
            <td data-title="Edit" class="rui-responsive-cell-center">
                <rui-grid-button iconType="edit"></rui-grid-button>
            </td>
        </tr>
    </tbody>
</table>

Angular wrapper development

Wrapper reference

jha-sort-button
jha-sort-button
Module: JhaButtonsModule - Package: @jkhy/responsive-ui-angular

Displays buttons in responsive table header for sorting table content

NameTypeDefaultDescription
jhaTextstring''Column header name; displayed as the button text
jhaShowArrowbooleanfalseBind to expression that evaluates to true if this column is the one being sorted and false otherwise
jhaArrowDirectionstring'Up'Indicates column sort direction: one of “Up” or “Down”
clickeventClick event for the sort button

Implementation

The responsive table is an HTML table that displays data in rows and columns at larger screen sizes and a vertically scrolling list of records at mobile size.

  • Add the jha-responsive-table and jha-table-minimal CSS classes to the table element.
  • Iterate through a list of business objects in your controller, emitting a tr element for each object in the list. Angular applications use *ngFor to do this.
  • Add a data-title attribute to each td whose value is the text title displayed at the top of the corresponding column. This allows the column header title to be displayed for each td when the table is collapsed to a vertically scrolling list of cards at mobile size.
  • It can be helpful to wrap a responsive table within a div that has overflow-x:auto so that horizontal scrollbars display at smaller screen widths. The responsive table drops into a list of vertically scrolling cards at screen widths less than 768 pixels, but the data in your table may not fit into the allocated space at widths greater than 768 pixels, so horizontal scrolling may be the best compromise.

Cell alignment

HTML table cells are left-aligned by default, but it’s best to right-align currency and numeric values so the decimal points and commas line up on the right, helping the user compare numeric values across rows.

Our first thought might be to force center and right alignment by adding inline styles to the cells. This works well at larger screen widths, but not always as well at mobile size. When the responsive table collapses to a vertical list at mobile size, we want to see all values right-aligned. Adding an inline style to force center-alignment will override the CSS and force center alignment even at mobile size, when all other values are right-aligned, which looks odd.

Here are CSS classes that you can add to responsive table cells to maintain proper horizontal alignment at different screen widths:

  • jha-responsive-cell-right: Right-aligns the cell’s content at all screen widths.
  • jha-responsive-cell-center: Center-aligns the cell’s content at larger screen widths and right-aligns it at mobile size.
  • jha-responsive-cell-left: Left-aligns the cell’s content at larger screen widths and right-aligns it at mobile size. (This CSS class is redundant since this is the default behavior, but is included for completeness.)

If a table cell tends to contain larger amounts of text that break to multiple lines at mobile size, the ragged left edge of this multi-line data can make the text harder to read. Add the jha-responsive-cell-large CSS class to cells that tend to contain larger amounts of data. This CSS class keeps the data left-aligned at all screen widths, making the long data easier to read.

Additionally, responsive tables vertically align content to the top of cells by default. Typically this is ideal so if the content wraps, all cells in a row are aligned along the top of the cell making the row shape easier to see. However, this may not always be desired, so there are classes that can be applied to the table rows that will vertically align the content that best fits your scenario.

  • jha-responsive-row-top: Top-aligns the cell’s content at all screen widths.
  • jha-responsive-row-middle: Middle-aligns the cell’s content at all screen widths.
  • jha-responsive-row-bottom: Bottom-aligns the cell’s content at all screen widths.

Responsive table example

Here is an example of a simple HTML table with a few attributes added (highlighted below) to set it up as a responsive table, running in an Angular application.

Responsive table example
<div style="overflow-x:auto">
    <table class="table jha-table-minimal jha-responsive-table">
        <thead>
            <tr>
                <th class="jha-responsive-cell-center">Date</th>
                <th class="jha-responsive-cell-center">Effective</th>
                <th>Payee</th>
                <th class="jha-responsive-cell-right">Amount</th>
                <th class="jha-responsive-cell-right">New Balance</th>
            </tr>
        </thead>
        <tbody>
            <tr class="jha-responsive-row-middle" *ngFor="let transaction of sortedTransactionList">
                <td data-title="Date" class="jha-responsive-cell-center">{{ transaction.TranDate | jhaDate }}</td>
                <td data-title="Effective" class="jha-responsive-cell-center">{{ transaction.EffDate | jhaDate }}</td>
                <td data-title="Payee">{{ transaction.Payee }}</td>
                <td data-title="Amount" class="jha-responsive-cell-right">{{ transaction.AbsoluteAmount | jhaCurrency }}</td>
                <td data-title="New Balance" class="jha-responsive-cell-right">{{ transaction.NewBalance | jhaCurrency }}</td>
            </tr>
        </tbody>
    </table>
</div>

Sorting the responsive table

If you’re adding simple sorting for your responsive table, you’ll need to use an instance of jha-sort-button instead of text for each column header that is sortable. Each time the user presses the jha-sort-button, your application will sort the table on the column that was clicked, reversing the existing sort direction. The jha-sort-button component displays an up/down arrow icon to the right of the text in the button for the sorted column; this indicates which column the table is sorted by and the current sort direction.

Begin by importing the JhaButtonsModule module into your application.

Import the module for sort buttons
// import into app.module
import { JhaButtonsModule } from '@jkhy/responsive-ui-angular/jha-buttons';

@NgModule({
    imports: [
        ...
        JhaButtonsModule,
        ...
    ]
})

export class AppModule(){}

At mobile size, the table header that contains the sort buttons is hidden and the table rows are displayed in a vertical list, so your sort buttons are no longer visible. To implement sorting at mobile size, include a jha-dropdown-button that only displays at mobile size, whose content is a description of the sorted column and direction, with dropdown options for sorting each column.

The next example is the same, with buttons for column headers that sort the table on that column for larger screen widths and a dropdown button with sort options for mobile width.

Sortable responsive table example
<jha-display-block-toolbar class="jha-visible-phone">
    <jha-dropdown-button [jhaText]="sortDescription" jhaButtonStyle="Secondary">
        <jha-button-menu-option jhaText="Date" (click)="sortHistory('TranDate')"></jha-button-menu-option>
        <jha-button-menu-option jhaText="Effective" (click)="sortHistory('EffDate')"></jha-button-menu-option>
        <jha-button-menu-option jhaText="Payee" (click)="sortHistory('Payee')"></jha-button-menu-option>
        <jha-button-menu-option jhaText="Amount" (click)="sortHistory('AbsoluteAmount')"></jha-button-menu-option>
        <jha-button-menu-option jhaText="New Balance" (click)="sortHistory('NewBalance')"></jha-button-menu-option>
    </jha-dropdown-button>
</jha-display-block-toolbar>

<div style="overflow-x:auto">
    <table class="table jha-table-minimal jha-responsive-table">
        <thead>
            <tr>
                <th class="jha-responsive-cell-center">
                    <jha-sort-button jhaText="Date" [jhaShowArrow]="sortColumn == 'TranDate'"
                     jhaArrowDirection="{{ sortDirection == -1 ? 'Down' : 'Up'}}" (click)="sortHistory('TranDate')">
                    </jha-sort-button>
                </th>
                <th class="jha-responsive-cell-center">
                    <jha-sort-button jhaText="Effective" [jhaShowArrow]="sortColumn == 'EffDate'"
                     jhaArrowDirection="{{ sortDirection == -1 ? 'Down' : 'Up'}}" (click)="sortHistory('EffDate')">
                    </jha-sort-button>
                </th>
                <th>
                    <jha-sort-button jhaText="Payee" [jhaShowArrow]="sortColumn == 'Payee'"
                     jhaArrowDirection="{{ sortDirection == -1 ? 'Down' : 'Up'}}" (click)="sortHistory('Payee')">
                    </jha-sort-button>
                </th>
                <th class="jha-responsive-cell-right">
                    <jha-sort-button jhaText="Amount" [jhaShowArrow]="sortColumn == 'AbsoluteAmount'"
                     jhaArrowDirection="{{ sortDirection == -1 ? 'Down' : 'Up'}}" (click)="sortHistory('AbsoluteAmount')">
                    </jha-sort-button>
                </th>
                <th class="jha-responsive-cell-right">
                    <jha-sort-button jhaText="New Balance" [jhaShowArrow]="sortColumn == 'NewBalance'"
                     jhaArrowDirection="{{ sortDirection == -1 ? 'Down' : 'Up'}}" (click)="sortHistory('NewBalance')">
                    </jha-sort-button>
                </th>
            </tr>
        </thead>
        <tbody>
            <tr *ngFor="let transaction of sortedTransactionList">
                <td data-title="Date" class="jha-responsive-cell-center">{{ transaction.TranDate | jhaDate }}</td>
                <td data-title="Effective" class="jha-responsive-cell-center">{{ transaction.EffDate | jhaDate }}</td>
                <td data-title="Payee">{{ transaction.Payee }}</td>
                <td data-title="Amount" class="jha-responsive-cell-right">{{ transaction.AbsoluteAmount | jhaCurrency }}</td>
                <td data-title="New Balance" class="jha-responsive-cell-right">{{ transaction.NewBalance | jhaCurrency }}</td>
            </tr>
        </tbody>
    </table>
</div>

Design

Figma design

Figma design info
You can find this component in the Components - Data Grids and Tables page in the Figma UI Kit.
Dev ComponentDesign Component Name
Responsive table header backgroundRUI / Grid / Row
Responsive table column header - sortable

RUI / Grid / Column Sort Button

Available values for the Sort Direction property:

  • Unsorted
  • Ascending
  • Descending
Responsive table column header - non-sortableAdd a text element, then apply the “rui-semibold” text style and the “rui-pacific/text-regular” color style.
Responsive table row background

RUI / Grid / Row

  • Set the component’s Appearance property value to Min w/o Separator if this is the first data row in the table. This state hides the top border line in the component (something we only want to display for subsequent data rows). Otherwise set its Appearance property value to Min with Separator.
  • Switch on the component’s Contains Input property if any cell in this row contains an input or button group component. This sets the row height to a value large enough to contain the input or button group.
Responsive table dataAdd a text element for each cell and apply the “rui-regular” text style and the “rui-pacific/text-regular” color style.
  • For the header row:
    • Add a grid row component as the header background. Set its Appearance property value to “Min w/o Separator”.
    • For each sortable column, add a column sort button (with appropriate sort direction) as a header for each column.
    • For each non-sortable column — for example columns that only display grid buttons — add a text element for the column header, apply the “rui-semibold” text style and the “rui-pacific/text-regular” color style.
  • For data rows:
    • Add a grid row component as the row background.
      • Set the component’s Appearance property value to Min w/o Separator if this is the first data row in the table. This state hides the top border line in the component (something we only want to display for subsequent data rows). Otherwise set its Appearance property value to Min with Separator.
      • Switch on the component’s Contains Input property if any cell in this row contains an input or button group component. This sets the row height to a value large enough to contain the input or button group.
    • Add a text element for each column. Apply the “rui-regular” text style and the “rui-pacific/text-regular” color style to the text element.

Adobe XD design

Adobe XD design info
You can find this component in these artboards in the Adobe XD design samples:
  • Sample App - Grid - Responsive Table
Dev ComponentDesign Component Name
Responsive table header backgroundJHA / Grid / Responsive Table Header
Responsive table header column sort button - sorted ascendingJHA / Grid / Responsive Table Sort Button / Up
Responsive table header column sort button - sorted descendingJHA / Grid / Responsive Table Sort Button / Down
Responsive table header column sort button - unsortedJHA / Grid / Responsive Table Sort Button / Unsorted
Responsive table column header - non-sortableAdd a text element, apply the “JHA / Text / Regular” character style, then make the text Semibold.
Responsive table row background

JHA / Grid / Responsive Table Row

  • Use the First Data Row state if this is the first data row in the table
  • Use the Contains Input state if any cell in this row contains an input or button group component.
  • Use the First Data Row Contains Input state if this is the first data row in the table and any cell in this row contains an input or button group component.
  • Use the Default State otherwise.
Responsive table dataAdd a text element for each cell and apply the “JHA / Text / Regular” character style.
  • For the header row:
    • Add a responsive table header component as the header background.
    • For each sortable column, add a sort button (with appropriate sort direction) to a header for each column.
    • For each non-sortable column — for example columns that include grid buttons — add a text element for the column header, apply the “JHA / Text / Regular” character style, then add Semibold styling for the text.
  • For the data rows:
    • Add a responsive table row component as the row background.
      • Set the component’s state to First Data Row if this is the first data row in the table. This state hides the top border line in the component (something we only want to display for subsequent data rows).
      • Set the component’s state to Contains Input if any cell in this row contains an input or button group component. This sets the row height to a value large enough to contain the input or button group.
      • Set the component’s state to First Data Row Contains Input if this is the first data row in the table and any cell in this row contains an input or button group component. This sets the proper height and hides the top line border.
      • Leave the component’s state as Default State otherwise.
    • Add a text element for each column. Apply the “JHA / Text / Regular” character style to the text element.
  • It can be very helpful to nest all rows in the table within a group, then turn that group into a vertical stack with 0 pixels spacing between each row. This helps keep the table layout updated if you later add or delete rows in the table.

Support options
Have questions on this topic?
Join the Responsive UI team in Microsoft Teams to connect with the community.
See something in this page that needs to change?
Send us feedback on this page.
Last updated Mon May 1 2023