Can auto margins work in CSS Grid like they do in Flexbox?

…衆ロ難τιáo~ 提交于 2019-12-01 06:11:53

问题


As far as I understand, anything flexbox can do, css-grid should also be able to do (usually more verbosely).

Yet I cannot figure out how to mimic a flexbox with an item pushing off the others with margin: auto

ul {
  list-style-type: none;
  padding: 0;
  display: flex;
  flex-direction: column;
  outline: 1px solid red;
  height: 200px;
  background-color: lime;
}

li {
  background-color: cornsilk;
}

li:last-of-type {
  margin-top: auto;
}
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
</ul>

See how all cells are sized to their content and the last li pushes the others away to appear at the end?

How would I do this with css-grid without modifying my html to add element?

ul {
  list-style-type: none;
  padding: 0;
  display: grid;
  outline: 1px solid red;
  height: 200px;
  background-color: lime;
}

li {
  background-color: cornsilk;
}

li:last-of-type {
  margin-top: auto;
}
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
</ul>

This is close, but all rows are not sized to min-content - I have no idea what they are sized to but its not min-content. The closest I can get is to add

grid-template-rows: repeat(3, min-content);

which works but only if you know the amount of lis ahead of time which is not necessary for the flexbox version.


回答1:


There is a way to get your request, that can be considered a little bit hackish, but that is effective.

Create an arbitrary number of unused rows between all the list elements and the last one. Here a snippet that will work as far as the list has less than 99 elements:

ul {
  list-style-type: none;
  padding: 0;
  display: grid;
  outline: 1px solid red;
  height: 150px;
  background-color: lime;
  grid-template-rows: repeat(99, max-content) 1fr [last];
}

li {
  background-color: cornsilk;
}

li:last-of-type {
  grid-row: last;
}
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
</ul>
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
</ul>



回答2:


Generally speaking, for alignment in flexbox there are two levels to manage:

  1. the flex container, and
  2. the flex items.

In CSS Grid, there are three levels to manage:

  1. the grid container,
  2. the rows / columns ("tracks"), and
  3. the grid items (which exist inside tracks).

When you set an auto margin on a flex item, it consumes space in the container. That's enough to space an item away from its siblings. You're done.

When you set an auto margin on a grid item, it consumes space in the track (not the container). So your tracks are not affected by auto margins.

You can see this in your Grid example. The item with margin-top: auto is pinned to the bottom of the track. While in the Flex example it's pinned to the bottom of the container.

There is no apples-to-apples method for Grid to emulate this flexbox behavior because, as mentioned above, in one case you have a container-item relationship, and in the other case you have a container-track-item relationship.

Put another way, since you're dealing with items that are all in the same line in flexbox, the spacing between them is easy. Since you're dealing with items that exist in different lines in Grid, there's more complexity.

You would need to apply the auto margin to the grid row, not the item, for it to behave like flexbox. Or, you would need to target and expand the particular grid-row-gap. None of these methods exist. The spec doesn't provide for auto margins on grid tracks or for multiple values on grid gaps in the same axis.

CSS Grid isn't here to replace flexbox. It's not even meant to be an enhanced version. Therefore, expect to find cases where flex is more useful than Grid. This post is a case in point.

Here are two other examples where flexbox may have the advantage:

  • How to get grid items of different lengths to wrap?
  • Sticky footer in css grid



回答3:


You need to make use of grid-template-rows which is used to declare the area occupied by each row where

  • minmax(1px, auto) defines that the minimum height is 1px and maximum height can be expanded as the content increases dynamically for the first 3 li.
  • 1fr is 1 fraction of the entire remaining space for last li.

ul {
  list-style-type: none;
  padding: 0;
  display: grid;
  outline: 1px solid red;
  height: 200px;
  background-color: lime;
  grid-template-rows: minmax(1px, auto) minmax(1px, auto) minmax(1px, auto) 1fr;
}

li {
  background-color: cornsilk;
}

li:last-of-type {
  margin-top: auto;
}
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
</ul>

On a further note, CSS Grid doesn't really replace the need of flexbox. https://css-tricks.com/css-grid-replace-flexbox/



来源:https://stackoverflow.com/questions/47982767/can-auto-margins-work-in-css-grid-like-they-do-in-flexbox

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!