Reputation: 23
.Hi Folks Im trying to set Javascript function to align (stretch) last child in FlexBox.
To show max three columns in row i have on . article-card-container is set flex: 1 1 calc(100 * (1/3));
.
To stretch last item I need set on it flex: 1;
<div id="content-container">
<article class="article-card-container"></article>
<article class="article-card-container"></article>
<article class="article-card-container"></article>
<article class="article-card-container"></article>
</div>
Here is my solution that is working BUT ...
window.onload = function alignLeftovers() {
// get container with flexboxes
var container = document.getElementById("content-container");
// get container children
var childernCount = container.children.length;
// get leftover children
var leftover = container.children.length % 3;
if (childernCount > 3 && leftover === 1 ) { // condition
// start loop
for (var i = 0; i < container.children.length; i++) {
// remove class on last child
container.lastElementChild.classList.remove('article-card-container');
}
// add a new class on last child
container.lastElementChild.classList.add('article-card-container-100');
}
};
Im using leftover === 1
for test because there are even 2 items leftover and leftover > 0
cause problems.
Problem of this function is that I had to write new class to be assigned (included all subclasses for inside elements = lots of code).
First condition in if
statement is used because modulus
was returning 1 even there were only two elements.
Is there better solution (Im new to JS) in pure JavaScript how to on last child class .article-card-container
selector get to "flex" property and change (remove & add) its value and avoid to write brand new class?
Thanks for any suggestions or hints to make it better
Upvotes: 0
Views: 7821
Reputation: 87191
This can be solved with CSS only, and will be much more efficient than using script.
It is done by combining the nth-child
/nth-last-child
and last-child
selector, and will work on any number of items, with start from 1 item.
It work like that, when both the nth-*
and last-child
selector will match an element at the same time, the rule kicks in.
E.g., the :nth-child(3n+1):last-child
rule will target every 3rd element, starting from the 1st, then 4th, 7th and so on, if it also is the last, and with this, select any single element on the last row.
The :nth-child(3n+1):nth-last-child(2)
will do the same, though select it if it is the 2nd element, meaning there is 2 on the last row.
The final sibling selector +
will target the immediate sibling if there were 2, which always also will be the last.
Stack snippet
.content-container {
display: flex;
flex-wrap: wrap;
}
.article-card-container {
width: 33.3333%;
padding: 9px;
background: red;
border: 2px solid #fff;
box-sizing: border-box;
}
/* if every 3rd, start from 1st, also being 2nd last + last */
.article-card-container:nth-child(3n+1):nth-last-child(2),
.article-card-container:nth-child(3n+1):nth-last-child(2) + article {
width: 50%;
}
/* if every 3rd, start from 1st, also being last */
.article-card-container:nth-child(3n+1):last-child {
width: 100%;
}
/* for demo styling */
.content-container + .content-container {
margin-top: 20px;
}
<div class="content-container">
<article class="article-card-container"></article>
<article class="article-card-container"></article>
<article class="article-card-container"></article>
<article class="article-card-container"></article>
</div>
<div class="content-container">
<article class="article-card-container"></article>
<article class="article-card-container"></article>
<article class="article-card-container"></article>
<article class="article-card-container"></article>
<article class="article-card-container"></article>
</div>
<div class="content-container">
<article class="article-card-container"></article>
<article class="article-card-container"></article>
<article class="article-card-container"></article>
<article class="article-card-container"></article>
<article class="article-card-container"></article>
<article class="article-card-container"></article>
</div>
Upvotes: 1
Reputation: 16855
You have to set the flex
of lastElementChild
and lastElementChild.previousElementSibling
to 1
if leftover===2
window.onload = function alignLeftovers() {
var container = document.getElementById("content-container");
var childernCount = container.children.length;
console.log(childernCount);
var leftover = container.children.length % 3;
if (childernCount > 3 && leftover === 1) {
container.lastElementChild.style.flex = "1"
} else if (childernCount > 3 && leftover === 2) {
container.lastElementChild.style.flex = "1"
container.lastElementChild.previousElementSibling.style.flex = "1"
}
};
#content-container {
display: flex;
flex-wrap: wrap;
}
.article-card-container {
width: 33.3333%;
padding: 9px;
background: red;
border: 2px solid #fff;
box-sizing: border-box;
}
<div id="content-container">
<article class="article-card-container"></article>
<article class="article-card-container"></article>
<article class="article-card-container"></article>
<article class="article-card-container"></article>
<article class="article-card-container"></article>
</div>
Upvotes: 3