Make flexbox children wrap around a child that is multiple rows tall - html

I am iterating over a list of items(red boxes). I have another element not part of this list that I want to insert into the items' grid in the top right(tall blue box). I am using flexbox and order to position it accordingly. But I want the 2nd row of red items to be 3 items wide and wrap inline with the blue aside. Screenshot of my ideal outcome below. Code at the bottom of my failed attempt.
.flex {
display: flex;
flex-wrap: wrap;
margin: auto;
max-width: 120px;
}
.flex>div {
background: red;
height: 25px;
width: 25px;
margin: 2px;
order: 3;
}
.flex>div:nth-child(-n+3) {
order: 1;
}
aside {
height: 55px;
width: 25px;
margin: 2px;
background: blue;
order: 2;
}
<div class="flex">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<aside></aside>
</div>
Worth noting that I know I can do this with floats but for other reasons unrelated to this problem I'm kind of stuck with flexbox. Open to any & all suggestions though.

Here is the problem you're facing with flexbox, and several potential solutions:
Is it possible for flex items to align tightly to the items above them?
Make a div span two rows in a grid
Here's a calculator keypad layout using flexbox:
Calculator keypad layout with flexbox
Here's the cleanest and most efficient CSS solution, which uses Grid:
.flex {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 25px;
grid-gap: 5px;
margin: auto;
max-width: 120px;
}
aside {
grid-column: 4;
grid-row: 1 / span 2;
background: blue;
}
.flex > div {
background: red;
}
<div class="flex">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<aside></aside>
</div>
jsfiddle demo
css grid browser support

.flex {
display: flex;
flex-wrap: wrap;
margin: auto;
max-width: 120px;
}
.flex>div {
background: red;
height: 25px;
width: 25px;
margin: 2px;
order: 3;
}
.flex>div:nth-child(-n+3) {
order: 1;
}
aside {
height: 55px;
width: 25px;
margin: 2px;
background: blue;
order: 2;
margin-bottom: -57px; /* added */
}
.flex>div:nth-child(6) { /* added */
margin-right: 27px;
}
<div class="flex">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<aside></aside>
</div>

Here is a version of another answer of mine, which might also qualify as a duplicate, though since it has a simpler CSS, I decided to post it as an answer.
It uses the order property and absolute position, to enable the required layout.
Read more here: Flexbox or Column CSS for positioning elements like this
Stack snippet
.container {
display: flex;
flex-wrap: wrap;
}
.container .right_corner > div {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: calc(200% + 10px);
background: blue;
}
.container::before,
.container > div {
height: 50px;
margin: 5px;
}
.container > div:not(:first-child) {
background: red;
}
.container .right_corner {
position: relative;
order: 1;
}
.container::before {
content: '';
order: 3;
}
#media (max-width: 600px){
.container > div:nth-child(n+5) {
order: 2;
}
.container > div:nth-child(n+8) {
order: 4;
}
.container::before,
.container > div {
width: calc((100% / 4) - 10px);
}
}
#media (min-width: 601px) and (max-width: 800px){
.container > div:nth-child(n+6) {
order: 2;
}
.container > div:nth-child(n+10) {
order: 4;
}
.container::before,
.container > div {
width: calc((100% / 5) - 10px);
}
}
#media (min-width: 800px) {
.container > div:nth-child(n+7) {
order: 2;
}
.container > div:nth-child(n+12) {
order: 4;
}
.container::before,
.container > div {
width: calc((100% / 6) - 10px);
}
}
<div class='container'>
<div class='right_corner'>
<div></div>
</div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>

Related

Css Grid Dynamic layouts

I am trying to make a dynamic grid layout containing 1-4 elements. They achieved something close to what I am looking for at https://css-tricks.com/exploring-css-grids-implicit-grid-and-auto-placement-powers/ under the "dynamic layouts" section. But slightly different.
The CSS for this layout:
.grid {
display: grid;
}
.grid :nth-child(2) {
grid-column-start: 2;
}
.grid :nth-child(3):last-child {
grid-column-start: span 2;
}
I am trying to do something similar but different, but I cannot get it. This is a picture of what I want to achieve:
You can use the CSS nth-last-child selector to spot when the first child is the first of three children.
.grid {
display: grid;
}
.grid :nth-child(2) {
grid-column-start: 2;
}
.grid :nth-child(1):nth-last-child(3) {
grid-row-start: span 2;
}
/**/
.grid {
width: 300px;
aspect-ratio: 1;
grid-gap: 5px;
outline: 2px solid red;
vertical-align: top;
margin: 10px;
counter-reset: num;
}
.grid * {
border: 2px solid;
font-size: 30px;
box-sizing: border-box;
font-family: sans-serif;
display: grid;
place-content: center;
}
.grid *:before {
content: counter(num);
counter-increment: num;
}
<div class="grid">
<div></div>
</div>
<div class="grid">
<div></div>
<div></div>
</div>
<div class="grid">
<div></div>
<div></div>
<div></div>
</div>
<div class="grid">
<div></div>
<div></div>
<div></div>
<div></div>
</div>

CSS Flexbox with Margin Spacing Causing Unwanted Stretch of Items

I've got a flexbox. There are 4 circles that are 25% width of the parent element. I added margin between the items but now the circles "stretch" because of my padding %. I'd like to keep the padding as a % to maintain an aspect ratio I require. But when I add margin to create spacing between the items stretch.
.items {
display: flex;
flex-wrap: wrap;
}
.items>* {
flex: 1;
flex-basis: 25%;
}
.items>*:after {
content: '';
display: block;
background: #000;
margin: 5px;
padding-bottom: 100%;
border-radius: 50%;
}
<div class="items">
<div></div>
<div></div>
<div></div>
<div></div>
</div>
The shape I want, but not the spacing:
The spacing I want, but not the shape:
Also, the reason I use margin is to have equal spacing all around the element in the case there are rows of elements.
How do I get the spacing and shape I want together?
Insert a gap in your flex element, then remove the padding and margin for the pseudoelement (::after) and use aspect-ratio
.items {
display: flex;
flex-wrap: nowrap;
gap: 20px;
}
.items > * {
flex: 1;
flex-basis: 25%;
}
.items > *::after {
content: '';
display: block;
background: #000;
aspect-ratio: 1;
border-radius: 50%;
}
<div class="items">
<div></div>
<div></div>
<div></div>
<div></div>
</div>
Why not remove the margin from the :after pseudo element and use padding on the main element? (also added box-sizing on main element):
.items {
display: flex;
flex-wrap: wrap;
}
.items>* {
flex: 1;
flex-basis: 25%;
padding: 5px;
box-sizing: border-box;
}
.items>*:after {
content: '';
display: block;
background: #000;
padding-bottom: 100%;
border-radius: 100%;
}
<div class="items">
<div></div>
<div></div>
<div></div>
<div></div>
</div>

CSS Flex: first child stretch, other children wrap

I'm trying to achieve this result, using css only: I have a container with a bunch of children inside. I would like the first child to stretch vertically and having the other children to wrap beside the first child.
expected result
this is the code:
.container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
align-content: center;
width: 350px;
border: 1px solid;
}
.container div {
min-height: 30px;
width: 100px;
background: green;
margin: 3px;
}
.container div:first-child {
background: red;
align-self: stretch;
}
<div class="container">
<div></div>
<div></div>
<div></div>
<div></div>
</div>
this is how it looks
But apparently it is not possible with flexbox. Is there any other solutions?
I know I can achieve this by taking the first child out of the container and treat it separately. But I was wondering if I could do it without changing the markup?
Thank you all!
You need CSS grid for this. Resize the container to see the result:
.container {
display: grid;
grid-template-columns: repeat(auto-fit,100px); /* width of your element */
width: 350px;
border: 1px solid;
/* resize the container*/
overflow: auto;
resize: horizontal;
}
.container div {
min-height: 30px;
background: green;
margin: 3px;
}
.container div:first-child {
background: red;
grid-area:1/1/span 200; /* 1s row/1st column/ take many rows (stretch)*/
}
<div class="container">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
position: absolute can also do the job since the width is fixed:
.container {
display: flex;
flex-wrap: wrap;
padding-left: 106px;
width: 350px;
border: 1px solid;
position: relative;
/* resize the container*/
overflow: auto;
resize: horizontal;
}
.container div {
min-height: 30px;
width: 100px;
background: green;
margin: 3px;
}
.container div:first-child {
background: red;
position: absolute;
inset: 0 auto 0 0;
}
<div class="container">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>

(HTML / CSS) How to Vertical Center Grid Within Parent Element

I am trying to center a grid display within an element 100% the size of a page, while making a space around the whole grid. I have tried auto margins, but the grid is sticking to the top of the parent. When adding manual margins, the body pushes down the grid's parent element acting as the margin of the grid. I have also tried another div within the parent element spacing the grid halfway down. Is there any way to do this cleaner (without the spacer)?
HTML:
<html>
<body>
<main>
<div class="spacer"></div>
<div class="grid">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</main>
</body>
</html>
CSS:
html, body {
height: 100%;
width: 100%;
}
main {
height: 100%;
width: 100%;
}
.spacer {
height: 10%;
}
.grid {
display: grid;
height: 80%;
width: 90%;
grid-template: 1fr 2fr 1fr / 1fr 2fr 1fr;
margin: auto;
}
JSFIDDLE:
https://jsfiddle.net/593Lovxw/22/
Try this:
html, body {
height: 100%;
width: 100%;
}
main {
background: #f00;
height: 100%;
width: 100%;
display: flex;
vertical-align: center;
}
.spacer {
background: orange;
height: 10%;
}
.grid {
display: grid;
height: 80%;
width: 90%;
grid-template: 1fr 2fr 1fr / 1fr 2fr 1fr;
margin: auto;
}
.grid div {
background: #00f;
border: thick solid black;
}
<html>
<body>
<div class="spacer"></div>
<main>
<div class="grid">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</main>
</body>
</html>

css3 display: grid; or grid-column-start: isn't working

I want to use the new grid module in CSS but it isn't working.
This is the code I have:
div {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
}
p {
grid-column-start: 2;
grid-row-start: 2;
}
<div>
<p>
Hello World! :D
</p>
</div>
It is working properly, you just need to visualise it better. Try adding some other child elements to your main container, you'd see Hello world is positioned where it should be. It is just because you have empty space all around, you are having difficulty
div.container {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
background: green;
}
div {
background: yellow;
padding: 10px;
background-clip: content-box;
}
p {
grid-column-start: 2;
grid-row-start: 2;
}
<div class="container">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<p>
Hello World! :D
</p>
</div>