Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS grid as child of flexbox not behaving as expected

I have often created a responsive 3-column grid with CSS display: grid. My HTML markup inside the grid has 3 div items, so the grid creates 3 columns

display: grid;
grid-gap: 2rem;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));

enter image description here

and as you resize the window it collapses to 1 column, as expected:

https://codepen.io/smlombardi/pen/oqMjrd?editors=1100

.hero-modules {
  display: grid;
  grid-gap: 2rem;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
}

.hero-modules .hero-item {
  border: 1px solid #000;
  text-align: center;
}

.hero-modules .hero-item h3 {
  font-size: 22px;
  text-align: center;
}
<div class="hero-modules">
  <div class="hero-item">
    <div>
      <h3>Title of Item</h3>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dicta est ipsa recusandae.</p>
    </div>
    <div>
      <a class="hero-read-more">Read more</a>
    </div>
  </div>

  <div class="hero-item">
    <div>
      <h3>Title of Item</h3>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dicta est ipsa recusandae.</p>
    </div>
    <div>
      <a class="hero-read-more">Read more</a>
    </div>
  </div>

  <div class="hero-item">
    <div>
      <h3>Title of Item</h3>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dicta est ipsa recusandae.</p>
    </div>
    <div>
      <a class="hero-read-more">Read more</a>
    </div>
  </div>
</div>

Now I need to use this grid inside a Flexbox, to center the enclosing box to float on the link background:

enter image description here

And as you can see, the grid collapses (the dotted border is only added to show the extents of the flex child).

https://codepen.io/smlombardi/pen/PRBPWB?editors=1100

.hero {
  background-color: pink;
  display: flex;
  min-height: 600px;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  border: 1px solid #000;
}

.box {
  border: 1px dotted #000;
  text-align: center;
}

.button-unit {
  text-align: center;
  margin-top: 20px;
}

.hero-modules {
  display: grid;
  grid-gap: 2rem;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}

.hero-modules .hero-item {
  border: 1px solid #000;
  text-align: center;
}

.hero-modules .hero-item h3 {
  font-size: 22px;
  text-align: center;
}
<div class="hero">
  <div class="box">
    <div>
      <h1 class="hero-heading">Check out these new features</h1>
    </div>

    <div class="hero-modules">
      <div class="hero-item">
        <div>
          <h3>Title of Item</h3>
          <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dicta est ipsa recusandae.</p>
        </div>
        <div>
          <a class="hero-read-more">Read more</a>
        </div>
      </div>

      <div class="hero-item">
        <div>
          <h3>Title of Item</h3>
          <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dicta est ipsa recusandae.</p>
        </div>
        <div>
          <a class="hero-read-more">Read more</a>
        </div>
      </div>

      <div class="hero-item">
        <div>
          <h3>Title of Item</h3>
          <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dicta est ipsa recusandae.</p>
        </div>
        <div>
          <a class="hero-read-more">Read more</a>
        </div>
      </div>
    </div>

    <div class="button-unit">
      <button class="btn btn-secondary mb-3">Got It</button>
      <p>
        <a class="remind-me-later" href="">Remind me later</a>
      </p>
    </div>
  </div>
</div>

<div class="container">
  <div class="row">
    <div class="col">
      Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nostrum molestias earum beatae, minima provident sunt a et? Voluptatibus sequi ipsum ad asperiores soluta odio, nam nobis quas non totam ut officiis itaque eveniet, maiores saepe id cum consequuntur.
      Molestias suscipit quia laudantium laborum nemo ab officia, nihil esse mollitia sunt!
    </div>
  </div>
</div>

Why is this happening? Is there something I am missing not allowing the grid to behave normally?

like image 875
Steve Avatar asked Apr 03 '18 14:04

Steve


People also ask

Is CSS Grid better than flexbox?

If you are using flexbox and find yourself disabling some of the flexibility, you probably need to use CSS Grid Layout. An example would be if you are setting a percentage width on a flex item to make it line up with other items in a row above. In that case, a grid is likely to be a better choice.

How do I make my flex grid responsive?

Creating the responsive gridUsing display: flex , our grid-row stretches to the full size of the container. We use flex-flow: wrap to designate that child divs (our columns/grid-items) should wrap if they exceed the width of the row. Then, flex-flow: row means our grid-items will flex from left to right.

Is CSS Grid identical to flexbox?

CSS Grid and Flexbox are layout models that share similarities and can even be used together. The main difference is that you can use CSS Grid to create two-dimensional layouts. In contrast, you can only use Flexbox to create one-dimensional layouts.

Should I use grid or flexbox 2022?

Grid is best for two-dimensional layouts with many elements that need to be precisely positioned relative to each other. Flexbox is better for one-dimensional or single-line layouts where you just need to space a bunch of elements a certain way.


2 Answers

The Simple Answer:

The grid container's automatic width is essentially whatever it would be if it weren't a grid container.

In the first example, the grid container width is only constrained by the width of the document and any default margins.

In the second example, the grid container width is the width of an ancestor flex item with default shrinkwrap behavior that's dependent on the width of its content, the text "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dicta est ipsa recusandae." (To put it more directly, the width of the grid container is the width of the preceding, quoted sentence.)

The Extended Answer:

The grid container (.hero-modules) has width: auto (the default). Per https://drafts.csswg.org/css-grid/#grid-container:

As a block-level box in a block formatting context, it is sized like a block box that establishes a formatting context, with an auto inline size calculated as for non-replaced block boxes.

The term "auto inline size" is just another way of saying width: auto in this case. (The "auto inline size" is height: auto in vertical text.)

"A block box that establishes a formatting context" is the same as a box with display: flow-root. Changing display: grid to display: flow-root will demonstrate what width is being used to calculate the width of the grid container as a result of width: auto.

So now we know where the grid container size comes from.

The flex item's size comes from flex-grow: 0 and flex-shrink: 1 (the defaults), which makes its width shrink and not grow. The basis for the flex item's width is flex-basis: auto (the default), which resolves to flex-basis: content. The content is the text "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dicta est ipsa recusandae."

So now we know why the flex item doesn't expand and what its width is based on.

Fixing This Layout:

This flex layout should not be column-based; it should be row-based. Columns are inside the sole flex item, but not flex items themselves and dimensional flexibility is desired on the x-axis, not the y-axis.

So, flex-direction: column needs to become flex-direction: row.

The flex layout needs to grow (on the x-axis) to fit available space, so flex-grow: 1 needs to be specified on the flex item (.box).

Lastly, the grid-template-columns value should use auto-fit, not auto-fill if horizontal centering is desired. Grid items can be centered with justify-content: center applied to the grid container element.

(With auto-fill, invisible placeholder grid items will be placed to fill out the layout, which will cause the three present grid items to be aligned to the left with a bunch of invisible placeholder items filling out the remaining blank space to their right. With auto-fit, those placeholder grid items are simply discarded and that space is freed for horizontal alignment.)

.hero {
  background-color: pink;
  display: flex;
  min-height: 600px;
  flex-direction: row;
  align-items: center;
  justify-content: center;
  border: 1px solid #000;
}

.box {
  border: 1px dotted #000;
  flex-grow: 1;
  text-align: center;
}

.button-unit {
  text-align: center;
  margin-top: 20px;
}

.hero-modules {
  display: grid;
  grid-gap: 2rem;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  justify-content: center;
}

.hero-modules .hero-item {
  border: 1px solid #000;
  text-align: center;
}

.hero-modules .hero-item h3 {
  font-size: 22px;
  text-align: center;
}
<div class="hero">
  <div class="box">
    <div>
      <h1 class="hero-heading">Check out these new features</h1>
    </div>

    <div class="hero-modules">
      <div class="hero-item">
        <div>
          <h3>Title of Item</h3>
          <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dicta est ipsa recusandae.</p>
        </div>
        <div>
          <a class="hero-read-more">Read more</a>
        </div>
      </div>

      <div class="hero-item">
        <div>
          <h3>Title of Item</h3>
          <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dicta est ipsa recusandae.</p>
        </div>
        <div>
          <a class="hero-read-more">Read more</a>
        </div>
      </div>

      <div class="hero-item">
        <div>
          <h3>Title of Item</h3>
          <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dicta est ipsa recusandae.</p>
        </div>
        <div>
          <a class="hero-read-more">Read more</a>
        </div>
      </div>
    </div>

    <div class="button-unit">
      <button class="btn btn-secondary mb-3">Got It</button>
      <p>
        <a class="remind-me-later" href="">Remind me later</a>
      </p>
    </div>
  </div>
</div>

<div class="container">
  <div class="row">
    <div class="col">
      Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nostrum molestias earum beatae, minima provident sunt a et? Voluptatibus sequi ipsum ad asperiores soluta odio, nam nobis quas non totam ut officiis itaque eveniet, maiores saepe id cum consequuntur.
      Molestias suscipit quia laudantium laborum nemo ab officia, nihil esse mollitia sunt!
    </div>
  </div>
</div>
like image 73
Patrick Dark Avatar answered Nov 12 '22 10:11

Patrick Dark


Add **display:flex** property to your main container.

 .Main {
     display:flex;
  }
 div {
   flex: 1;
 }

Then All div will be act as grid for more information refer below link. https://www.w3schools.com/css/css3_flexbox.asp

like image 1
Shamim Avatar answered Nov 12 '22 11:11

Shamim