Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Center Flexbox on Part of Element

I am trying to use flexbox to vertically center two elements along the blue line shown in the picture below.

Example 1

The problem is that the second box and the text are part of one div and flexbox wants to align them like this:

Example 2

By making the div position: relative and the text position: absolute I am able to accomplish my goal, except that this causes the entire container to exclude the text in calculating the height of the container:

Example 3

How can I center these elements correctly while still allowing the container to have the height of all content in the container?

Desired Result:

Desired Result

Example of Problem: (While the boxes are centered, the container does not include the text, as shown by a blue border.)

.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>
like image 750
Mitch Talmadge Avatar asked Apr 01 '19 08:04

Mitch Talmadge


People also ask

How do I center all items in a Flexbox?

By using align-items: center we can vertically center all flex items to the parent container along the cross axis of the flex container. The nice aspect of flexbox is the styles apply to all children of our flex container. If we add two more elements they all stay centered within the parent select.

How to center a <Div> using Flexbox property of CSS?

How to center a <div> using Flexbox property of CSS ? 1 We use the property of display set to flex i.e. display: flex; 2 Align items to center using align-items: center; 3 The last step is to set justify-content to center i.e. justify-content: center;

How do I Center a flex element vertically?

If you just want specific flex items to be centered vertically, you can set align-self on the items instead: arrr! yeehaw! If you want to put an element at the dead center of a page, it can be a little bit more tricky because flex items will only center vertically according to the height of their container.

What is flexbox and how to use it?

With the layout superpowers of flexbox, you can align and justify your HTML elements perfectly within the center of its parent element. Centering elements vertically has always been a challenge in web design, until flexbox arrived on the scene. With flexbox it’s easy to center elements vertically in their parent element.


1 Answers

I only found a solution which uses JavaScript and grid. In principle The JS should work with flex, too, but I started with grid, because I thought it wouldn't be possible with flex to begin with.

{
  // 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>

Without the JS part, the left-box would be too big, because the 1fr unit is too greedy (or the auto rows are too relutant).

.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>

I've created a flex version as well

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>
like image 101
yunzen Avatar answered Sep 28 '22 07:09

yunzen