3

How do I achieve this layout drawn on the picture? E.g. 3 items on left side, one centered, 2 on the right.

the ul is the orangish color and the black boxes are the items

example

ul {
  display: flex;
  width: 100%;
}
<ul>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
  <li>Item 4</li>
  <li>Item 5</li>
  <li>Item 6</li>
</ul>
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
lastnoob
  • 646
  • 12
  • 28

5 Answers5

3

If you need the centered in the exact middle of its parent, then the simplest is to use 3 wrappers, containing the items, and give them flex-basis: 33.333%.

With this you can then easily control how the items should wrap on smaller screens.

ul {
  display: flex;
  width: 100%;
  list-style: none;
  padding: 0;
}

ul li {
  flex-basis: 33.333%;
  display: flex;
}

ul li:nth-child(2) span {
  margin: auto;                          /*  align center  */
}

ul li:nth-child(3) span:first-child {
  margin-left: auto;                     /*  align right  */
}
<ul>
  <li>
    <span>Item 1</span><span>Item 2</span><span>Item 3</span>
  </li>
  <li>
    <span>Item 4</span>
  </li>
  <li>
    <span>Item 5</span><span>Item 6</span>
  </li>
</ul>

Another option is to use flex: 1 1 0 on the left/right wrappers

ul {
  display: flex;
  width: 100%;
  list-style: none;
  padding: 0;
}

ul li {
  display: flex;
}

ul li:nth-child(1),
ul li:nth-child(3) {
  flex: 1 1 0;
}

ul li:nth-child(3) span:first-child {
  margin-left: auto;
}
<ul>
  <li>
    <span>Item 1</span><span>Item 2</span><span>Item 3</span>
  </li>
  <li>
    <span>Item 4</span>
  </li>
  <li>
    <span>Item 5</span><span>Item 6</span>
  </li>
</ul>

Yet another, keeping the existing markup, is to use auto margins, though then the centered will be between, in this case, 3 and 5.

ul {
  display: flex;
  width: 100%;
  list-style: none;
  padding: 0;
}

ul li:nth-child(4) {
  margin: auto;
}
<ul>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
  <li>Item 4</li>
  <li>Item 5</li>
  <li>Item 6</li>
</ul>
Asons
  • 84,923
  • 12
  • 110
  • 165
  • 1
    No, item 4 is centered between Item 3 and Item 5, thus if there are more items on one side, it's not absolutely centered anymore. – lastnoob Sep 26 '17 at 15:08
3

Flexbox

Use 7 items.

One in the center.

Each side has 3.

Hide one on the right with visibility: hidden.

If you don't want to add a fake item in the DOM, then use a pseudo-element instead, also with visibility: hidden.

More details here:


Grid

If you're open to another CSS3 technology, you can avoid the flexbox hacks above. Here's a clean and valid solution using Grid:

ul {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  grid-template-rows: 50px;
  grid-gap: 10px;
  grid-template-areas: " item1 item2 item3 item4 ... item5 item6 ";
}

li:nth-child(1) { grid-area: item1; }
li:nth-child(2) { grid-area: item2; }
li:nth-child(3) { grid-area: item3; }
li:nth-child(4) { grid-area: item4; }
li:nth-child(5) { grid-area: item5; }
li:nth-child(6) { grid-area: item6; }

/* non-essential demo styles */
p {
  text-align: center;
}
span {
  background-color: yellow;
  padding: 5px;
}
li {
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  background-color: black;
}
ul {
  background-color: red;
  list-style: none;
  margin: 0;
  padding: 10px;
}
<ul>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
  <li>Item 4</li>
  <li>Item 5</li>
  <li>Item 6</li>
</ul>
<p><span>TRUE CENTER</span></p>
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • 1
    That's a good workaround actually, but if the items are not the same width (for example links in a navbar), it doesn't work anymore, does it? So I'd have to give the same fixed width for each item, or no? edit: just saw your link, thats good! maybe the absolute positioning is the answer – lastnoob Sep 26 '17 at 15:12
  • Actually, it can still be done, even without abspos, which could result in your items overlapping on narrower screens. See my linked posts for the details. – Michael Benjamin Sep 26 '17 at 15:15
  • @lastnoob, to avoid flexbox hacks, consider CSS Grid. Answer updated. – Michael Benjamin Sep 26 '17 at 15:45
  • 1
    1+ for the grid :) – Asons Sep 26 '17 at 15:56
1

If you don't want to change the markup, you can use Grid layout instead of Flexbox:

ul {
  display: grid;
  width: 100%;
  grid-template-columns: auto auto 1fr auto 1fr auto auto;
  grid-column-gap: 20px;
  list-style: none;
  padding: 0;
}

li {
  width: 50px;
  height: 50px;
  background: #000;
  color: #fff;
}

li:nth-child(5) {
  grid-column: 6;
}
<ul>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
  <li>Item 4</li>
  <li>Item 5</li>
  <li>Item 6</li>
</ul>
Ilya Streltsyn
  • 13,076
  • 2
  • 37
  • 57
0

Here it is:

* {
  padding: 0;
  margin: 0;
}

ul,
li {
  list-style:none;
}

ul {
  display:flex;
  width:100%;
  background-color: yellow;
  justify-content: space-between;
}

span {
  width: 50px;
  height: 50px;
  background-color: violet;
}

span + span {
  margin-left: 25px;
}

li {
  display: flex;
  flex-direction: row;
}

.centered {
  margin-left: -75px;
}
<ul>
  <li>
    <span>Item 1</span>
    <span>Item 2</span>
    <span>Item 3</span>
  </li>
  <li class="centered">
    <span>Item 4</span>
  </li>
  <li>
    <span>Item 5</span>
    <span>Item 6</span>
  </li>
</ul>

Feel free to ask questions if anything isn't clear.

P.S.
  • 15,970
  • 14
  • 62
  • 86
0

I think flexbox is a great solution for your case. I have create a codepen where you can see the results of my solution. It uses <div>s but you can change them back to <ul>.

HTML :

<div class="container">
    <div class="inter first">
        <div class="content"></div>
        <div class="content"></div>
        <div class="content"></div>
    </div>
    <div class="inter second">
        <div class="content"></div>
    </div>
    <div class="inter first">
        <div class="content dont-mind-me"></div>
        <div class="content"></div>
        <div class="content"></div>
    </div>
</div>

CSS :

.container {
    width: 600px;
    height: 20px;
    display: flex;
    background-color: orange;
}

.inter {
    flex: 1 0 auto;
    display: flex;
}
.first {
    justify-content: space-between;
}

.second {
    justify-content: center;
}

.content {
    flex: 0 1 60px;
    height: 20px;
    background-color: black;
}

.dont-mind-me {
    visibility: hidden;
}
M0nst3R
  • 5,186
  • 1
  • 23
  • 36