Why doesn't position: sticky work in Chrome? - css

How do you get position: sticky working?
I tried the following in Chrome 26.0.1410.43 m and it's not working:
thead {
position: -webkit-sticky;
position: -moz-sticky;
position: -ms-sticky;
position: -o-sticky;
position: sticky;
top: 10px;
}
http://jsfiddle.net/8LRms/
According to this, it should work:
http://updates.html5rocks.com/2012/08/Stick-your-landings-position-sticky-lands-in-WebKit
It seemed to be supported in Chrome 23.0.1247.0, but now it doesn't work in 26.0.1410.43 m.

For a short time, Chrome enabled this feature behind a flag, --enable-experimental-webkit-features, in their about:flags section. However, it was shortly removed due to inefficiencies in how the browser was repainting.
As of Chrome 56, this feature is enabled without a flag once again.
As of Chrome 52.0.2743.116, this feature is enabled by the flag --enable-experimental-webkit-features once more.
To answer the updated question about why it was removed: Google (Chromium) removed support for position: sticky due to the unfinished nature of the spec, and they will focus on other scrolling features in the mean-time:
"We would eventually like to implement position: sticky, but the current
implementation isn't designed in a way that integrates well with the existing
scrolling and compositing system. For example, position: sticky relies upon
updateLayerPositionsAfterDocumentScroll to function correctly, but that
function has no other purpose and can otherwise be removed. Similarly,
position: sticky doesn't work at all with composited overflow scrolling, which
is now the default mechanism for driving scrolling in the engine.
Once we've got our scrolling and compositing house in order, we should return
to position: sticky and implement the feature in a way that integrates well
with the rest of the engine. For now, however, this CL removes our current
implementation so we can focus on improving our implementation of the scrolling
features we've already shipped."
Emphasis mine. You can read more about it here.

EDIT: You need to launch with --enable-experimental-webkit-features flag enabled via about:flags.
Update: This does not work on Chrome v35 through v51, Chrome 52 reenables this with the experimental web platform features flag. Starting from Chrome 56 position: sticky works out of the box.

FilamentGroup released a nice polyfill for position: sticky. Have a look at: https://github.com/filamentgroup/fixed-sticky

It seems that it doesn't work on iOS7 Safari if there is a parent node with overflow: hidden property set.

When Chrome switched over to the Blink rendering engine with version 28, they dropped Webkit, which is the only engine to support this (on Mac and iOS.)
So unless you're using Safari on Mac or iOS, or Chrome on iOS (for now) you will not be able to support this in other browsers.
Sad, it's a great and easy way to float elements.

It does - now at least
Look up https://caniuse.com/#feat=css-sticky
You are targeting the <thead> while Chrome and the Blink engine(Chrome, Edge, Opera) does not support this. Gecko(Mozilla Firefox) and Webkit(Safari) does. Instead try to target the <th> instead as shown below.
Also overflow: hidden on a parent WILL break position:sticky
Be sure to include your vendor prefixes.
Run the snippet and it should show a functional sticky header.
thead > tr > th {
background: white;
position: -webkit-sticky;
position: -moz-sticky;
position: -ms-sticky;
position: -o-sticky;
position: sticky;
top: 10px;
}
<h1>Position sticky</h1>
<table>
<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>
<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>
<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>

The great news is that as of Chrome 56 (currently beta as of December 2016, stable in Jan 2017) position: sticky is now back in Chrome.
So, in the near future only Edge would be the only one of all browsers that hasn't implemented it still, except browsers for mobile devices, but I hope they would implement it also soon.

Related

CSS Selector Targeting

I'm trying to target a particular <th> within the table below and only that particular <th>
The <th> in question is the <th>Abilities</th> under located after the <th>Weapons</th>
There will be multiple of these in the larger dataset but being able to target in this smaller set of data would be ideal test.
I know :nth-child, :nth-of-type aren't able to help here due to their selector limitations, but is there a way to do so at all?
I'm very much a novice coder and this code is an output from an app with zero support from the developer anymore so highly unlikely the core coding design will ever change.
I also using an external stylesheet which I'd hope the code if there is any would sit in there.
<table cellspacing="-1">
<tr>
<th>Psyker</th>
<th>Cast</th>
<th>Deny</th>
<th>Powers Known</th>
<th>Other</th>
</tr>
<tr>
<td class="profile-name">Primaris Librarian</td>
<td>2</td>
<td>1</td>
<td>Smite, 2 Librarius</td>
<td>-</td>
</tr>
</table>
<table cellspacing="-1">
<tr>
<th>Unit</th>
<th>M</th>
<th>WS</th>
<th>BS</th>
<th>S</th>
<th>T</th>
<th>W</th>
<th>A</th>
<th>Ld</th>
<th>Save</th>
</tr>
<tr>
<td class="profile-name">Primaris Librarian</td>
<td>6"</td>
<td>3+</td>
<td>3+</td>
<td>4</td>
<td>4</td>
<td>5</td>
<td>4</td>
<td>9</td>
<td>3+</td>
</tr>
</table>
<table cellspacing="-1">
<tr>
<th>Weapon</th>
<th>Range</th>
<th>Type</th>
<th>S</th>
<th>AP</th>
<th>D</th>
<th>Abilities</th>
</tr>
<tr>
<td class="profile-name">Bolt pistol</td>
<td>12"</td>
<td>Pistol 1</td>
<td>4</td>
<td>0</td>
<td>1</td>
<td>-</td>
</tr>
<tr>
<td class="profile-name">Force sword</td>
<td>Melee</td>
<td>Melee</td>
<td>+1</td>
<td>-3</td>
<td>D3</td>
<td>-</td>
</tr>
<tr>
<td class="profile-name">Frag grenades</td>
<td>6"</td>
<td>Grenade D6</td>
<td>3</td>
<td>0</td>
<td>1</td>
<td>Blast.</td>
</tr>
<tr>
<td class="profile-name">Krak grenades</td>
<td>6"</td>
<td>Grenade 1</td>
<td>6</td>
<td>-1</td>
<td>D3</td>
<td>-</td>
</tr>
</table>
Easy to achieve in your example HTML, with the help of some pseudo selectors:
table:nth-of-type(3) tr:first-of-type :last-child { color: red; }
<table cellspacing="-1">
<tr>
<th>Psyker</th>
<th>Cast</th>
<th>Deny</th>
<th>Powers Known</th>
<th>Other</th>
</tr>
<tr>
<td class="profile-name">Primaris Librarian</td>
<td>2</td>
<td>1</td>
<td>Smite, 2 Librarius</td>
<td>-</td>
</tr>
</table>
<table cellspacing="-1">
<tr>
<th>Unit</th>
<th>M</th>
<th>WS</th>
<th>BS</th>
<th>S</th>
<th>T</th>
<th>W</th>
<th>A</th>
<th>Ld</th>
<th>Save</th>
</tr>
<tr>
<td class="profile-name">Primaris Librarian</td>
<td>6"</td>
<td>3+</td>
<td>3+</td>
<td>4</td>
<td>4</td>
<td>5</td>
<td>4</td>
<td>9</td>
<td>3+</td>
</tr>
</table>
<table cellspacing="-1">
<tr>
<th>Weapon</th>
<th>Range</th>
<th>Type</th>
<th>S</th>
<th>AP</th>
<th>D</th>
<th>Abilities</th>
</tr>
<tr>
<td class="profile-name">Bolt pistol</td>
<td>12"</td>
<td>Pistol 1</td>
<td>4</td>
<td>0</td>
<td>1</td>
<td>-</td>
</tr>
<tr>
<td class="profile-name">Force sword</td>
<td>Melee</td>
<td>Melee</td>
<td>+1</td>
<td>-3</td>
<td>D3</td>
<td>-</td>
</tr>
<tr>
<td class="profile-name">Frag grenades</td>
<td>6"</td>
<td>Grenade D6</td>
<td>3</td>
<td>0</td>
<td>1</td>
<td>Blast.</td>
</tr>
<tr>
<td class="profile-name">Krak grenades</td>
<td>6"</td>
<td>Grenade 1</td>
<td>6</td>
<td>-1</td>
<td>D3</td>
<td>-</td>
</tr>
</table>
If, due to the dynamic nature of the HTML, using pseudo selectors won't work for you, there sadly is no other way of achieving this other than adding a class, or resorting to JS:
[...document.querySelectorAll('th')].find(th => th.textContent === 'Abilities').style.color = 'red';
<table cellspacing="-1">
<tr>
<th>Psyker</th>
<th>Cast</th>
<th>Deny</th>
<th>Powers Known</th>
<th>Other</th>
</tr>
<tr>
<td class="profile-name">Primaris Librarian</td>
<td>2</td>
<td>1</td>
<td>Smite, 2 Librarius</td>
<td>-</td>
</tr>
</table>
<table cellspacing="-1">
<tr>
<th>Unit</th>
<th>M</th>
<th>WS</th>
<th>BS</th>
<th>S</th>
<th>T</th>
<th>W</th>
<th>A</th>
<th>Ld</th>
<th>Save</th>
</tr>
<tr>
<td class="profile-name">Primaris Librarian</td>
<td>6"</td>
<td>3+</td>
<td>3+</td>
<td>4</td>
<td>4</td>
<td>5</td>
<td>4</td>
<td>9</td>
<td>3+</td>
</tr>
</table>
<table cellspacing="-1">
<tr>
<th>Weapon</th>
<th>Range</th>
<th>Type</th>
<th>S</th>
<th>AP</th>
<th>D</th>
<th>Abilities</th>
</tr>
<tr>
<td class="profile-name">Bolt pistol</td>
<td>12"</td>
<td>Pistol 1</td>
<td>4</td>
<td>0</td>
<td>1</td>
<td>-</td>
</tr>
<tr>
<td class="profile-name">Force sword</td>
<td>Melee</td>
<td>Melee</td>
<td>+1</td>
<td>-3</td>
<td>D3</td>
<td>-</td>
</tr>
<tr>
<td class="profile-name">Frag grenades</td>
<td>6"</td>
<td>Grenade D6</td>
<td>3</td>
<td>0</td>
<td>1</td>
<td>Blast.</td>
</tr>
<tr>
<td class="profile-name">Krak grenades</td>
<td>6"</td>
<td>Grenade 1</td>
<td>6</td>
<td>-1</td>
<td>D3</td>
<td>-</td>
</tr>
</table>
If you're able to add html to the existing table structure the easiest thing to do would be to put a class on the <th> that your trying to target. <th class="abilities">Abilities</th>
With the class added you can then apply styles to that class and they will apply only to any element in the table that you have assigned that class name to.
Then adding this class with the styles you want to your css sheet should do the trick.
.abilities {
custom css styles here!
}
EDIT
Because you cant add styles directly to the existing HTML structure you could use Javascript or jQuery to crawl the page contents and find the word "Abilities" the code for that might look something like this
jQuery('th:contains("Abilities")').addClass('customClassName');
There might be some playing around needed to get it functioning exactly the way you want but this could be an option
the :has() Selector might also be usefull

Use CSS to hide some columns in a gridview

I have gridview (asp.NET) that populates automatically, and I use CSS to format it as a table. I need to set display:none for about the first six rows. I can do that with javascript, but is there an elegant way to do it with CSS? I tried:
#myTable td:eq(0)
which give me an error, and:
#myTable tr:nth-child(0) {display:none}
which doesn't error, but also doesn't work. If these worked, I could hide my columns one by one, but I have about seven or eight columns to hide. So I guess I have two questions, first, can I hide some columns but not others, and second, can I hide a range?
UPDATE, based Miak's answer. Here's the complete working solution:
#gvLoadStatus th:nth-child(-n+9) {
display: none;
}
#gvLoadStatus td:nth-child(-n+9) {
display: none;
}
To hide the first 6 rows you can use this: tr:nth-child(-n+6)
tr:nth-child(-n+6) {
display: none;
}
<table>
<tr>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td>2</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td>2</td>
</tr>
<tr>
<td>4</td>
<td>2</td>
</tr>
<tr>
<td>5</td>
<td>2</td>
</tr>
<tr>
<td>6</td>
<td>2</td>
</tr>
<tr>
<td>7</td>
<td>2</td>
</tr>
<tr>
<td>8</td>
<td>2</td>
</tr>
</table>

page-break not working in html-pdf coverter in nodejs

I am using html-pdf 2.2.0 module to convert my html in pdf. I am using table with multiple rows so I want to use page-break so then a single row does not divide in two pages but its not working when converting it to pdf.
Below is the code sample
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<style>
table tbody tr {
height: 120px;
border:5px solid red;
}
</style>
<body>
<table border="1" style="page-break-after: always;">
<thead>
<tr>
<td>AA</td>
<td>BB</td>
<td>CC</td>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
</tbody>
</table>
</body>
</html>
When printing the code (CTRL + P) with simple HTML it looks fine but when converting it to the pdf it doesn't work.
It is really hard to find the good package or API that can convert things to PDF while keeping all the layout. I spent a lot of time investigating and tried a lot of different solutions (directly convert HTML to PDF, converting to DOCX and then from DOCX to PDF...). I would suggest you to check online converting tools (most of them are free and you can use them really quickly, you just need to upload the file and they will give you a PDF back to download). If you only need to convert this one html file that is the best way to go (because one of the tools will probably convert it in the right way). If you need it as a feature, then you can ask the provider of convertor that worked for you for an API access.
Usually when you convert PDF to HTML, it works fine, but when you try to convert it back (even the same HTML) it will not look the same as original. From my experience, the best mapping is between PDF and DOCX files. So maybe you can consider to convert you HTML to DOCX first, and then convert DOCX to PDF. There are npm packages that can do both so you can check them (or consider checking online converting tools agian).
I would recommend to use tr, td { page-break-inside: avoid; } to prevent breaks inside rows and cells.
I would recommed below css to fix this
<style type="text/css">
table { page-break-inside:auto }
tr { page-break-inside:avoid; page-break-after:auto }
thead { display:table-header-group }
tfoot { display:tenter code hereable-footer-group }
</style>
Unfortunately, this occurs using some libs to convert html to pdf in node, it is even treated as a reported bug and so far it doesn't seem to have a solution, however, there is a way around the problem.
If instead of creating several columns and rows, create them all as a table and apply this to CSS:
table, tr, td { page-break-inside: avoid; }
will solve the problem.
Example how create table to solve the problem in HTML:
<table>
<tr>
<th>AA</th>
<th>BB</th>
<th>CC</th>
</tr>
</table>
<table>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
</table>
<table>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
</table>
<table>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
</table>
...
This was the only way I was able to solve the problem in node of the pdf libs

I cannot understand how the selector works?

I do not understand how to use the two pseudo-classes. I want to change the black background to the row with cells 3,3,3.
tbody tr:not(:empty):first-of-type td {
background: black;
}
<table>
<tr>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>2</td>
<td>2</td>
<td>2</td>
<td>2</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td>3</td>
<td>3</td>
<td>3</td>
<td>3</td>
</tr>
<tr>
</tr>
</table>
Why is background not applicable?
Cells "3" are in the second to last row. To select that second to last row, you should use :nth-last-child() as in:
edit2: <nope tbody is created as an anonymous element by browsers so you can selecttbody somethingwithout any tbody in a table> As stated by #Esko in a comment to your question, you don't have a tbody element in your HTML code. You should then remove it from the selector. tr can only be found in a table so it's unnecessary to add table to the left of your selector (but you can).</nope>
Note 1: none of your tr is/are empty: they contain whitespace and thus are non-empty.
<tr></tr> and <tr><!-- some comment --></tr>: both empty
<tr> </tr>: NOT empty
Note 2: :first-of-type would, in your code select the very first tr, which is the one with no td inside (if it had td children, it'd still be the first of its type)
tr:nth-last-child(2) td {
background:black;
}
<table>
<tr>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>2</td>
<td>2</td>
<td>2</td>
<td>2</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td>3</td>
<td>3</td>
<td>3</td>
<td>3</td>
</tr>
<tr>
</tr>
</table>

Position: sticky (firefox) on a <table> element

The new value of position is very confusing to me.. a lot of search result give javascript/jQuery (JavaScript-framework) solutions.
In the example in bottom i have a table with a thead and tbody.
No matter what i cannot achieve the desire result.
Desire result is thead to be sticky to the table. sticky means when not in view the element is some kind of position:fixed fixed means it sticks to your screen. What i did try:
display: inline/block/inline-block;
th element position:sticky (th element is an element inside a tr witch is inside a thead element)
mix of display:inline/block etc; (values of property display)
I just cannot find how to achieve this sticky in firefox (supported)
Any solutions ??
(as position:sticky still an experimental API and should not be used in production site http://developer.mozilla.org/en/docs/Web/CSS/position )
table {
background-color: rgba(241, 31, 0, 0.3);
width: 100%;
}
thead {
background-color: rgba(241, 0, 241, 0.3);
position: -webkit-sticky;
position: sticky;
}
th {} tbody td:nth-child(2) {
height: 200px;
}
<table>
<thead>
<tr>
<th>1</th>
<th>2</th>
<th>3</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
</tbody>
</table>
Firefox seems not to allow yet 'sticky' on table childs elements.
a workaround would be to set table as block, then thead, tbody, tfoot to display:table; so one of them can be sticked.
unfortunately this breaks the table-layout and split table into few tables .. :(
you also need to set coordonates where sticky comes in action http://codepen.io/gc-nomade/pen/reoExq . not the best :(
CSS base would be like:
table {
display: block;
}
thead {
position: sticky;
top: 0px; /* trigger sticky when reaches coordonates */
}
thead, tbody, tfoot {
display: table;
width: 100%;
}
table {
background-color: rgba(241, 31, 0, 0.3);
width: 100%;
margin-top: 1em;
position: static;
display: block;
}
thead {
display: table;
width: 100%;
background-color: rgba(241, 0, 241, 0.3);
position: sticky;
top: 0px;
/* trigger sticky when reaches coordonates */
}
tbody {
display: table;
width: 100%;
}
th {} tbody td:nth-child(2) {
height: 200px;
}
<table>
<thead>
<tr>
<th>1</th>
<th>2</th>
<th>3</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<th>1</th>
<th>2</th>
<th>3</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<th>1</th>
<th>2</th>
<th>3</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<th>1</th>
<th>2</th>
<th>3</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
</tbody>
</table>
Another method is to use css3 to translate the header cells. This method does require javascript and will work in all modern browsers, but because it translates the table cell, the border does not get included for some reason (demo)
Also, this css is necessary to include a background color on the translated cells
thead th,
caption {
background: #fff;
}
jQuery
var $win = $(window),
$table = $('table'),
$thead = $table.children('thead'),
$tfoot = $table.children('tfoot'),
$caption = $table.children('caption'),
$cells = $thead.children().children().add($caption);
$win.on('scroll', function() {
var bottom = $table.position().top +
$table.height() -
$thead.height() -
($tfoot.height() || 0),
delta = $win.scrollTop() -
$thead.offset().top +
$caption.outerHeight(),
// include border thickness (minus 2)
vertPos = (delta < 0 || delta > bottom ? 0 : delta - 2);
$cells.css("transform", "translate(0px," + vertPos + "px)");
});
Update Q1 2018
position: sticky has now landed in stable Firefox 59. The fiddle linked below now works unchanged in Firefox as well.
I know you specifically asked for Firefox compatibility of position: sticky, but unfortunately its styling effect in Firefox is not defined on inner table elements:
Quoting from https://developer.mozilla.org/en/docs/Web/CSS/position
The effect of position:relative on table-*-group, table-row, table-column, table-cell, and table-caption elements is undefined.
The effect of ‘position: sticky’ on table elements is the same as for ‘position: relative’.
That being said, position: sticky is about to land in Chrome Stable channel (it is in Canary at the time of writing and there's a developer.google.com blog post about it). Their implementation does work fine on thead, solving my own long-standing problem of sticky theads as all other solutions fail when you need to resize the table/cell widths.
I've created a fiddle to test the sticky positioning. On all channels of Firefox, this has no effect.
My hope is that position: sticky now gains tractions due to the more complete implementation in Chrome, it will stir discussions again on the lacking inner table support of sticky.
There's also a bug report on Firefox' Bugzilla:
https://bugzilla.mozilla.org/show_bug.cgi?id=975644

Resources