Center parent div with float children

2019-03-02 03:18发布

问题:

Parent hasnt got a defined width because there are unknown number of children inside.

Why do children fall into new line and how to prevent that? Children need to be on the same line.

.wrap {
  position: absolute;
  left: 50%;
  top: 50px;
  height:40px;
  transform: translateX(-50%);
}
.box {
 width:40px;
 height:40px;
 float:left;
 background:red;
 margin-right:1px;
}
<div class="wrap">
  <div class="box">0</div>
  <div class="box">1</div>
  <div class="box">2</div>
  <div class="box">3</div>
  <div class="box">4</div>
  <div class="box">5</div>
  <div class="box">6</div>
  <div class="box">7</div>
  <div class="box">8</div>
  <div class="box">9</div>
  <div class="box">10</div>
</div>

回答1:

You should consider using flex-box.

And to answer your question: floated DIVs are not supposed and will not expand their parent's width, as they are 'floating' above the content flow.

Absolute positioned block elements will have an initial width of zero, if not specified otherwise. Thus, they're behaving differently than usual.

The floating elements indeed behave as usual: as the parent element provides not enough width (zero!) to display them all in one line, of course they break to the next line.

.wrap {
  display: flex;
  justify-content: center;
  flex-wrap: nowrap;
  margin-top: 50px;
}
.box {
 width:40px;
 height:40px;
 float:left;
 background:red;
 margin-right:1px;
}
<div class="wrap">
  <div class="box">0</div>
  <div class="box">1</div>
  <div class="box">2</div>
  <div class="box">3</div>
  <div class="box">4</div>
  <div class="box">5</div>
  <div class="box">6</div>
  <div class="box">7</div>
  <div class="box">8</div>
  <div class="box">9</div>
  <div class="box">10</div>
</div>



回答2:

Since you are using left: 50%, the maximum width of .wrap is the 50% remaining of body.

That's why the wrap is happening.

To avoid it, add more space to it with margin-right: -50%. This will give it an aditional 50% (that is the space lost with the left: 50% style)

.wrap {
  position: absolute;
  left: 50%;
  margin-right: -50%;
  top: 50px;
  height:40px;
  transform: translateX(-50%);
}
.box {
 width:40px;
 height:40px;
 float:left;
 background:red;
 margin-right:1px;
}
<div class="wrap">
  <div class="box">0</div>
  <div class="box">1</div>
  <div class="box">2</div>
  <div class="box">3</div>
  <div class="box">4</div>
  <div class="box">5</div>
  <div class="box">6</div>
  <div class="box">7</div>
  <div class="box">8</div>
  <div class="box">9</div>
  <div class="box">10</div>
</div>



回答3:

What happens here is that when you use translate the element is visually re-positioned, though from a document flow perspective it is still positioned at 50% left.

So as you can see in this sample, they wrap at the same time though one think that the first shouldn't as there is space left, but there isn't, as technically the first has the same position as the second, hence it wrap at the same time.

.wrap {
  position: absolute;
  left: 50%;
  top: 150px;
  height:40px;
}
.wrap.translate {
  top: 50px;
  transform: translateX(-50%);
}
.box {
 width:40px;
 height:40px;
 float:left;
 background:red;
 margin-right:1px;
}
<div class="wrap translate">
  <div class="box">0</div>
  <div class="box">1</div>
  <div class="box">2</div>
  <div class="box">3</div>
  <div class="box">4</div>
  <div class="box">5</div>
  <div class="box">6</div>
  <div class="box">7</div>
  <div class="box">8</div>
  <div class="box">9</div>
  <div class="box">10</div>
</div>
<div class="wrap">
  <div class="box">0</div>
  <div class="box">1</div>
  <div class="box">2</div>
  <div class="box">3</div>
  <div class="box">4</div>
  <div class="box">5</div>
  <div class="box">6</div>
  <div class="box">7</div>
  <div class="box">8</div>
  <div class="box">9</div>
  <div class="box">10</div>
</div>


The simplest and best way to solve this is to make the wrap an inline-block and set text-align: center on its parent, in this case the body

body {
  text-align: center;
}
.wrap {
  display: inline-block;
  height:40px;
}
.box {
 width:40px;
 height:40px;
 float:left;
 background:red;
 margin-right:1px;
}
<div class="wrap">
  <div class="box">0</div>
  <div class="box">1</div>
  <div class="box">2</div>
  <div class="box">3</div>
  <div class="box">4</div>
  <div class="box">5</div>
  <div class="box">6</div>
  <div class="box">7</div>
  <div class="box">8</div>
  <div class="box">9</div>
  <div class="box">10</div>
</div>


Yet another is to make the box's inline-block and set text-align: center on the wrap

Note, to defeat the white space between inline block elements, I also change the markup so each box's end and start tag are on the same line. Here is a few more ways to solve that: how-to-remove-the-space-between-inline-block-elements

.wrap {
  height:40px;
  text-align: center;
}
.box {
 display: inline-block;
 width:40px;
 height:40px;
 background:red;
 margin-right:1px;
}
<div class="wrap">
  <div class="box">0
  </div><div class="box">1
  </div><div class="box">2
  </div><div class="box">3
  </div><div class="box">4
  </div><div class="box">5
  </div><div class="box">6
  </div><div class="box">7
  </div><div class="box">8
  </div><div class="box">9
  </div><div class="box">10
  </div>
</div>


If you don't need to support older browsers you can also use Flexbox

.wrap {
  display: flex;
  justify-content: center;
  height:40px;
}
.box {
 width:40px;
 height:40px;
 background:red;
 margin-right:1px;
}
<div class="wrap">
  <div class="box">0</div>
  <div class="box">1</div>
  <div class="box">2</div>
  <div class="box">3</div>
  <div class="box">4</div>
  <div class="box">5</div>
  <div class="box">6</div>
  <div class="box">7</div>
  <div class="box">8</div>
  <div class="box">9</div>
  <div class="box">10</div>
</div>



回答4:

Use center class :

.wrap {
  text-align: center;
  margin: 50px auto 0 auto;
  height:40px;
}

.center {
  display: inline-block;
}

.box {
 width: 40px;
 height:40px;
 float:left;
 background:red;
 margin-right:1px;
}

@media all and (max-width: 474px) {
  .box {
    width: 25px;
  }
}
<div class="wrap">
  <div class="center">
    <div class="box">0</div>
    <div class="box">1</div>
    <div class="box">2</div>
    <div class="box">3</div>
    <div class="box">4</div>
    <div class="box">5</div>
    <div class="box">6</div>
    <div class="box">7</div>
    <div class="box">8</div>
    <div class="box">9</div>
    <div class="box">10</div>
  </div>
</div>