将Flexbox放在部分元素上

时间:2019-04-01 08:00:30

标签: html css flexbox css-grid

我正在尝试使用flexbox将两个元素沿下图所示的蓝线垂直居中。

Example 1

问题是第二个框和文本是一个div的一部分,而flexbox希望像这样对齐它们:

Example 2

通过使div position: relative和文本position: absolute能够实现我的目标,除了这会导致整个容器在计算容器高度时排除文本:

Example 3

如何在仍允许容器具有容器中所有内容的高度的同时正确地使这些元素居中?

所需结果:

Desired Result

问题示例:(虽然框居中,但容器不包含文本,如蓝色边框所示。)

.container {
  display: flex;
  align-items: center;
  padding: 10px;
  border: 4px solid #00aaff;
}

.big-box {
  width: 200px;
  height: 100px;
  margin-right: 20px;
  padding: 10px;
  border: 4px solid black;
}

.small-box {
  width: 150px;
  height: 50px;
  padding: 10px;
  border: 4px solid black;
}

.group {
  position: relative;
}

.group p {
  position: absolute;
  margin-top: 20px;
}
<div class="container">
  <div class="big-box">
    Lots of content...
  </div>

  <div class="group">
    <div class="small-box">
      Some content...
    </div>

    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
  </div>
</div>

2 个答案:

答案 0 :(得分:6)

我只找到了使用JavaScript和网格的解决方案。 原则上,JS也应该与flex一起使用,但是我从网格开始,因为我认为从flex开始是不可能的。

{
  // define some vars local to this block
  // CSS selectors for the containers
  const containerSelector = '.container';
  const leftSelector = '.left-box';
  const rightSelector = '.right-box';

  // this function will recalculate the height of two grid boxes
  const recalc = () => {
    const containers = document.querySelectorAll(containerSelector);
    for (let container of containers) {
      const l = container.querySelector(`:scope > ${leftSelector} > *`).offsetHeight
      const r = container.querySelector(`:scope > ${rightSelector} > *`).offsetHeight
      const gap = parseInt(window.getComputedStyle(container).gridRowGap)
      // +-----+  +-----+
      // |     |  |  c  |
      // |     |  +-----+  ------.
      // |     |                  }-- gap
      // |     |  +-----+  ------´
      // |  l  |  |  r  | 
      // |     |  +-----+  ------.
      // |     |                  }-- gap
      // |     |  +-----+  --.---´ 
      // |     |  |  c  |     }
      // +-----+  +- - -|     }------ text
      //          |     |     }
      //          +-----+  --´
      // l = c + gap + r + gap + c
      // l = 2 * c + 2 * gap + r
      // l - r - 2 * gap = 2 * c
      const c = (l - r - 2 * gap) / 2
      container.style.gridTemplateRows = `${c}px auto ${c}px auto`
    }
  }

  window.addEventListener('resize', recalc);
  window.addEventListener('load', recalc);
  recalc();
}
.container {
  align-content: left;
  border: 1px solid gold;
  width: 50%;
  margin: auto;
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr auto 1fr auto;
  grid-auto-rows: auto;
  grid-gap: 1rem 50px;
  padding: 25px;
  grid-template-areas: "leftbox b" "leftbox rightbox" "leftbox mytextbox" "a mytextbox";
}

.container .left-box {
  grid-area: leftbox;
  background-color: green;
}

.container .right-box {
  grid-area: rightbox;
  background-color: orange;
}

.container .text-box {
  grid-area: mytextbox;
  background-color: yellow;
}

.container figure {
  border: 1px solid;
  margin: 0;
}

.container figure img {
  display: block;
  width: 100%;
  max-width: 100%;
  height: auto;
}
<div class="container">
  <div class="left-box">
    <figure>
      <img src="http://picsum.photos/225/300?image=990" alt="">
      <figcaption>Figure 1</figcaption>
    </figure>
  </div>
  <div class="right-box">
    <figure>
      <img src="http://picsum.photos/225/100?image=991" alt="">
      <figcaption>Figure 2</figcaption>

    </figure>
  </div>
  <div class="text-box">Lorem ipsum dolor sit amet consectetur adipisicing elit. Est, cum porro quod unde neque doloribus excepturi odio nobis necessitatibus, nostrum labore id. Dolorem facere, quia nihil similique quis consectetur earum repudiandae non ut aperiam, dolore
    cum, corporis ratione quaerat temporibus.<br> Lorem ipsum dolor sit, amet consectetur adipisicing elit. Corrupti quam impedit perspiciatis sit nulla officiis in, delectus adipisci aliquam dolores, ratione voluptates dolorem odio ab ducimus praesentium
    omnis! Unde, at?<br>
  </div>
</div>

如果没有JS部分,则左框会太大,因为1fr单元太贪婪(或者auto行太烂了)。

.container {
  align-content: left;
  border: 1px solid gold;
  width: 50%;
  margin: auto;
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr auto 1fr auto;
  grid-auto-rows: auto;
  grid-gap: 1rem 50px;
  padding: 25px;
  grid-template-areas: "leftbox b" "leftbox rightbox" "leftbox mytextbox" "a mytextbox";
}
.container .left-box {
  grid-area: leftbox;
  background-color: green;
}
.container .right-box {
  grid-area: rightbox;
  background-color: orange;
}
.container .text-box {
  grid-area: mytextbox;
  background-color: yellow;
}
.container figure {
  border: 1px solid;
  margin: 0;
}
.container figure img {
  display: block;
  width: 100%;
  max-width: 100%;
  height: auto;
}
<div class="container">
  <div class="left-box">
    <figure>
      <img src="http://picsum.photos/225/300?image=990" alt="">
      <figcaption>Figure 1</figcaption>
    </figure>
  </div>
  <div class="right-box">
    <figure>
      <img src="http://picsum.photos/225/100?image=991" alt="">
      <figcaption>Figure 2</figcaption>

    </figure>
  </div>
  <div class="text-box">
  Lorem ipsum dolor sit amet consectetur adipisicing elit. Est, cum porro quod unde neque doloribus excepturi odio nobis necessitatibus, nostrum labore id. Dolorem facere, quia nihil similique quis consectetur earum repudiandae non ut aperiam, dolore cum, corporis ratione quaerat temporibus.<br> Lorem ipsum dolor sit, amet consectetur adipisicing elit. Corrupti quam impedit perspiciatis sit nulla officiis in, delectus adipisci aliquam dolores, ratione voluptates dolorem odio ab ducimus praesentium omnis! Unde, at?<br>
  Lorem ipsum dolor sit amet consectetur adipisicing elit. Est, cum porro quod unde neque doloribus excepturi odio nobis necessitatibus, nostrum labore id. Dolorem facere, quia nihil similique quis consectetur earum repudiandae non ut aperiam, dolore cum, corporis ratione quaerat temporibus.<br> Lorem ipsum dolor sit, amet consectetur adipisicing elit. Corrupti quam impedit perspiciatis sit nulla officiis in, delectus adipisci aliquam dolores, ratione voluptates dolorem odio ab ducimus praesentium omnis! Unde, at?<br>
  </div>
</div>

我也创建了一个flex版本

console.clear()
{
  const containerSelector = '.container';
  const leftColSelector = '.left-col';
  const rightColSelector = '.right-col';
  const leftSelector = '.left-box';
  const rightSelector = '.right-box';
  const rightSpacerSelector = '.right-spacer';

  const recalc = () => {
    const containers = document.querySelectorAll(containerSelector);
    for (let container of containers) {
      const l = container.querySelector(`:scope > ${leftColSelector} > ${leftSelector} > *`).offsetHeight;
      const r = container.querySelector(`:scope > ${rightColSelector} > ${rightSelector} > *`).offsetHeight;
      const s = container.querySelector(`:scope > ${rightColSelector} > ${rightSpacerSelector}`)
      const c = (l - r) / 2
      s.style.height = `${c}px`;
      // container.style.gridTemplateRows = `${c}px auto ${c}px auto`
    }
  }

  window.addEventListener('resize', recalc);
  window.addEventListener('load', recalc);
  recalc();
}
.container {
  border: 1px solid gold;
  width: 50%;
  margin: auto;
  display: flex;
  flex-wrap: flex;
  padding: 25px;
}
.container .left-col,
.container .right-col {
  width: calc(50% - 25px);
}
.container .left-col {
  margin-right: 25px;
}
.container .right-col {
  margin-left: 25px;
}
.container .left-box {
  background-color: green;
}
.container .right-box {
  background-color: orange;
}
.container .text-box {
  background-color: yellow;
}
.container figure {
  border: 1px solid;
  margin: 0;
}
.container figure img {
  display: block;
  width: 100%;
  max-width: 100%;
  height: auto;
}
<div class="container">
  <div class="left-col">
    <div class="left-box">
      <figure>
        <img src="http://picsum.photos/225/300?image=990" alt="">
        <figcaption>Figure 1</figcaption>
      </figure>
    </div>
  </div>
  <div class="right-col">
    <div class="right-spacer"></div>
    <div class="right-box">
      <figure>
        <img src="http://picsum.photos/225/100?image=991" alt="">
        <figcaption>Figure 2</figcaption>

      </figure>
    </div>
    <div class="text-box">Lorem ipsum dolor sit amet consectetur adipisicing elit. Est, cum porro quod unde neque doloribus excepturi odio nobis necessitatibus, nostrum labore id. Dolorem facere, quia nihil similique quis consectetur earum repudiandae non ut aperiam, dolore
      cum, corporis ratione quaerat temporibus.<br> Lorem ipsum dolor sit, amet consectetur adipisicing elit. Corrupti quam impedit perspiciatis sit nulla officiis in, delectus adipisci aliquam dolores, ratione voluptates dolorem odio ab ducimus praesentium
      omnis! Unde, at?<br>
    </div>

  </div>
</div>

答案 1 :(得分:4)

我希望这是您正在寻找的解决方案

$(window).on('resize load', function(){
  var coll = $('.big-box').height();
  var sheight = $('.small-box').height();
  var calci = (coll - sheight)/2;
  $('.small-box').css({'margin-top':calci});
});
.container {
  padding: 10px;
  border: 4px solid #00aaff;
  position:relative;
  height:auto;
  display:inline-block;
  width:100%;
}
.big-box{
  display:inline-block;
  width:49%;
  border:2px solid #000;
  float:left;
  height:200px;
  box-sizing:border-box;
}
.right-div{
  display:inline-block;
  width:calc(100% - 49% - 20px);
  float:left;
  margin-left:20px;
  box-sizing:border-box;
}
.small-box{
  border:2px solid #000;
  height:50px;
 
  
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
      <div class="big-box">
        Lots of content...
      </div>
      <div class="right-div">
        <div class="small-box">
            Some content...
        </div>
        <div class="group1">
                <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
        </div>
      </div>
</div>