How to center single column in CSS multi-column layout

巧了我就是萌 提交于 2021-01-29 03:23:51

问题


I have an element using CSS multi-column layout to display a list of items.

<div style="column-width: 300px; column-count: 3; text-align: center;">
    <div>Item 1</div>
    <div>Item 2</div>
    <div>Item 3</div>
    <div>Item 4</div>
    <div>Item 5</div>
    <div>Item 6</div>
</div>

The example list correctly displays as three columns, each containing two items, with each item centered within its column.

However, when I have a list containing only one item, the item is shown in the first column while the space for the second and third columns are still being held empty.

Is there any way to make the single column centered within the parent element? Likewise, if I have a list of only two items, is there a way to make the two populated columns centered within the parent element?

Essentially, what I want is, if there are three or more items, display three columns, but if there are only one or two items, display only the number of columns needed to display those items without reserving the unused column space.

EDIT

The problem is when I have a list with only one item, like:

<div style="column-width: 300px; column-count: 3; text-align: center;">
    <div>Item 1</div>
</div>

The single item is in column one, while the space where columns two and three would be are still reserved, even though there is no content there.


回答1:


I created a fiddle: https://jsfiddle.net/Lvtya3qL/

<div class="parent">
    <div class="child">Item 1</div>
    <div class="child">Item 2</div>
    <div class="child">Item 3</div>
    <div class="child">Item 4</div>
    <div class="child">Item 5</div>
    <div class="child">Item 6</div>
    <div class="child">Item 7</div>
</div>

.parent{
  display:flex;
  width: 300px;
  flex-wrap: wrap;
  justify-content: center;
}

.child {
  width: 100px;
}



回答2:


I wasn't planning on answering this question, because the problem I'm facing is different. But then I noticed that the only answer here threw out the columns and switched to flexbox, which does a completely different thing, leaving the question sort of unanswered.

I've made an implementation that you can find below. I've also added a fourth column, so that it is more clear what I am doing at the :nth-child(n):nth-last-child(n) parts of the CSS.

You can see that there are 3 odd selectors that all add an inset on the left, so that all children are centered. You can keep adding these selectors the more columns you want. The amount of selectors you need, is the amount of columns - 1.

When going for 3 columns, you can remove the last odd-looking selector.
Like stated, I had added the fourth column so that you can see the selector-pattern you need to apply to get this to work.

.parent {
  --columns: 4;
  --gap:     1em;
  column-count: var(--columns);
  column-gap:   var(--gap);
}

.child {
  position: relative;
  break-inside: avoid;
  break-inside: avoid-column;
}

.child:only-child {
  left: calc((100% + var(--gap)) * (var(--columns) - 1) / 2);
}

.child:nth-child(1):nth-last-child(2),
.child:nth-child(2):nth-last-child(1) {
  left: calc((100% + var(--gap)) * (var(--columns) - 2) / 2);
}

.child:nth-child(1):nth-last-child(3),
.child:nth-child(2):nth-last-child(2),
.child:nth-child(3):nth-last-child(1) {
  left: calc((100% + var(--gap)) * (var(--columns) - 3) / 2);
}

/* Prettifications only */

body {
  margin: 0;
  font-family: sans-serif;
}

.parent {
  margin: var(--gap);
  text-align: center;
}

.child {
  padding: 8px 0;
  background-color: rgba(127,127,127,.1);
  outline: 1px solid black;
  outline-offset: -1px;
}
<div class="parent">
    <div class="child">1</div>
</div>
<div class="parent">
    <div class="child">1</div>
    <div class="child">2</div>
</div>
<div class="parent">
    <div class="child">1</div>
    <div class="child">2</div>
    <div class="child">3</div>
</div>
<div class="parent">
    <div class="child">1</div>
    <div class="child">2</div>
    <div class="child">3</div>
    <div class="child">4</div>
</div>

There is a big downside to this, though. It isn't responsive by itself anymore!

I've removed column-width, which might as well render this implementation useless for your case, because the column-width property was previously solely responsible for making the whole responsive. If you are okay with manually adding breakpoints, however, then I think this is one of the only ways to implement centered multi-column layout.

Adding breakpoints is best done as follows:

@media all and (min-width: 500px) {
  .parent { --columns: 2 }

  .child:only-child {
    left: calc((100% + var(--gap)) * (var(--columns) - 1) / 2);
  }
}

@media all and (min-width: 600px) {
  .parent { --columns: 3 }

  .child:nth-child(1):nth-last-child(2),
  .child:nth-child(2):nth-last-child(1) {
    left: calc((100% + var(--gap)) * (var(--columns) - 2) / 2);
  }
}

@media all and (min-width: 700px) {
  .parent { --columns: 4 }

  .child:nth-child(1):nth-last-child(3),
  .child:nth-child(2):nth-last-child(2),
  .child:nth-child(3):nth-last-child(1) {
    left: calc((100% + var(--gap)) * (var(--columns) - 3) / 2);
  }
}

This way, the styles are only applied when they can be needed. Also: remember to keep the media-queries in this order. The higher the media-query, the higher the --columns variable has to be.



来源:https://stackoverflow.com/questions/41992140/how-to-center-single-column-in-css-multi-column-layout

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