Customize Tables in CSS
You may have glanced at that title and wondered, “Table layout? Isn’t that exactly what we’re trying to avoid doing?” Indeed so, but this chapter is not about using tables for layout. Instead, it’s about the ways that tables themselves are laid out by CSS, which is a far more complicated affair than it might first appear..
Tables are unusual, compared to the rest of document layout. Until flexbox and grid came along, tables alone possessed the unique ability to associate element sizes with other elements-for example, all the cells in a row have the same height, no matter how much or how little content each individual cell might contain. The same is true for the widths of cells that share a column. Cells that adjoin can share a border, even if the two cells have very different border styles. As we’ll see, these abilities are pur- chased at the expensof a great many behaviors and rules-many of them rooted deep in the past-that apply to tables, and only tables.
Different Customization Properties in CSS
Table Formatting
Before we can start to worry about how cell borders are drawn and tables sized, we need to delve into the fundamental ways in which tables are assembled, and the ways that elements within a table are related. This is referred to as table formatting, and it is quite distinct from table layout: the layout is possible only after the formatting has been completed.
Visually Arranging a Table
The first thing to understand is how CSS defines the arrangement of tables. While this knowledge may seem a bit basic, it’s key to understanding how best to style tables CSS draws a distinction between table elements and internal table elements. In CSS, internal table elements generate rectangular boxes that have content, padding, and borders, but not margins. Therefore, it is not possible to define the separation between table cells by giving them margins. A CSS-conformant browser will ignore any attempts to apply margins to cells, rows, or any other internal table element (with the exception of captions, which are discussed in the section.
To customize tables in CSS, you can use various properties to modify the appearance, such as changing the border, background, font, and alignment. Here’s an example of how you can customize tables using CSS:
HTML:
<table>
<thead>
<tr>
<th>Product</th>
<th>Price</th>
<th>Quantity</th>
<th>Total</th>
</tr>
</thead>
<tbody>
<tr>
<td>Product 1</td>
<td>$10</td>
<td>2</td>
<td>$20</td>
</tr>
<tr>
<td>Product 2</td>
<td>$15</td>
<td>3</td>
<td>$45</td>
</tr>
<tr>
<td>Product 3</td>
<td>$8</td>
<td>5</td>
<td>$40</td>
</tr>
</tbody>
</table>
CSS:
table {
border-collapse: collapse;
width: 100%;
}
th, td {
border: 1px solid black;
padding: 8px;
text-align: left;
}
thead {
background-color: #f2f2f2;
}
tbody tr:nth-child(even) {
background-color: #dddddd;
}
In this example, we have a basic table structure with a table header (thead) and table body (tbody) sections. The CSS rules are applied to customize the appearance of the table.
Here’s a breakdown of the CSS properties used:
- border-collapse: collapse;: This property ensures that the borders between table cells collapse into a single border.
- width: 100%;: The table width is set to 100% of its container.
- border: 1px solid black;: The table cells (th and td) have a 1-pixel solid black border.
- padding: 8px;: Adds 8 pixels of padding inside each table cell.
- text-align: left;: Sets the text alignment of the table cells to the left.
- background-color: #f2f2f2;: Sets the background color of the table header (thead) to a light gray.
- tbody tr:nth-child(even): Selects every even row in the table body (tbody) and sets the background color to a slightly darker gray (#dddddd).
You can modify these CSS properties according to your desired customization preferences to style your tables in different ways.
Table arrangement rules
- Each row bow encompasses a single row of grid cells. All the row boxes in a table fill the table from top to bottom in the order they occur in the source document (with the exception of any table-header or table-footer row boxes, which come at the beginning and end of the table,spectively). Thus, a table contains as many grid rows as there are row elements (eg. tr elements).
- A row group’s box encompasses the same grid cells as the row boxes it contains.
- A column box encompasses one or more columns of grid cells. All the column boxes are placed next to one another in the order they occur. The first column. box is on the left for left-to-right languages, and on the right for right-to-left lan- guages.
- A column group’s box encompasses the same grid cells as the column boxes it contains.
- Although cells may span several rows or columns, CSS does not define how this happens. It is instead left to the document language to define spanning. Each spanned cell is a rectangular box one or more grid cells wide and high. The top row of this spanning rectangle is in the row that is parent to the spanned grid cell. The cell’s rectangle must be as far to the left as possible in left-to-right lan- guages, but it may not overlap any other cell box. It must also be to the right of all cells in the same row that are earlier in the source document (in a left-to-right language). In right-to-left languages, a spanned cell must be as far to the right as possible without overlapping other cells, and must be to the left of all cells in the same row that follow it in the document source.
- A cell’s box cannot extend beyond the last row box of a table or row group. If the table structure would cause this condition, the cell must be shortened until it fits within the table or row group that encloses it.
Table Display Values
In HTML, it’s easy to know which elements are parts of tables because the handling of clements like tr and td is built into browsers. In XML, on the other hand, there is no way to intrinsically know which elements might be part of a table. This is where a whole collection of values for display come into play.
In this text, we’ll stick to the table-related values, as the others (block, inline, inline-block, run-in, and list-iten) are beyond the scope of tables. The table- related values can be summarized as follows:
table: This value specifies that an element defines a block-level table. Thus, it defines a rectangular block that generates a block box. The corresponding HTML element is, not surprisingly, table.
inline-table: This value specifies that an element defines an inline-level table. This means the element defines a rectangular block that generates an inline box. The closest non- table analogue is the value inline-block. The closest HTML element is table. although, by default, HTML tables are not inline
table-row: This value specifies that an element is a row of table cells. The corresponding HTML element is the tr element.
table-row-group: This value specifies that an element groups one or more table rows. The corre sponding HTML value is tbody.
table-header-group: This value is very much like table-row-group, except that for visual formatting. the header row group is always displayed before all other rows and row groups, and after any top captions. In print, if a table requires multiple pages to print, a user agent may repeat header rows at the top of each page (Firefox does this, for example). The specification does not define what happens if you assign table. header-group to multiple elements. A header group can contain multiple rows. The HTML equivalent is thead.
table-footer-group: This value is very much like table-header-group, except that the footer row group is always displayed after all other rows and row groups, and before any bottom captions. In print, if a table requires multiple pages to print, a user agent may repeat footer rows at the bottom of each page. The specification does not define what happens if you assign table-footer-group to multiple elements. This is equivalent to the HTML element tfoot.
table-column: This value declares that an element describes a column of table cells. In CSS terms, elements with this display value are not visually rendered, as if they had the value none. Their existence is largely for the purposes of helping to define the presentation of cells within the column. The HTML equivalent is the col element.
table-column-group: This value declares that an element groups one or more columns. Like table- column elements, table-column-group elements are not rendered, but the value is useful for defining presentation for elements within the column group. The HTML equivalent is the colgroup element.
table-cell: This value specifies that an element represents a single cell in a table. The HTML elements th and td are both examples of table-cell elements.
table-caption: This value defines a table’s caption. CSS does not define what should happen if multiple elements have the value caption, but it does explicitly warn, “…authors should not put more than one element with display: caption inside a table or inline-table element.
You can get a quick summary of the general effects of these values by taking an excerpt from the example HTML 4.0 stylesheet given in Appendix D of the CSS 2.1 specification:
table (display: table;} tr (display: table-row:)
thead (display: table-header-group;) tbody (display: table-row-group;}
tfoot (display: table-footer group
col (display: table-column;)
;}
colgroup (display: table-column-group; }
td, th (display: table-cell:)
caption (display: table-caption;) In XML, where elements will not have display semantics by default, these values become quite useful. Consider the following markup:
<scores>
<headers>
<label>Team</label> <label>Score</label>
</headers>
<game sport="ALB" league="NL">
<team <name>Reds</name>
<score>8</score>
</team>
<team>
<name>Cubs</name> <score>5</score>
</team>
</game>
</scores>
This could be formatted in a tabular fashion using the following styles:
scores {display: table;}
game {display: table-row-group;}
headers {display: table-header-group; } label, name, score {display: table-cell;}
tean {display: table-row;}
The various cells could then be styled as necessary-for example, boldfacing the label elements and right-aligning the scores.