There is a grid of 9 elements, their colors are like this:
Blue, Gray, Green
Green, Blue, Gray
Gray, Green, Blue
and then it repeats Blue, Gray, Green - how can I use nth of child to create this kind of pattern?
This is the rough and dirty way to accomplish this, using vanilla CSS and :nth:child formulas. With :nth-child, you are essentially writing a math expression to determine the behavior of elements that meet xn + y. Since you know your starting size, it's fairly simple to declare each one:
.child:nth-child(9n+1){
background: blue;
}
But you can view my snippet for a full demo.
.parent{
display: grid;
grid-template-columns: max-content max-content max-content;
gap: 10px;
}
.child{
width: 100px;
height: 100px;
}
.child:nth-child(9n+1){
background: blue;
}
.child:nth-child(9n+2){
background: gray;
}
.child:nth-child(9n+3){
background: green;
}
.child:nth-child(9n+4){
background: green;
}
.child:nth-child(9n+5){
background: blue;
}
.child:nth-child(9n+6){
background: gray;
}
.child:nth-child(9n+7){
background: gray;
}
.child:nth-child(9n+8){
background: green;
}
.child:nth-child(9n+9){
background: blue;
}
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
Edit: Here is a less redundant version, using shared properties:
.parent{
display: grid;
grid-template-columns: max-content max-content max-content;
gap: 10px;
}
.child{
width: 100px;
height: 100px;
}
.child:nth-child(9n+1), .child:nth-child(9n+5), .child:nth-child(9n+9){
background: blue;
}
.child:nth-child(9n+3), .child:nth-child(9n+4), .child:nth-child(9n+8){
background: green;
}
.child:nth-child(9n+2), .child:nth-child(9n+6), .child:nth-child(9n+7){
background: gray;
}
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
Related
This question already has answers here:
Make container shrink-to-fit child elements as they wrap
(4 answers)
Closed last year.
Is there a responsive way (not using min-width) to minimise a width of a parent when children do not take the entire space that parent has, given that the width of the children is hard set?
Problem
Solution
.parent {
display: flex;
flex-wrap: wrap;
border: 1px solid grey;
}
.child {
background: lightgrey;
height: 50px;
width: 40vw;
margin: 10px;
}
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
Try to add width: fit-content; to your .parent
UPD: try this approach (using grid system)
.parent {
display: grid;
border: 1px solid grey;
grid-template-columns: repeat(2, minmax(min-content, max-content));
width: fit-content;
}
.child {
background: lightgrey;
height: 50px;
width: 40vw;
margin: 10px;
}
<div class="parent">
<div class="child"></div>
<div class="child"></div>
</div>
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
<div class="parent">
<div class="child" style="width: 30vw"></div>
<div class="child" style="width: 33vw"></div>
<div class="child" style="width: 27vw"></div>
<div class="child" style="width: 35vw"></div>
</div>
This question already has answers here:
Make container shrink-to-fit child elements as they wrap
(4 answers)
CSS when inline-block elements line-break, parent wrapper does not fit new width
(2 answers)
Closed 2 years ago.
Either I'm missing something or this is just how flex works.
Given a wrapping flex container with a max-width as children wrap the parents width remains at the max-width even though by wrapping the children the width could be reduced.
This makes it impossible to align the container to the center of it's container.
Here's a codepen illustrating the issue:
https://codepen.io/rsouthgate/pen/PozPyXZ
.container {
display: inline-flex;
flex-wrap: wrap;
max-width: 300px;
}
So how can I get the container to not take up the space on the right after the wrap?
Here are some of the possibilities via justify-content, in order: center, space-around, space-between. These all just change how the excess looks. If you want to make the children themselves take up the remaining space, use flex-grow: 1 instead.
You can read up more on css tricks: https://css-tricks.com/snippets/css/a-guide-to-flexbox/
.outer {
display: flex;
flex-direction: column;
}
.container {
justify-content: center;
background: grey;
display: inline-flex;
margin: 0 auto 10px;
flex-wrap: wrap;
max-width: 300px;
}
.child {
width: 25px;
height: 25px;
background: white;
margin: 5px;
}
.container2 {
justify-content: space-around;
background: grey;
display: inline-flex;
margin: 0 auto 10px;
flex-wrap: wrap;
max-width: 300px;
}
.container3 {
justify-content: space-between;
background: grey;
display: inline-flex;
margin: 0 auto 10px;
flex-wrap: wrap;
max-width: 300px;
}
.container4 {
justify-content: space-between;
background: grey;
display: inline-flex;
margin: 0 auto 10px;
flex-wrap: wrap;
width: 300px;
}
.child-grow {
flex-basis: 25px;
flex-grow: 1;
height: 25px;
background: white;
margin: 5px;
}
center
<div class="outer">
<div class="container">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
<div class="container">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
</div>
Space around
<div class="outer">
<div class="container2">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
<div class="container2">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
</div>
Space between
<div class="outer">
<div class="container3">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
<div class="container3">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
</div>
Flex grow
<div class="outer">
<div class="container4">
<div class="child-grow"></div>
<div class="child-grow"></div>
<div class="child-grow"></div>
<div class="child-grow"></div>
<div class="child-grow"></div>
<div class="child-grow"></div>
<div class="child-grow"></div>
<div class="child-grow"></div>
</div>
<div class="container4">
<div class="child-grow"></div>
<div class="child-grow"></div>
<div class="child-grow"></div>
<div class="child-grow"></div>
<div class="child-grow"></div>
<div class="child-grow"></div>
<div class="child-grow"></div>
<div class="child-grow"></div>
<div class="child-grow"></div>
<div class="child-grow"></div>
<div class="child-grow"></div>
</div>
</div>
So I have the following html structure:
<div class="wrapper">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
...
</div>
The layout I'm trying to achieve is this:
Now I've figured out that I can achieve this effect on one row by using flexbox, with the following:
.wrapper {
display: flex;
align-items: flex-start;
flex-wrap: nowrap;
overflow-x: auto;
}
This works for 1 row and gives me the following:
I was then doing a bit of reading up on css grid, as it sounds like this is one of the reasons it was introduced ie. flexbox works for one dimension where as grid works for two, however I've been unable to wrap my head around it and I'm still not sure it's the correct route.
I'm wondering whether the way I should approach it is to build a grid with 1 column and 2 rows, and then list out the items within these columns.
The alternative would be to have 2 rows and X columns (1 for each item) but I believe this will remove the staggered effect as it'll hold to a grid layout.
Does anyone have any advice on how to achieve this layout?
Grid aligns all its rows together, so you lose that staggered effect of flexbox. The easiest solution is to have an outer grid or flexbox that houses two inner flexboxes:
.wrapper {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 1fr 1fr;
border: solid 2px gray;
overflow-y: scroll;
max-width: 400px;
}
.child {
height: 60px;
background-color: red;
margin: 4px;
}
.flex:first-child .child:nth-child(even) {
min-width: 50px;
}
.flex:first-child .child:nth-child(odd) {
min-width: 75px;
}
.flex:last-child .child:nth-child(even) {
min-width: 75px;
}
.flex:last-child .child:nth-child(odd) {
min-width: 65px;
}
.flex {
display: flex;
}
<div class="wrapper">
<div class="flex">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
<div class="flex">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
</div>
Edit: If the HTML can't be edited, but you have an outer container and an inner container (i.e. .wrapper and .flex in this instance) you can also achieve the desired effect by giving the inner container a min-width narrower than the min-width of the outer container, and setting flex-wrap: wrap:
.wrapper {
border: solid 2px gray;
overflow-y: scroll;
max-width: 400px;
}
.flex{
min-width:900px;
flex-wrap:wrap;
}
.child {
height: 60px;
background-color: red;
margin: 4px;
}
.child:nth-child(even) {
min-width: 50px;
}
.child:nth-child(n+3) {
min-width: 60px;
}
.child:nth-child(n+5) {
min-width: 40px;
}
.child:nth-child(odd) {
min-width: 75px;
}
.flex {
display: flex;
}
<div class="wrapper">
<div class="flex">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
</div>
I have a container that holds multiple divs, around 20. I want to put 3 divs on each line so it kind of looks something like this (with the divs just continuing to flow).
What's the best way to centre these columns without having them in some sort of parent div? I can center them if I used a div which held 3 columns each but with the system I'm using I cannot. Any ideas?
A simple example will be:
pure css you can use this one to control row:
.child:nth-child(3n+1) {
clear: both;
}
with width: calc((100% - 60px)/3); to get width dynamically.
.child {
background: white;
height: 40vh;
float: left;
margin: 0px 10px 10px 0px;
width: calc((100% - 60px)/3);
border: 5px solid black;
}
.child:nth-child(3n+1) {
clear: both;
}
.wrapper {
background: white;
border: 5px solid black;
display: inline-block;
width: calc(100% - 30px);
margin: 10px;
padding: 10px 0px 0px 10px;
}
<div class="wrapper">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
The 'best' way IMO is to use flexbox. You say with no parent div but it has to have some kind of parent container div.
* {
box-sizing: border-box;
}
.container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
max-width: 400px;
margin: 0 auto;
padding: 25px;
border: 2px solid black;
}
.box {
display: block;
height: 160px;
width: 100px;
margin-bottom: 25px;
border: 2px solid black;
}
<div class="container">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
I know when using display: flex you can use margin-left: auto on a child and that pushes it all the way to the right but if you do that with multiple children you end up with evenly distributed margins instead of them all sitting to the far left.
Assuming HTML is uneditable
I know you could create a class like so: http://jsfiddle.net/L943ckr5/
.flex {
display: flex;
}
.child {
height: 30px;
width: 50px;
background-color: red;
}
.child:nth-child(even) {
background-color: blue;
}
.end {
margin-left: auto;
}
<div class="flex">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child end"></div>
<div class="child"></div>
<div class="child"></div>
</div>
But is there a way to individually target the last 3 children and 'float' them right but with Flex obviously. Something along the lines of justify-self: flex-end;
In case of you're being OK with using jQuery to tackle this problem, I got solution to wrap every group of 3 child divs into a parent div, and spread them as a column.
This might get helpful if you don't know the exact number of child divs in your markup.
JSFiddle
HTML:
<div class="flex">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
CSS:
.flex {
display: flex;
justify-content:space-between;
}
.flex-container {
display:flex;
}
.child {
height: 30px;
width: 50px;
background-color: red;
}
.child:nth-child(even) {
background-color: blue;
}
jQuery:
var arr = $(".child"),
templ = '<div class="flex-container"></div>';
for(var i = 0; i < arr.length; i+=3) {
arr.slice(i, i+3).wrapAll(templ);
}
Do you mean like this:
.child:nth-last-child(3) {
margin-left: auto;
}
.flex {
display: flex;
}
.child {
height: 30px;
width: 50px;
background-color: red;
}
.child:nth-child(even) {
background-color: blue;
}
.child:nth-last-child(3) {
margin-left: auto;
}
<div class="flex">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
As far as I know there is no property to add to each of the elements that would achieve the same effect.