Home > other >  Can this grid be achieved using flex?
Can this grid be achieved using flex?

Time:05-26

This is what I need to achieve: enter image description here (Note the empty grey slots)

Which in Flex should normally behave like this: (if flex-wrap is set to wrap)

enter image description here

I know that this could be achieved with css grid

.parent {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  grid-column-gap: 0px;
  grid-row-gap: 0px;
  height: 400px;
}

.parent div {
  border: 1px solid;
  box-sizing: border-box;
}

div:nth-child(1) { grid-area: 1 / 1 / 2 / 2; }
div:nth-child(2) { grid-area: 1 / 2 / 2 / 3; }
div:nth-child(3) { grid-area: 1 / 3 / 2 / 4; }
div:nth-child(4) { grid-area: 2 / 1 / 3 / 2; }
div:nth-child(5) { grid-area: 2 / 2 / 3 / 3; }
div:nth-child(6) { grid-area: 3 / 1 / 4 / 2; }
div:nth-child(7) { grid-area: 3 / 2 / 4 / 3; }
<div >
   <div></div>
   <div></div>
   <div></div>
   <div></div>
   <div></div>
   <div></div>
   <div></div> 
</div>

The thing is that I would like to use with justify-content: space-between or gap as in my scenario the child elements are narrower and not feeling so confortable with css grid. Example:

.parent {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}

.parent div {
  border: 1px solid;
  box-sizing: border-box;
  width: calc(33% - 4px);
  height: 150px;
  margin-bottom: 8px;
}

/* just to illustrate: child(6) */
.parent div:nth-child(6) { transform: translate(calc(-100% - 8px), calc(100%   8px)); }
<div >
   <div></div>
   <div></div>
   <div></div>
   <div></div>
   <div></div>
   <div></div>
   <div></div> 
</div>

Can this be done with flex?

CodePudding user response:

writing-mode can wrap it downward in the desired shape

.parent {
  display: flex;
  flex-flow: wrap;
  width: 100%;
  writing-mode: vertical-lr;
}

and if needed you can order within

CodePudding user response:

I suppose you could cheese it using a margin/transform like so:

.parent {
 display:flex;
 width:100%;
 flex-wrap: wrap;
}

.parent div {
  box-sizing: border-box;
  height: 100px;
  width: 33.33333%;
  border: 1px solid #f00;
}

div:nth-child(6) {
  margin-left: 1px; /* force a wrap */
}

div:nth-child(n 6) {
  transform: translateX(-1px); /* correct the horizontal offset */
}
<div >
   <div></div>
   <div></div>
   <div></div>
   <div></div>
   <div></div>
   <div></div>
   <div></div> 
</div>

CodePudding user response:

It wouldn't technically be semantically incorrect to use the <hr> element as a line-break for your flex children. It essentially acts as a placeholder, and will force the following flex children to a new line.

Using margin or padding with transform to try and break it to the next line may cause overlapping issues when resizing.

In CSS2 we were able to use break-after and break-before for these types of things. But it is not widely supported in CSS3.

I hope there is this sort of functionality in the future, but for now, css-grid handles this type of design well.

.parent {
  display: flex;
  flex-wrap: wrap;
}

.parent > div {
  background-color: #1b6b34;
  height: 100px;
  width: calc(100%/3);
}

.parent > div:nth-child(even) {
  background-color: #685219;
}

hr {
  border: transparent;
  width: .1px;
}

.parent > div:nth-child(6) {
  align-self: flex-end;
}
<div >
   <div></div>
   <div></div>
   <div></div>
   <div></div>
   <div></div><hr>
   <div></div>
   <div></div> 
</div>

CodePudding user response:

I would rely on pseudo-elements and this can work up to 9 elements. I am adding some coloration to better understand the trick:

.parent {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}

.parent div {
  border: 1px solid;
  box-sizing: border-box;
  width: calc(33% - 4px);
  height: 150px;
  margin-bottom: 8px;
}

.parent:before,
.parent:after {
  content: "";
  flex-basis: 100%;
  /* to illustrate */ border-bottom:2px solid red;
}

.parent :nth-child(-n   5) {
  order:-1;
  /* to illustarte */ background: lightgreen;
}
.parent :nth-child(n   8) {
  order:1;
  /* to illustarte */ background: lightblue;
}
<div >
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
  <div>9</div>
</div>

  • Related