I have a list made of thousands of items.
In order to display them in a clean fashion, I need to apply a specific css rule to every third item of the list (3th li, 6th li, 9th li,....,3000th li..9999th li...).
Normally, I would use this:
li:nth-child(3),li:nth-child(6),...
but this would obviously be too tedious to write a css rule for each item (not to mention that the list may grow over time)
I also may use a class for every third item of the list but the list is reordered constantly according to a filter by a jQuery plugin (Quicksand), so the 6th li can asynchronously become the 4th one according to the user manipulation.
So, is there a way to use a css rule that would simply do something like this?:
li:nth-child(n*3)
Thank you.
You could use the :nth-child(an+b) pseudo class as li:nth-child(3n+3) in order to select every third list item (a parameter) starting from 3rd <li> element (b parameter).
In which:
n starts from 0
n = 0: (3 * 0 + 3) = 3 => 3rd element
n = 1: (3 * 1 + 3) = 6 => 6th element
n = 2: (3 * 2 + 3) = 9 => 9th element
...
li:nth-child(3n+3) {
background-color: gold;
}
Example Here. (Which is the same as li:nth-child(3n)).
From the MDN:
The :nth-child(an+b) CSS pseudo-class matches an element that has
an+b-1 siblings before it in the document tree, for a given positive
or zero value for n, and has a parent element.
It's worth noting that :nth-child pseudo-class is supported in IE9+.
Related
In Cypress, I'm trying to count how many elements (in this case how many buttons in li) contain text. When using "contains", the number of returned items is always equal to one because "contains" only gives the first item in the document containing the search text.
cy.get('li')
.contains('button', 'Submit')
.its('length')
.then(elLength => {
// I want to test here the number of all buttons in li elements containig word 'Submit'
}
Of course, this doesn't work that way, because elLength is always 1 (or 0 if no items found).
Is there any other method in Cypress that can return all elements with text, and I can count them?
Cypress get() uses the same selectors as jQuery. You can therefor use :contains to get all elements containing a text.
As Cypress contains() only includes visible DOM elements, you have to add :visible to get the same kind of behaviour.
To make sure only one visible button contains "Submit":
cy.get('button:visible:contains("Submit")').should('have.length', 1);
To make sure only one visible button inside a "li" element contains the text "Submit":
cy.get('li button:visible:contains("Submit")').should('have.length', 1);
To count the "li" elements that contain one or more visible "Submit" buttons:
cy.get('li:has(button:visible:contains("Submit"))').should('have.length', 1);
If you know the right amount of buttons that need to have that label, you could try:
cy.get('li').then($el => {
cy.wrap($el).find(".button").then($els => {
expect($els.filter(index => $els.eq(index).is(':contains(Submit)'))).to.have.length(your_amount);
})
In my React website I'd like to change the line-height property of a word I have that changes length (based on some other logic). What I'm doing is that every letter of the word is on a separate line:
.myWord {
line-height: 3.9;
word-break: break-all;
}
outputs:
m
y
w
o
r
d
But I also need it to line up with another element next to it, so that it would always be equally tall. The current line-height is only fitting for a word that is 6 letters long.
I found a similar question on stackoverflow with a jQuery answer:
var cnt = $(".tweeter_widget").text().length;
if (cnt > 10) {
$(".tweeter_widget").css("line-height", "5px");
}
If someone could translate that into JSX or provide a different answer, I would highly appreciate.
The logic would basically be:
If the word is 6 letters long, line-height will be 3.9
If the word is 5 letters long, line-height will be 4.2
...
I only need it for 3-6 letter words so it's no problem to write them all out.
Given that I am not totally sure to have understood your question but...
Let's say that we have a MyWord component, in relation to the length of the text given, we need to apply to the element a certain amount of line-height property.
I would first of all have a map of the length-lineHeight matches, something like this:
// the key is the text length, the value is the applicable line-height
const HEIGHTS = {
5: 4.2,
6: 3.9
}
If it useful, we could keep a default, just in case we missed something
const DEFAULT_HEIGHT = 1
Then, we need a simple MyWord component that only takes a text prop. We assign an inline style property value upon the text prop length:
const MyWord = ({ text }) => (
<div
className="myWord"
style={{
lineHeight: HEIGHTS[text.length] || DEFAULT_HEIGHT
}}
>
{ text }
</div>
)
This is just an idea of mine, whether I got the question at all... I made a sample Pen... https://codepen.io/ciamiz/pen/VEXNQo
For example, there are total 12 elements.
I want to apply my style only on last n (1, 2, 3...) numbers of child of total 12 elements; how can I do this?
I think what you are looking for is the css pseudo-class :nth-last-child (see MDN)
Just use a negative n value and add the index from the end (represents number of elements)
.parentClass > * :nth-last-child ( -n + 3 ) {
/* CSS here for last 3 elements */
}
https://jsfiddle.net/evm0mg8j/
I'm trying to make this:
I have an array like this:
#levels:'level_one','level_two','level_three','level_four','level_five','level_six','level_seven','level_eight';
Each of those levels also has a corresponding variable which is a colour, and match a class in the list markup of the level indicator.
I'm able to loop through these easily enough to generate out the background colours for each level.
I want to be able to have the heights automatically set for each item, so theoretically if I wanted to add a 9th or 10th level to the indicator, I just add the colour variable, add it to the array and add the relevant markup, without having to explicitly set the height on each class.
.for(#levels); .-each(#color) {
#name: e(#color);
&.#{name} {
background:##name;
}
}
I'm looping through the levels like the above, but it is somehow possible to get the current index of the loop as well as the count of the #levels array to work out a percentage based height for each item? Eg. if there's 10 items, the first item is 10% in height etc etc.?
Looking forward to any suggestions!
Thanks!
Assuming you're using for.less snippet: There's additional #i variable available in the .-each scope (the variable is implicitly inherited from .-each's caller).
So you can write this as (with unnecessary quotes removed):
#levels:
level_one,
level_two,
level_three,
level_four,
level_five,
level_six,
level_seven,
level_eight;
.for(#levels); .-each(#name) {
&.#{name} {
background: ##name;
height: (100% * #i / length(#levels));
}
}
- - -
In Modern Less you'll achieve the same using the Lists plugin where the .for-each statement has explicitly specified index variable:
#levels:
level_one,
level_two,
level_three,
level_four,
level_five,
level_six,
level_seven,
level_eight;
.for-each(#name, #i in #levels) {
&.#{name} {
background: ##name;
height: #i * 100% / length(#levels);
}
}
I know you can select the last child with :last-child or a certain child with :nth-child (if you know their position/number).
What I need is to select the last 3 children without knowing how many child elements there could be.
I know there is something that's called :nth-last-child but I cant really understand how it is working.
For this:
<div id="something">
<a href="images/x.jpg" ><a/>
<a href="images/x.jpg" ><a/>
<!-- More elements here -->
<!-- ..... -->
<!-- I need to select these: -->
<a href="images/x.jpg" ><a/>
<a href="images/x.jpg" ><a/>
<a href="images/x.jpg" ><a/>
</div>
I need something like this:
#something a:last-child{
/* only now it selects the last <a> and the 2 <a>'s that come before*/
}
You can read more here about nth-last child, but this should basically do the trick of selecting the last 3 children with just CSS
#something a:nth-last-child(-n+3) {
/*declarations*/
}
fiddle demonstration from FabrÃcio Matté
This will only select those rows returning a positive number for out N expression (-n+3), and since we are using nth-last-child, it's counting from last to first,
so first rows from bottom gives,
f(n) = -n+3
f(1) = -1+3 = 2 <- first row from the bottom
f(2) = -2+3 = 1 <- second row from the bottom
f(3) = -3+3 = 0 <- third row from the bottom
everything else will return a negative number
This is possible with CSS3 selectors and formulas:
.something a:nth-last-child(-n+3) { ... }
You could also try using jQuery (example) or adding a specific class to the last three elements in your server-side code (it does not require JavaScript to be enabled in browsers and also works on older browsers that do not support CSS3).
The accepted answer has the correct formula, but the explanation is wrong.
So the correct CSS is (same as currently accepted answer):
#something a:nth-last-child(-n+3) {
/*declarations*/
}
But here is the correct explanation of the math:
f(n) = -n+3
f(0) = -0+3 = 3 <- 3rd row from the bottom
f(1) = -1+3 = 2 <- 2nd row from the bottom
f(2) = -2+3 = 1 <- 1st row from the bottom
f(3) = -3+3 = 0 <- nothing
f(3) = -4+3 = -1 <- nothing
etc...