Lance Pollard
Lance Pollard

Reputation: 79268

How to center first flexbox vertically, and rest of list follows

Given this markup, the first item in the list should be vertically centered in the screen, and the rest should follow after. However, it doesn't center vertically at all. Also, it shouldn't require a hardcoded value based on the height of the item (the item should be able to have dynamic height).

* {
  position: relative;
  box-sizing: border-box;
}

html, body {
  height: 100%;
  overflow: hidden;
}

div {
  display: flex;
}

body > div {
  align-items: center;
  -webkit-box-pack: center;
  -webkit-justify-content: center;
  justify-content: center;
  border: 1px solid orange;
  flex-direction: column;
}

body > div > div {
  max-width: 600px;
  border: 1px solid black;
  width: 100%;
}

body > div > div > div {
  border: 1px solid blue;
  background: red;
  height: 30px;
  flex: 1;
  width: 100%;
}

body > div {
  top: 50%;
}

body > div > div {
  -webkit-transform: translateY(-50%);
  transform: translateY(-50%);
}
<div>
  <div>
    <div></div>
  </div>
  <div>
    <div></div>
  </div>
  <div>
    <div></div>
  </div>
  <div>
    <div></div>
  </div>
  <div>
    <div></div>
  </div>
  <div>
    <div></div>
  </div>
  <div>
    <div></div>
  </div>
  <div>
    <div></div>
  </div>
  <div>
    <div></div>
  </div>
  <div>
    <div></div>
  </div>
  <div>
    <div></div>
  </div>
  <div>
    <div></div>
  </div>
</div>

Upvotes: 1

Views: 65

Answers (2)

Asons
Asons

Reputation: 87191

Assuming the items will be dynamically sized, and to solve this using CSS alone, a small markup change is needed.

The first item will have its own wrapper, and then, with a pseudo to match the second wrapper, we can give the pseudo and the second wrapper flex: 1 to equally share the body's height, minus the first wrappers content, and with this, the first item will be centered no matter each item's size.

The flex-shrink: 0; in the body > div > div rule prevents the items from shink to fit when there is too many.

Stack snippet

* {
  position: relative;
  box-sizing: border-box;
}

html, body {
  height: 100%;
  overflow: hidden;
}

body {                                          /*  added rule  */
  display: flex;
  flex-direction: column;
  margin: 0;
}

body::before, body > div:nth-child(2)  {        /*  added rule  */
  content: '';
  flex: 1;
}

div {
  display: flex;
}

body > div {
  flex-direction: column;
  align-items: center;
}

body > div > div {
  max-width: 600px;
  border: 1px solid black;
  width: 100%;
  flex-shrink: 0;                               /*  added  */
}

body > div > div > div {
  border: 1px solid blue;
  background: red;
  min-height: 30px;
  flex: 1;
}

/*  middle marker for this demo only  */
span {position: absolute; width: 30px; height: 50%; right: 0; background: lime; z-index: 100}
<div>
  <div>
    <div>Hey<br>Hey<br>Hey<br></div>
  </div>
</div>
<div>
  <div>
    <div></div>
  </div>
  <div>
    <div></div>
  </div>
  <div>
    <div>Hey<br>Hey<br>Hey<br></div>
  </div>
  <div>
    <div></div>
  </div>
  <div>
    <div></div>
  </div>
  <div>
    <div></div>
  </div>
  <div>
    <div></div>
  </div>
  <div>
    <div></div>
  </div>
  <div>
    <div></div>
  </div>
  <div>
    <div></div>
  </div>
  <div>
    <div></div>
  </div>
</div>

<span>50% high</span>

Upvotes: 1

ankita patel
ankita patel

Reputation: 4251

Give this css for center

body > div:first-child {
 margin-top:20px;
}

body > div > div{
 -webkit-transform: translateY(-50%);
 transform: translateY(-50%);
}

* {
  position: relative;
  box-sizing: border-box;
}

html, body {
  height: 100%;
  overflow: hidden;
}

div {
  display: flex;
}

body > div {
  align-items: center;
  -webkit-box-pack: center;
  -webkit-justify-content: center;
  justify-content: center;
  border: 1px solid orange;
  flex-direction: column;
}

body > div > div {
  max-width: 600px;
  border: 1px solid black;
  width: 100%;
  -webkit-transform: translateY(-50%);
  transform: translateY(-50%);
}

body > div > div > div {
  border: 1px solid blue;
  background: red;
  height: 30px;
  flex: 1;
  width: 100%;
}

body > div:first-child {
 margin-top:20px;
}
<div>
  <div>
    <div></div>
  </div>
  <div>
    <div></div>
  </div>
  <div>
    <div></div>
  </div>
  <div>
    <div></div>
  </div>
  <div>
    <div></div>
  </div>
  <div>
    <div></div>
  </div>
  <div>
    <div></div>
  </div>
  <div>
    <div></div>
  </div>
  <div>
    <div></div>
  </div>
  <div>
    <div></div>
  </div>
  <div>
    <div></div>
  </div>
  <div>
    <div></div>
  </div>
</div>

Upvotes: 2

Related Questions