Tables

Flexible table component with color variants, striping, hover states, borders, and responsive behavior.

Basic Table#

A simple table with default styling.

#FirstLastHandle
1MarkOtto@mdo
2JacobThornton@fat
3LarryBird@twitter
<%= table do |t| %>
  <% t.with_head do |head| %>
    <% head.with_row do |row| %>
      <% row.with_cell "#" %>
      <% row.with_cell "First" %>
      <% row.with_cell "Last" %>
      <% row.with_cell "Handle" %>
    <% end %>
  <% end %>

  <% t.with_body do |body| %>
    <% body.with_row do |row| %>
      <% row.with_cell "1", scope: "row" %>
      <% row.with_cell "Mark" %>
      <% row.with_cell "Otto" %>
      <% row.with_cell "@mdo" %>
    <% end %>
    <% body.with_row do |row| %>
      <% row.with_cell "2", scope: "row" %>
      <% row.with_cell "Jacob" %>
      <% row.with_cell "Thornton" %>
      <% row.with_cell "@fat" %>
    <% end %>
    <% body.with_row do |row| %>
      <% row.with_cell "3", scope: "row" %>
      <% row.with_cell "Larry" %>
      <% row.with_cell "Bird" %>
      <% row.with_cell "@twitter" %>
    <% end %>
  <% end %>
<% end %>

Variants#

Apply color variants to individual rows using the theme's semantic color system.

#VariantFirstLastHandle
1Light PrimaryMarkOtto@mdo
2Light SecondaryJacobThornton@fat
3Dark PrimaryLarryBird@twitter
4Dark SecondarySarahConnor@sarah
5SuccessJohnDoe@johndoe
6DangerJaneSmith@janesmith
7WarningBobJohnson@bob
8InfoAliceWilliams@alice
<%= table do |t| %>
  <% t.with_head do |head| %>
    <% head.with_row do |row| %>
      <% row.with_cell "#" %>
      <% row.with_cell "Variant" %>
      <% row.with_cell "First" %>
      <% row.with_cell "Last" %>
      <% row.with_cell "Handle" %>
    <% end %>
  <% end %>

  <% t.with_body do |body| %>
    <% body.with_row variant: "light-primary" do |row| %>
      <% row.with_cell "1", scope: "row" %>
      <% row.with_cell "Light Primary" %>
      <% row.with_cell "Mark" %>
      <% row.with_cell "Otto" %>
      <% row.with_cell "@mdo" %>
    <% end %>
    <% body.with_row variant: "light-secondary" do |row| %>
      <% row.with_cell "2", scope: "row" %>
      <% row.with_cell "Light Secondary" %>
      <% row.with_cell "Jacob" %>
      <% row.with_cell "Thornton" %>
      <% row.with_cell "@fat" %>
    <% end %>
    <% body.with_row variant: "dark-primary" do |row| %>
      <% row.with_cell "3", scope: "row" %>
      <% row.with_cell "Dark Primary" %>
      <% row.with_cell "Larry" %>
      <% row.with_cell "Bird" %>
      <% row.with_cell "@twitter" %>
    <% end %>
    <% body.with_row variant: "dark-secondary" do |row| %>
      <% row.with_cell "4", scope: "row" %>
      <% row.with_cell "Dark Secondary" %>
      <% row.with_cell "Sarah" %>
      <% row.with_cell "Connor" %>
      <% row.with_cell "@sarah" %>
    <% end %>
    <% body.with_row variant: "success" do |row| %>
      <% row.with_cell "5", scope: "row" %>
      <% row.with_cell "Success" %>
      <% row.with_cell "John" %>
      <% row.with_cell "Doe" %>
      <% row.with_cell "@johndoe" %>
    <% end %>
    <% body.with_row variant: "danger" do |row| %>
      <% row.with_cell "6", scope: "row" %>
      <% row.with_cell "Danger" %>
      <% row.with_cell "Jane" %>
      <% row.with_cell "Smith" %>
      <% row.with_cell "@janesmith" %>
    <% end %>
    <% body.with_row variant: "warning" do |row| %>
      <% row.with_cell "7", scope: "row" %>
      <% row.with_cell "Warning" %>
      <% row.with_cell "Bob" %>
      <% row.with_cell "Johnson" %>
      <% row.with_cell "@bob" %>
    <% end %>
    <% body.with_row variant: "info" do |row| %>
      <% row.with_cell "8", scope: "row" %>
      <% row.with_cell "Info" %>
      <% row.with_cell "Alice" %>
      <% row.with_cell "Williams" %>
      <% row.with_cell "@alice" %>
    <% end %>
  <% end %>
<% end %>

Accented Tables#

Add visual emphasis to your tables with accent styles like striping, hovering, and borders to help organize and highlight your data.

Striped#

Add zebra-striping to any table row within the <tbody>.

#FirstLastHandle
1MarkOtto@mdo
2JacobThornton@fat
3LarryBird@twitter
4JohnDoe@johndoe
<%= table(striped: true) do |t| %>
  <% t.with_head do |head| %>
    <% head.with_row do |row| %>
      <% row.with_cell "#" %>
      <% row.with_cell "First" %>
      <% row.with_cell "Last" %>
      <% row.with_cell "Handle" %>
    <% end %>
  <% end %>

  <% t.with_body do |body| %>
    <% body.with_row do |row| %>
      <% row.with_cell "1", scope: "row" %>
      <% row.with_cell "Mark" %>
      <% row.with_cell "Otto" %>
      <% row.with_cell "@mdo" %>
    <% end %>
    <% body.with_row do |row| %>
      <% row.with_cell "2", scope: "row" %>
      <% row.with_cell "Jacob" %>
      <% row.with_cell "Thornton" %>
      <% row.with_cell "@fat" %>
    <% end %>
    <% body.with_row do |row| %>
      <% row.with_cell "3", scope: "row" %>
      <% row.with_cell "Larry" %>
      <% row.with_cell "Bird" %>
      <% row.with_cell "@twitter" %>
    <% end %>
    <% body.with_row do |row| %>
      <% row.with_cell "4", scope: "row" %>
      <% row.with_cell "John" %>
      <% row.with_cell "Doe" %>
      <% row.with_cell "@johndoe" %>
    <% end %>
  <% end %>
<% end %>

Hoverable#

Add hover state on table rows.

#FirstLastHandle
1MarkOtto@mdo
2JacobThornton@fat
3LarryBird@twitter
<%= table(hover: true) do |t| %>
  <% t.with_head do |head| %>
    <% head.with_row do |row| %>
      <% row.with_cell "#" %>
      <% row.with_cell "First" %>
      <% row.with_cell "Last" %>
      <% row.with_cell "Handle" %>
    <% end %>
  <% end %>

  <% t.with_body do |body| %>
    <% body.with_row do |row| %>
      <% row.with_cell "1", scope: "row" %>
      <% row.with_cell "Mark" %>
      <% row.with_cell "Otto" %>
      <% row.with_cell "@mdo" %>
    <% end %>
    <% body.with_row do |row| %>
      <% row.with_cell "2", scope: "row" %>
      <% row.with_cell "Jacob" %>
      <% row.with_cell "Thornton" %>
      <% row.with_cell "@fat" %>
    <% end %>
    <% body.with_row do |row| %>
      <% row.with_cell "3", scope: "row" %>
      <% row.with_cell "Larry" %>
      <% row.with_cell "Bird" %>
      <% row.with_cell "@twitter" %>
    <% end %>
  <% end %>
<% end %>

Active#

Highlight a table row with the table-active class.

#FirstLastHandle
1MarkOtto@mdo
2JacobThornton@fat
3LarryBird@twitter
<%= table do |t| %>
  <% t.with_head do |head| %>
    <% head.with_row do |row| %>
      <% row.with_cell "#" %>
      <% row.with_cell "First" %>
      <% row.with_cell "Last" %>
      <% row.with_cell "Handle" %>
    <% end %>
  <% end %>

  <% t.with_body do |body| %>
    <% body.with_row do |row| %>
      <% row.with_cell "1", scope: "row" %>
      <% row.with_cell "Mark" %>
      <% row.with_cell "Otto" %>
      <% row.with_cell "@mdo" %>
    <% end %>
    <% body.with_row active: true do |row| %>
      <% row.with_cell "2", scope: "row" %>
      <% row.with_cell "Jacob" %>
      <% row.with_cell "Thornton" %>
      <% row.with_cell "@fat" %>
    <% end %>
    <% body.with_row do |row| %>
      <% row.with_cell "3", scope: "row" %>
      <% row.with_cell "Larry" %>
      <% row.with_cell "Bird" %>
      <% row.with_cell "@twitter" %>
    <% end %>
  <% end %>
<% end %>

Borders#

Add borders to your tables to create visual separation between cells and rows. Choose from bordered, borderless, or border-top styles.

Bordered#

Add borders on all sides of the table and cells.

#FirstLastHandle
1MarkOtto@mdo
2JacobThornton@fat
3LarryBird@twitter
<%= table(bordered: true) do |t| %>
  <% t.with_head do |head| %>
    <% head.with_row do |row| %>
      <% row.with_cell "#" %>
      <% row.with_cell "First" %>
      <% row.with_cell "Last" %>
      <% row.with_cell "Handle" %>
    <% end %>
  <% end %>

  <% t.with_body do |body| %>
    <% body.with_row do |row| %>
      <% row.with_cell "1", scope: "row" %>
      <% row.with_cell "Mark" %>
      <% row.with_cell "Otto" %>
      <% row.with_cell "@mdo" %>
    <% end %>
    <% body.with_row do |row| %>
      <% row.with_cell "2", scope: "row" %>
      <% row.with_cell "Jacob" %>
      <% row.with_cell "Thornton" %>
      <% row.with_cell "@fat" %>
    <% end %>
    <% body.with_row do |row| %>
      <% row.with_cell "3", scope: "row" %>
      <% row.with_cell "Larry" %>
      <% row.with_cell "Bird" %>
      <% row.with_cell "@twitter" %>
    <% end %>
  <% end %>
<% end %>

No borders#

Remove all borders from the table.

#FirstLastHandle
1MarkOtto@mdo
2JacobThornton@fat
3LarryBird@twitter
<%= table(borderless: true) do |t| %>
  <% t.with_head do |head| %>
    <% head.with_row do |row| %>
      <% row.with_cell "#" %>
      <% row.with_cell "First" %>
      <% row.with_cell "Last" %>
      <% row.with_cell "Handle" %>
    <% end %>
  <% end %>

  <% t.with_body do |body| %>
    <% body.with_row do |row| %>
      <% row.with_cell "1", scope: "row" %>
      <% row.with_cell "Mark" %>
      <% row.with_cell "Otto" %>
      <% row.with_cell "@mdo" %>
    <% end %>
    <% body.with_row do |row| %>
      <% row.with_cell "2", scope: "row" %>
      <% row.with_cell "Jacob" %>
      <% row.with_cell "Thornton" %>
      <% row.with_cell "@fat" %>
    <% end %>
    <% body.with_row do |row| %>
      <% row.with_cell "3", scope: "row" %>
      <% row.with_cell "Larry" %>
      <% row.with_cell "Bird" %>
      <% row.with_cell "@twitter" %>
    <% end %>
  <% end %>
<% end %>

Small Tables#

Make tables more compact by reducing cell padding.

#FirstLastHandle
1MarkOtto@mdo
2JacobThornton@fat
3LarryBird@twitter
<%= table(small: true) do |t| %>
  <% t.with_head do |head| %>
    <% head.with_row do |row| %>
      <% row.with_cell "#" %>
      <% row.with_cell "First" %>
      <% row.with_cell "Last" %>
      <% row.with_cell "Handle" %>
    <% end %>
  <% end %>

  <% t.with_body do |body| %>
    <% body.with_row do |row| %>
      <% row.with_cell "1", scope: "row" %>
      <% row.with_cell "Mark" %>
      <% row.with_cell "Otto" %>
      <% row.with_cell "@mdo" %>
    <% end %>
    <% body.with_row do |row| %>
      <% row.with_cell "2", scope: "row" %>
      <% row.with_cell "Jacob" %>
      <% row.with_cell "Thornton" %>
      <% row.with_cell "@fat" %>
    <% end %>
    <% body.with_row do |row| %>
      <% row.with_cell "3", scope: "row" %>
      <% row.with_cell "Larry" %>
      <% row.with_cell "Bird" %>
      <% row.with_cell "@twitter" %>
    <% end %>
  <% end %>
<% end %>

Vertical Alignment#

Control the vertical alignment of table cells.

Top#

Heading 1Heading 2Heading 3
This cell has a lot of content that spans multiple lines to demonstrate vertical alignment behavior in table cells.ShortContent
<%= table(align: :top) do |t| %>
  <% t.with_head do |head| %>
    <% head.with_row do |row| %>
      <% row.with_cell "Heading 1" %>
      <% row.with_cell "Heading 2" %>
      <% row.with_cell "Heading 3" %>
    <% end %>
  <% end %>

  <% t.with_body do |body| %>
    <% body.with_row do |row| %>
      <% row.with_cell "This cell has a lot of content that spans multiple lines to demonstrate vertical alignment behavior in table cells." %>
      <% row.with_cell "Short" %>
      <% row.with_cell "Content" %>
    <% end %>
  <% end %>
<% end %>

Middle (Default)#

Heading 1Heading 2Heading 3
This cell has a lot of content that spans multiple lines to demonstrate vertical alignment behavior in table cells.ShortContent
<%= table(align: :middle) do |t| %>
  <% t.with_head do |head| %>
    <% head.with_row do |row| %>
      <% row.with_cell "Heading 1" %>
      <% row.with_cell "Heading 2" %>
      <% row.with_cell "Heading 3" %>
    <% end %>
  <% end %>

  <% t.with_body do |body| %>
    <% body.with_row do |row| %>
      <% row.with_cell "This cell has a lot of content that spans multiple lines to demonstrate vertical alignment behavior in table cells." %>
      <% row.with_cell "Short" %>
      <% row.with_cell "Content" %>
    <% end %>
  <% end %>
<% end %>

Bottom#

Heading 1Heading 2Heading 3
This cell has a lot of content that spans multiple lines to demonstrate vertical alignment behavior in table cells.ShortContent
<%= table(align: :bottom) do |t| %>
  <% t.with_head do |head| %>
    <% head.with_row do |row| %>
      <% row.with_cell "Heading 1" %>
      <% row.with_cell "Heading 2" %>
      <% row.with_cell "Heading 3" %>
    <% end %>
  <% end %>

  <% t.with_body do |body| %>
    <% body.with_row do |row| %>
      <% row.with_cell "This cell has a lot of content that spans multiple lines to demonstrate vertical alignment behavior in table cells." %>
      <% row.with_cell "Short" %>
      <% row.with_cell "Content" %>
    <% end %>
  <% end %>
<% end %>

Table Captions#

Add a caption to provide context for your table.

List of users
#FirstLastHandle
1MarkOtto@mdo
2JacobThornton@fat
<%= table do |t| %>
  <% t.with_caption("List of users") %>

  <% t.with_head do |head| %>
    <% head.with_row do |row| %>
      <% row.with_cell "#" %>
      <% row.with_cell "First" %>
      <% row.with_cell "Last" %>
      <% row.with_cell "Handle" %>
    <% end %>
  <% end %>

  <% t.with_body do |body| %>
    <% body.with_row do |row| %>
      <% row.with_cell "1", scope: "row" %>
      <% row.with_cell "Mark" %>
      <% row.with_cell "Otto" %>
      <% row.with_cell "@mdo" %>
    <% end %>
    <% body.with_row do |row| %>
      <% row.with_cell "2", scope: "row" %>
      <% row.with_cell "Jacob" %>
      <% row.with_cell "Thornton" %>
      <% row.with_cell "@fat" %>
    <% end %>
  <% end %>
<% end %>

Bottom Caption#

List of users shown below
#FirstLastHandle
1MarkOtto@mdo
2JacobThornton@fat
<%= table do |t| %>
  <% t.with_caption("List of users shown below", position: :bottom) %>

  <% t.with_head do |head| %>
    <% head.with_row do |row| %>
      <% row.with_cell "#" %>
      <% row.with_cell "First" %>
      <% row.with_cell "Last" %>
      <% row.with_cell "Handle" %>
    <% end %>
  <% end %>

  <% t.with_body do |body| %>
    <% body.with_row do |row| %>
      <% row.with_cell "1", scope: "row" %>
      <% row.with_cell "Mark" %>
      <% row.with_cell "Otto" %>
      <% row.with_cell "@mdo" %>
    <% end %>
    <% body.with_row do |row| %>
      <% row.with_cell "2", scope: "row" %>
      <% row.with_cell "Jacob" %>
      <% row.with_cell "Thornton" %>
      <% row.with_cell "@fat" %>
    <% end %>
  <% end %>
<% end %>

Nesting#

Tables can be nested inside table cells.

# Name Details
1 John Doe
Project Status
Project A Complete
Project B In Progress
2 Jane Smith
Project Status
Project C Complete
<table class="table table-bordered">
  <thead>
    <tr>
      <th scope="col">#</th>
      <th scope="col">Name</th>
      <th scope="col">Details</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <th scope="row">1</th>
      <td>John Doe</td>
      <td>
        <table class="table table-sm table-bordered">
          <thead>
            <tr>
              <th>Project</th>
              <th>Status</th>
            </tr>
          </thead>

          <tbody>
            <tr>
              <td>Project A</td>
              <td>Complete</td>
            </tr>

            <tr>
              <td>Project B</td>
              <td>In Progress</td>
            </tr>
          </tbody>
        </table>
      </td>
    </tr>

    <tr>
      <th scope="row">2</th>
      <td>Jane Smith</td>
      <td>
        <table class="table table-sm table-bordered">
          <thead>
            <tr>
              <th>Project</th>
              <th>Status</th>
            </tr>
          </thead>

          <tbody>
            <tr>
              <td>Project C</td>
              <td>Complete</td>
            </tr>
          </tbody>
        </table>
      </td>
    </tr>
  </tbody>
</table>

Responsive Tables#

Make tables scroll horizontally on small screens.

#Heading 1Heading 2Heading 3Heading 4Heading 5Heading 6Heading 7Heading 8Heading 9
1CellCellCellCellCellCellCellCellCell
2CellCellCellCellCellCellCellCellCell
3CellCellCellCellCellCellCellCellCell
<%= table(responsive: true) do |t| %>
  <% t.with_head do |head| %>
    <% head.with_row do |row| %>
      <% row.with_cell "#" %>
      <% row.with_cell "Heading 1" %>
      <% row.with_cell "Heading 2" %>
      <% row.with_cell "Heading 3" %>
      <% row.with_cell "Heading 4" %>
      <% row.with_cell "Heading 5" %>
      <% row.with_cell "Heading 6" %>
      <% row.with_cell "Heading 7" %>
      <% row.with_cell "Heading 8" %>
      <% row.with_cell "Heading 9" %>
    <% end %>
  <% end %>

  <% t.with_body do |body| %>
    <% body.with_row do |row| %>
      <% row.with_cell "1", scope: "row" %>
      <% row.with_cell "Cell" %>
      <% row.with_cell "Cell" %>
      <% row.with_cell "Cell" %>
      <% row.with_cell "Cell" %>
      <% row.with_cell "Cell" %>
      <% row.with_cell "Cell" %>
      <% row.with_cell "Cell" %>
      <% row.with_cell "Cell" %>
      <% row.with_cell "Cell" %>
    <% end %>
    <% body.with_row do |row| %>
      <% row.with_cell "2", scope: "row" %>
      <% row.with_cell "Cell" %>
      <% row.with_cell "Cell" %>
      <% row.with_cell "Cell" %>
      <% row.with_cell "Cell" %>
      <% row.with_cell "Cell" %>
      <% row.with_cell "Cell" %>
      <% row.with_cell "Cell" %>
      <% row.with_cell "Cell" %>
      <% row.with_cell "Cell" %>
    <% end %>
    <% body.with_row do |row| %>
      <% row.with_cell "3", scope: "row" %>
      <% row.with_cell "Cell" %>
      <% row.with_cell "Cell" %>
      <% row.with_cell "Cell" %>
      <% row.with_cell "Cell" %>
      <% row.with_cell "Cell" %>
      <% row.with_cell "Cell" %>
      <% row.with_cell "Cell" %>
      <% row.with_cell "Cell" %>
      <% row.with_cell "Cell" %>
    <% end %>
  <% end %>
<% end %>

Property Tables#

Specialized two-column tables for displaying object properties, database records, or key-value pairs. Property tables provide a clean layout for showing attributes with names and values.

Basic Usage#

A simple property table with name-value pairs.

NameJohn Doe
Emailjohn.doe@example.com
Phone+1 (555) 123-4567
StatusActive
<%= property_table striped: true, hover: true do |t| %>
  <% t.with_property "Name", "John Doe" %>
  <% t.with_property "Email", "john.doe@example.com" %>
  <% t.with_property "Phone", "+1 (555) 123-4567" %>
  <% t.with_property "Status", "Active" %>
<% end %>

HTML Content#

Property values can contain HTML content by using a block.

NameJohn Doe
Email john.doe@example.com
Status Active
Actions
<%= property_table do |t| %>
  <% t.with_property "Name", "John Doe" %>
  <% t.with_property "Email" do %>
    <%= link_to "john.doe@example.com", "mailto:john.doe@example.com" %>
  <% end %>
  <% t.with_property "Status" do %>
    <%= badge("Active", variant: "success") %>
  <% end %>
  <% t.with_property "Actions" do %>
    <%= button("Edit", variant: "primary", size: "sm") %>
    <%= button("Delete", variant: "danger", size: "sm") %>
  <% end %>
<% end %>