I have a table which contains multiple tbody
elements — some created by the browser, and some that I have written in myself for programmatic reasons. I want to apply styling to only the first tr
within my table, which I would normally use table > tr
for. However, my styling cannot assume that a tbody
element does or does not exist, because I don't know that every user's browser is adding in tbody
elements automatically in every case.
As you can see, an unwanted border styling is applied to the first tr
within the second tbody
of this table. How can I get this to be applied to only the first tr
in my table without regards to the presence of a tbody
tag?
.my-table {
border-collapse: collapse;
}
.my-table td,
.my-table th {
text-align: left;
padding: 6px 8px;
align-content: center;
box-sizing: border-box;
}
.my-table td[colspan="42"] {
text-align: center;
background-color: lightgray;
}
.my-table th {
padding-top: 12px;
padding-bottom: 12px;
background-color: #0e3e64;
color: white;
text-align: center;
}
.my-table tr:not(:first-child) {
border: 1px solid #efefef;
}
/*here's the styling I don't want applied to that third tr in my table*/
.my-table tr:first-child {
border: 1px solid #0e3e64;
}
<table class="my-table">
<tr>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 3</th>
</tr>
<tr>
<td colspan="42">Section 1</td>
</tr>
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
<td>Cell 3</td>
</tr>
<tbody>
<tr>
<td colspan="42">Section 2</td>
</tr>
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
<td>Cell 3</td>
</tr>
</tbody>
</table>
Unfortunately in your case, CSS does not provide a "first occurrence on page", nor a "first occurrence within parent" selector that ignores immediate-parent. As CSS stands for Cascading Style Sheets, it doesn't exactly fit within the inherent functionality of the language - default behavior is directly related to parent elements, rather than an entire page.
If your table was always going to have a tbody
, you could do the following:
.my-table tbody:first-of-type tr:first-child { ... }
Though, if you truly wanted to select the first occurrence of a <tr>
within .my-table
, you'd need a JavaScript solution. For this, I'd suggest jQuery, simply because it makes DOM/element manipulation much simpler:
$(".my-table tr").first().css("border", "1px solid #0e3e64");
EDIT: As torazaburo mentions in the comments, the second portion of this answer isn't exactly necessary. Regardless of whether or not a tbody
is declared, the browser will automatically insert one into all <table>
elements. For this reason, selecting "first row of first tbody" should be a sufficient solution in all cases.
A good method is to use additional classes:
css :
/* Custom CSS class */
tr .custom {
color: #ff0000;
}
html :
<tr class="custom"><th>Column 1</th></tr>
Note, you can add this to existing class as <tr class="otherCls custom">
You can assign a specific "id" to your third tr and use it in the css.
<style>
.my-table {
border-collapse: collapse;
}
.my-table td,
.my-table th {
text-align: left;
padding: 6px 8px;
align-content: center;
box-sizing: border-box;
}
.my-table td[colspan="42"] {
text-align: center;
background-color: lightgray;
}
.my-table th {
padding-top: 12px;
padding-bottom: 12px;
background-color: #0e3e64;
color: white;
text-align: center;
}
.my-table tr:not(:first-child) {
border: 1px solid #efefef;
}
/*here's the styling I don't want applied to that third tr in my table*/
#third{
border: 5px solid #0e3e64;
}
</style>
</head>
<body>
<table class="my-table">
<tr>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 3</th>
</tr>
<tr>
<td colspan="42">Section 1</td>
</tr>
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
<td>Cell 3</td>
</tr>
<tbody>
<tr>
<td colspan="42">Section 2</td>
</tr>
<tr id="third">
<td>Cell 1</td>
<td>Cell 2</td>
<td>Cell 3</td>
</tr>
</tbody>
</table>
</body>
</html>
As @Santi stated in his answer, what I'm asking for isn't really possible with raw CSS, because table tr:first-child
doesn't translate as "first tr within table", it translates more like "first tr within its parent element within table", which may be the table
itself, or it may be tbody
or thead
.
His answer works perfectly fine, but for those reading this who don't want to use JavaScript, I'll share what solution I'm going to use.
I'm just going to explicitly surround the header row in each of my tables with a thead
wrapper, and change my problematic styling code to look like this:
.my-table > thead > tr:first-child {
border: 1px solid #0e3e64;
}
It still requires me to manually change old tables, but it doesn't require me to worry about multiple occurrences of tbody
elements.
According to this post , any browser worth their salt will insert a <tbody>
into a <table>
, and according to this :
8.2.5.4.9 The "in table" insertion mode ...
A start tag whose tag name is one of: "td", "th", "tr"
Act as if a start tag token with the tag name "tbody" had been seen, then reprocess the current token.
Coincides with that default behavior. Can you show us any example of which this doesn't happen? So using:
.my-table tbody:first-of-type tr:first-of-type { ... }
or
.my-table tbody:first-of-type tr:first-child { ... }
wouldn't work?
This Snippet shows a basic <table>
with <tr>
please review it in different browsers and the result in console should report the same:
SNIPPET
var row = document.querySelector('tr'); console.log(row.parentNode.nodeName);
<table> <tr></tr> </table>
Ok, here you are. Style only applied to the first tr child no matter if you have <thead>
, <tbody>
, both or none:
table { width: 200px; height: 400px; } thead { height: 100px; } tr { background-color: grey; height: 100px; } table > :nth-child(1) > tr:nth-of-type(1) { background-color: red; }
<body> Head and body <table> <thead> <tr><td>Head</td></tr> </thead> <tbody> <tr><td>Body</td></tr> <tr><td></td></tr> <tr><td></td></tr> </tbody> </table> No head <table> <tr><td></td></tr> <tr><td></td></tr> <tr><td></td></tr> <tr><td></td></tr> </table> </body>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.