Bug 74200
Summary: | nth-child:nth-last-child combination failing unexpectedly. | ||
---|---|---|---|
Product: | WebKit | Reporter: | Chris Kalafarski <chris> |
Component: | CSS | Assignee: | Nobody <webkit-unassigned> |
Status: | RESOLVED WORKSFORME | ||
Severity: | Normal | CC: | bfulgham, shanestephens |
Priority: | P2 | ||
Version: | 528+ (Nightly build) | ||
Hardware: | Mac (Intel) | ||
OS: | OS X 10.6 |
Chris Kalafarski
Overview
When using a combination of nth-child() and nth-last-child(), the browser is failing to select certain DOM elements that match provided selectors, while others are correctly being matched and styled.
Steps to Reproduce
1) Create a <ul> element, and fill it with a number of <li> elements
2) Style the list such that the <li> elements float and form a grid or rows and columns
3) Use selectors to build rules that match only the last "row" of the grid
Actual Results
Only some of the elements in the last "row" are matched
Expected Results
All elements in the last "row" are matched
Build
This bug is presenting itself in the Spotify app, which is reporting as: "5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.8 (KHTML, like Gecko) Chrome/17.0.944.0 Safari/535.8"
I have not yet confirmed it in any other browser or application.
Additional Information
My experience with this bug is as follows:
We have build a grid of equally sized rectangles (as <li> elements), that are in a <ul> elements, and set to float:left to build the grid of equally sized rows and columns. The grid is limited to a minimum and maximum width (and, thus, number of columns, which varies the number of rows). In order to apply some specific styles to the <li> elements that appear in the last row of the grid, I have set up the following styles:
body[data-columns='9'] .playlist li.song:nth-child(9n):nth-last-child(1) { background: red; }
body[data-columns='9'] .playlist li.song:nth-child(8n):nth-last-child(2) { background: red; }
body[data-columns='9'] .playlist li.song:nth-child(7n):nth-last-child(3) { background: red; }
body[data-columns='9'] .playlist li.song:nth-child(6n):nth-last-child(4) { background: red; }
body[data-columns='9'] .playlist li.song:nth-child(5n):nth-last-child(5) { background: red; }
body[data-columns='9'] .playlist li.song:nth-child(4n):nth-last-child(6) { background: red; }
body[data-columns='9'] .playlist li.song:nth-child(3n):nth-last-child(7) { background: red; }
body[data-columns='9'] .playlist li.song:nth-child(2n):nth-last-child(8) { background: red; }
body[data-columns='9'] .playlist li.song:nth-child(1n):nth-last-child(9) { background: red; }
The logic here being that the combination of nth-child and nth-last-child will select only those elements in the last row. nth-last-child alone is not enough, even when the data-columns value is known, since when there is an incomplete row at the end of the list, it would start selecting items in the second-to-last row (eg, if there is only a single item in the last row, nth-last-child(2) will select the last item in the second to last row). By adding the nth-child to, essentially, match which column the element is in, the selector is limited to only those items in the last row (I realize this sample code only works when the last row is a complete row, but that is irrelevant to the bug).
The bug presents itself such that, with this code, if there is a complete final row, certain elements are inexplicably not matched. For example, the last element is red, as per the first selector (9th column, last child of the list), the 8th element in the row is also red, the 7the element in the row is NOT red, but the 6th element is. There are no additional elements in the DOM between surrounding the 7th element, so based on the math, there's no reason I can see that it wouldn't match. Given that 6n matches the preceding element, 7n should match the incorrectly styled element. Likewise, given that last-child(2) matches the proceeding element, last-child(3) should match the element in question. For some reason that's not the case; I have't been able to determine why, and it seems like, at least with my styles, it's always the same elements that get skipped (7/3, 5/5 are two I've noticed)
Attachments | ||
---|---|---|
Add attachment proposed patch, testcase, etc. |
Shane Stephens
Could you provide a reduction of the problem, preferably as an uploaded attachment?
Brent Fulgham
We do not see issues with nth-child or nth-last-child in Safari 15. Could you please REOPEN this bug and provide a test case illustration the problem if you still believe there is an issue.
Chris Kalafarski
I suspect this was never an issue, and was just bad math on my part. It's been 11 years, so I don't exactly remember what I was trying to do, but vaguely remember what the intent was, and I think the actual solution would look like this:
li:nth-child(9n-0):nth-last-child(1) { background: red; }
li:nth-child(9n-1):nth-last-child(2) { background: red; }
li:nth-child(9n-2):nth-last-child(3) { background: red; }
li:nth-child(9n-3):nth-last-child(4) { background: red; }
li:nth-child(9n-4):nth-last-child(5) { background: red; }
li:nth-child(9n-5):nth-last-child(6) { background: red; }
li:nth-child(9n-6):nth-last-child(7) { background: red; }
li:nth-child(9n-7):nth-last-child(8) { background: red; }
li:nth-child(9n-8):nth-last-child(9) { background: red; }
li:nth-child(9n-1):nth-last-child(1) { background: red; }
li:nth-child(9n-2):nth-last-child(2) { background: red; }
li:nth-child(9n-3):nth-last-child(3) { background: red; }
li:nth-child(9n-4):nth-last-child(4) { background: red; }
li:nth-child(9n-5):nth-last-child(5) { background: red; }
li:nth-child(9n-6):nth-last-child(6) { background: red; }
li:nth-child(9n-7):nth-last-child(7) { background: red; }
li:nth-child(9n-8):nth-last-child(8) { background: red; }
li:nth-child(9n-2):nth-last-child(1) { background: red; }
li:nth-child(9n-3):nth-last-child(2) { background: red; }
li:nth-child(9n-4):nth-last-child(3) { background: red; }
li:nth-child(9n-5):nth-last-child(4) { background: red; }
li:nth-child(9n-6):nth-last-child(5) { background: red; }
li:nth-child(9n-7):nth-last-child(6) { background: red; }
li:nth-child(9n-8):nth-last-child(7) { background: red; }
li:nth-child(9n-3):nth-last-child(1) { background: red; }
li:nth-child(9n-4):nth-last-child(2) { background: red; }
li:nth-child(9n-5):nth-last-child(3) { background: red; }
li:nth-child(9n-6):nth-last-child(4) { background: red; }
li:nth-child(9n-7):nth-last-child(5) { background: red; }
li:nth-child(9n-8):nth-last-child(6) { background: red; }
li:nth-child(9n-4):nth-last-child(1) { background: red; }
li:nth-child(9n-5):nth-last-child(2) { background: red; }
li:nth-child(9n-6):nth-last-child(3) { background: red; }
li:nth-child(9n-7):nth-last-child(4) { background: red; }
li:nth-child(9n-8):nth-last-child(5) { background: red; }
li:nth-child(9n-5):nth-last-child(1) { background: red; }
li:nth-child(9n-6):nth-last-child(2) { background: red; }
li:nth-child(9n-7):nth-last-child(3) { background: red; }
li:nth-child(9n-8):nth-last-child(4) { background: red; }
li:nth-child(9n-6):nth-last-child(1) { background: red; }
li:nth-child(9n-7):nth-last-child(2) { background: red; }
li:nth-child(9n-8):nth-last-child(3) { background: red; }
li:nth-child(9n-7):nth-last-child(1) { background: red; }
li:nth-child(9n-8):nth-last-child(2) { background: red; }
li:nth-child(9n-8):nth-last-child(1) { background: red; }
Which works as expected (for a grid with 9 columns with an arbitrary number of rows, makes elements in the last row red).
Brent Fulgham
(In reply to Chris Kalafarski from comment #3)
> I suspect this was never an issue, and was just bad math on my part. It's
> been 11 years, so I don't exactly remember what I was trying to do, but
> vaguely remember what the intent was, and I think the actual solution would
> look like this:
>
Thank you for updating the bug. I apologize for no one reviewing it for so long. My team is working on finding and addressing these orphans!