As you might know, position: sticky; has landed in Webkit (demo).
So far I can see this only works within the parent element. But I'd like to know if I can use this in a scrolling div with a table.
So it needs to 'listen' on the scrolling event of the div, not the table.
I know I can do this with javascript and absolute positioning, but I was wondering if the sticky-positioning would support this.
Position sticky on thead th works in 2018!
In your stylesheets just add this one line:
thead th { position: sticky; top: 0; }
Your table will need to include thead and th for this to style.
<table>
<thead>
<tr>
<th>column 1</th>
<th>column 2</th>
<th>column 3</th>
<th>column 4</th>
</tr>
</thead>
<tbody>
// your body code
</tbody>
</table>
Also, if you have multiple rows in thead, you can select the first one to remain sticky:
thead tr:first-child th { position: sticky; top: 0; }
As of March 2018 support is pretty much there across modern browsers
ref: https://caniuse.com/#feat=css-sticky
Credit goes to #ctf0 for this one (ref comment made 3 Dec 2017)
If you need sticky header for chrome only then you can set position: sticky; top: some_value (top property is mandatory) for td element in a thead element.
See:
<table border=1>
<thead>
<tr>
<td style='position: sticky; top: -1px;background: red'>Sticky Column</td>
<td>Simple column</td>
</tr>
</thead>
table with a stiky header
position: sticky doesn't work with table elements (as long as their display attribute starts with table-) since tables are not part of specification:
Other kinds of layout, such as tables, "floating" boxes, ruby annotations, grid layouts, columns and basic handling of normal "flow" content, are described in other modules.
Edit: As Jul 2019 according to https://caniuse.com/#feat=css-sticky Firefox supports this feature and Chrome has at least support for <th> tag.
As it turns out it position: sticky only works in the window and not in a scrolling div.
I created a test-case with a very long table with a table header:
h1 {
font-size: 18px;
font-weight: bold;
margin: 10px 0;
}
div.testTable {
height: 200px;
overflow: auto;
}
table.stickyHead thead {
position: -webkit-sticky;
top: 0px;
background: grey;
}
table.stickyHead td,
table.stickyHead th {
padding: 2px 3px;
}
<h1>Position sticky</h1>
<div class="testTable">
<table class="stickyHead">
<thead>
<tr>
<th>column 1</th>
<th>column 2</th>
<th>column 3</th>
<th>column 4</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
</tbody>
</table>
</div>
As you can see, if you remove the overflow from the wrapper and make your window not so tall, the table-head is sticking to the top of the window. I doesn't apply to the wrapping div even if you make give the div position: relative
Caution:
position:sticky doesn't work anymore on Google Chrome in 2019, try to use fixed instead or display:inline-block
Setting the position:sticky for the thead is enough, no need to set it for th :
table.StickyHeader thead {
position: sticky;
top: 0px;
}
Tested in:
Edge 105.0.1343.42 ,
Firefox 105.0 ,
Chrome 105.0.5195.127 ,
Opera 91.0.4516.16
But, Firefox can not render borders of th when position of thead is set to sticky and th has background-color:
table.StickyHeader th {
border: 1px solid black;
padding: 5px;
background-color: gold;
text-align: center;
}
Firefox
Edge, Chrome, Opera
Related
I am working on a table that is optimized with Bootstrap and I encounter the following problem I want column 1 both header and body to have font size 12px then column number 2 both header and body to have font size 21px.
In other words, I want to customize the font as I want for each column.
Code:
<table class="table">
<thead>
<tr>
<th style="font-size: 12px;">1</th>
<th style="font-size: 21px;">2</th>
<th style="font-size: 12px;">3</th>
<th style="font-size: 21px;">4</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
</tbody>
</table>
You need to use nth-child/nth-of-type and if you want a zebra style (column-based) you can use odd and even
/*one approach */
.table th:first-child,
.table td:first-child {
font-size: 21px
}
.table th:nth-child(2),
.table td:nth-child(2) {
font-size: 12px
}
/*second approach */
/* odd */
.table th:nth-child(2n+1),
.table td:nth-child(2n+1) {
background: red
}
/* even */
.table th:nth-child(2n),
.table td:nth-child(2n) {
background: lightblue
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap#4.5.3/dist/css/bootstrap.min.css" rel="stylesheet" />
<table class="table">
<thead>
<tr>
<th>1</th>
<th>2</th>
<th>3</th>
<th>4</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
</tbody>
</table>
you can also use odd and even keywords with nth-child:
th:nth-child(odd),
td:nth-child(odd){
font-size: 12px;
}
th:nth-child(even),
td:nth-child(even){
font-size: 21px;
}
<table class="table">
<thead>
<tr>
<th>1</th>
<th>2</th>
<th>3</th>
<th>4</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
</tbody>
</table>
Easily with CSS nth-child you can target what ever child you want, see below:
td:nth-child(1),
td:nth-child(3),
th:nth-child(1),
th:nth-child(3){
font-size: 12px
}
td:nth-child(2),
td:nth-child(4),
th:nth-child(2),
th:nth-child(4){
font-size: 21px
}
<table class="table">
<thead>
<tr>
<th>1</th>
<th>2</th>
<th>3</th>
<th>4</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
</tbody>
</table>
Check MDN Web Docs for more about nth-child
table {
border:1px solid red;
width:100%;
position: relative;
}
table tbody {
height:100px;
overflow-y:auto;
display:block;
}
table tbody tr {
display:table;
width:100%;
}
td,th {
text-align: center;
}
<div>
<table>
<thead>
<tr>
<th>1</th>
<th>2</th>
<th>3</th>
<th>4</th>
<th>5</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr><tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr><tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
</tbody>
</table>
</div>
Some reasons, the tbody not expanding with 100%. any one figure-out the issue?
I can see a couple of problems that causes this:
You have css styling on the table tbody tr to: display: table;
And table tbody { display: block; }
Remove those and the issue should be fixed.
Edit: PS, for keeping the table height and a scroll when needed, I would wrap the table in a div and have the div set to something like:
div.table-wrap {
height: 100px;
overflow-y:auto;
}
Regardless of which browser is rendering, the css rule width: 100% sets the element in question to a width of 100% of the parent element. So the table is 100% of its parent element, whatever that is, and on the tbody you have not set a width, so when you set the width of the rows to 100%, it is 100% of the tbody's width, which the browser will set to whatever it feels is appropriate.
If you want to make sure something is as wide as the viewport, set the width to 100vw, or make sure every parent of the element has width 100% all the way up to the html tag.
And as Vitikka pointed out, you shouln't set display:table on the tr tags.
You can use this example, it will work guessing you are using Bootstrap!
<table style="width:100%;">
Inside the table tag, you can add styles without placing them in your CSS file. Another example using Bootstrap:
<table class="bg-dark text-white" style="width:100%;">
You can also style using the style tag any td or tr tag too.
<th class="text-center text-white" style="text-transform:uppercase;">Content goes here</th>
I was tasked with creating a table that would be used as the major portion of a layout. The header of the table should be static while body should scroll if necessary. The issue is that if the scrollbar is needed, the columns of the table becomes misaligned because the width of the tbody changes.
I used a bit of javascript to compensate by setting the right padding on the thead to be equal to the width of the scrollbar, and planned to use a listener to remove / add back the padding as the scrollbar disappeared / appeared.
While this approach worked to keep the columns aligned, I was asked to come up with an HTML/CSS only solution if possible. Does anyone know of a way to achieve this without any js? Thanks.
Some relevant CSS I currently have:
table {
width: 100%;
border-collapse: collapse;
}
table tbody {
position: absolute;
top: 24px;
left: 0;
right: 0;
bottom: 0;
overflow-y: auto;
}
table thead {
position: absolute;
top: 0;
left: 0;
right: 0;
}
Here is a fiddle to see the whole example: http://jsfiddle.net/kirky93/qqv73kjo/5/
Drag the viewport up/down to make the scrollbar dis/appear to see the issue.
To eliminate the misalignment with pure CSS, we can get the scrollbar to push the header aside. We can do this by making it position: fixed so that the scroll bar on the tbody extends to the top of the viewport.
Too much to read? Skip to the example at the bottom.
Column colors and widths
Use seven <col> elements, one to represent each column. We can place the class on them with width and background color and these properties will be repeated for the entire column without having to put a class on each table cell. They look like this:
<table class="fixed">
<col class="one">
<col class="two">
<col class="three">
<col class="four">
<col class="five">
<col class="six">
<col class="seven">
In order to place a width CSS property on the columns, we can set table-layout: fixed on the table element. No matching min/max widths are needed now.
Getting the thead to scroll
Set position: fixed
Set display: table to make it behave like a table again
Set table-layout: fixed so that the width behave properly
Because the thead is now effectively removed from its table and <col> elements, set the column classes on each th
The tbody
Leave it at its initial position: static
Set a top margin the same height as the thead
Full Example
Note the box-sizing: border-box which makes elements include padding and borders into their widths and heights.
html {
box-sizing: border-box;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
body {
margin: 0;
}
table {
border-collapse: collapse;
background: #FFF;
table-layout: fixed;
width: 100%;
}
table thead {
position: fixed;
top: 0;
left: 0;
width: 100%;
background: #FFF;
display: table;
table-layout: fixed;
border: solid 1px #000;
}
table tbody {
margin-top: 24px;
}
table {
/*Make sure table has border that matches the cell border so it is included in the width*/
border: 1px solid black;
}
td,
th {
height: 20px;
border: 1px solid black;
}
.one {
width: 30px;
background-color: yellow;
}
.two {
width: 30px;
background-color: orange;
}
.three {
width: 30px;
background-color: red;
}
.four {
width: 100%;
}
.five {
width: 100px;
background-color: green;
}
.six {
width: 100px;
background-color: lightblue;
}
.seven {
width: 100px;
}
<table class="fixed">
<col class="one">
<col class="two">
<col class="three">
<col class="four">
<col class="five">
<col class="six">
<col class="seven">
<thead>
<tr>
<th class="one">1</th>
<th class="two">2</th>
<th class="three">3</th>
<th class="four">4</th>
<th class="five">5</th>
<th class="six">6</th>
<th class="seven">7</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
</tr>
</tbody>
</table>
just set it to overflow:scroll on the tbody instead of auto
table tbody {
position: absolute;
top: 24px;
left: 0;
right: 0;
bottom: 0;
overflow-y: scroll;
}
I was hoping I could get some help with removing a table border from an "nested" (not sure if that is the proper terminology).
Here is what I have so far:
<table>
<thead>
<tr>
<th>One</th>
<th>Two</th>
<th>Three</th>
<th>Four</th>
<th>Five</th>
<th>Six</th>
<th>Seven</th>
<th>Eight</th>
<th>nine</th>
<th>ten</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
</tr>
<tr class="schedule-header">
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>11</td>
</tr>
</tbody>
</table>
Here is the CSS:
.schedule-header {
background: #0062a1;
color: white;
border: none;
font-weight: bold;
}
Now I am getting all the styling I want except for the border: none; style.
Basically my plan is to use jquery to pop in this nested table when a dropdown arrow is clicked on the table row above, revealing relevant data.
Ok so I fixed the code and added the collapse to my css and it doesnt seem to be fixing it.
I wrote you a small function that will attach a display function to each sibling row that has a button, but I think you should do some more tutorials first, as you have many mistakes that just create more confusion.
Try doing some of the Tutorials on W3Schools to improve your CSS, HTML and eventually JQuery.
Good Luck ;)
<html>
<head>
<style>
.more_info {
background-color: #0062a1;
color: white;
font-weight: bold;
display:none;
}
table {
border-collapse: collapse;
}
button {
border-radius: 50%;
background-color: #0062a1;
color: white;
font-weight: bold;
}
</style>
<script src="jquery-2.1.1.min.js"></script>
<script>
$(document).ready(function(){
$("button").click(function (){
var info_row = $(this).parent().parent().next();
info_row.toggle("slow");
});
});
</script>
</head>
<body>
<table>
<thead>
<tr>
<th></th>
<th>One</th>
<th>Two</th>
<th>Three</th>
</tr>
</thead>
<tbody>
<tr id="1">
<td><button>i</button></td>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr class="more_info">
<td></td>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr id="2">
<td><button>i</button></td>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr class="more_info">
<td></td>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
</tbody>
</table>
</body>
</html>
Add border-collapse: collapse; to the CSS of your table:
table {
border-collapse: collapse;
}
JSFiddle
I'd like to right align the text of last two columns of a table.
<table>
<tr>
<th>H 1</th>
<th>H 2</th>
<th>H 3</th>
<th>H 4</th>
</tr>
<tr>
<td rowspan='3'>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
</table>
There is not the same number of columns in each row and I'm not sure how to use css:nth-child to select the last two td items in each row.
http://jsfiddle.net/BB9ty/
th:last-child,
td:last-child,
th:nth-last-child(2),
td:nth-last-child(2) {
text-align: right;
}