简体   繁体   中英

How to center single column in CSS multi-column layout

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.

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;
}

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM