skip to Main Content

I wonder if there is a pure elegant css solution to get a text next to a float element going under it when its height is higher than the float element BUT ALSO be centered when its height is lower than the float element. The 2 next images present what I want to obtain :
enter image description here
enter image description here

And there a coded version of both cases :

.float {
  float: right;
  height: 80px;
  width: 500px;
  background-color: blue;
}

#with_text_centered {
  height: 80px;
  position: relative;
}

#with_text_centered p {
  position: relative;
  top: 50%;
  transform: translate(0, -50%);
}
<h1>WITH TEXT UNDER THE FLOAT</h1>

<div class=ctn>
  <div class=float></div>
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>

<h1>WITH TEXT CENTERED</h1>

<div id="with_text_centered">
  <div class=float></div>
  <p>Lorem ipsum.</p>
</div>

I can so do each separately but can’t find a way to do both (for responsive design purpose). The only solution I found for now require js (using ResizeObserver) and it seams odd to me to have to use some js in that case that seams pretty simple.

Also, I would for sure prefer to not have to hardly define height anywhere. In my exemple, I unfortunately define a height of 80px.In fact, in my version using js, I switch to a flexbox when the text is lower than the float element. It’s easier and more elegant like this IMO to center the text. When I do so the float is ignored (flex are made to ignore float).

2

Answers


  1. I will provide an answer for those who face a similar problem – there is NO css solution. Because elements with the float property are removed from the normal stream.
    A simple javascript solution, as the questioner pointed out – watch the height of the float and the content. Something like this:

    window.addEventListener('load', centeContent);
    window.addEventListener('resize', centeContent);
    
    function centeContent() {
      document.querySelectorAll('.container').forEach(el => {
        const imgHeight = el.querySelector('img')?.clientHeight || 0;
        el.style.removeProperty('--display');
        el.style.setProperty('--min-height', imgHeight);
        if(el.offsetHeight <= imgHeight) {
          el.style.setProperty('--display', 'flex');
        }
      })
    }
    * {
      box-sizing: border-box;
      margin: 0;
      padding: 0;
    }
    
    .container {
      display: flow-root;
      max-width: 400px;
      margin-bottom: 16px;
    }
    
    .container img {
      float: right;
      max-width: 50%;
      margin-left: 16px;;
    }
    
    .content {
      display: var(--display, block);
      min-height: calc(var(--min-height) * 1px);
      flex-direction: column;
      justify-content: center;
    }
    <div class="container">
      <img src="https://picsum.photos/200/120" alt="">
      <div class="content">
        Lorem ipsum dolor sit amet, consectetur adipisicing elit. Fugit, a asperiores officia amet rerum nesciunt!
      </div>
    </div>
    <div class="container">
      <img src="https://picsum.photos/200/120" alt="">
      <div class="content">
        Lorem ipsum dolor sit amet, consectetur adipisicing elit. Mollitia, dolores id odit. Deserunt, quae iste doloremque eligendi earum provident tenetur aperiam necessitatibus cumque nemo mollitia voluptas et aliquid veritatis reiciendis veniam ab odio repellat accusamus modi quasi nam corrupti eum? Dolor, nesciunt repellat voluptas eos nostrum quasi ipsum! Veritatis, quo!
      </div>
    </div>
    Login or Signup to reply.
  2. Using container queries, you can get close to this behavior. However, it is not achievable to adapt elements based solely off content height. For that, you need some js.

    More here: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_containment/Container_queries

    I made a fiddle too:
    https://jsfiddle.net/jottin/ykx8cf9d/6/

    section {
      margin: 0;
      padding: 0;
      container-type: inline-size;
      container-name: section;
    }
    .wrapper {
      background-color: #eee;
      display: flex;
      align-items: center;
      padding: 1em;
    }
    .wrapper::after {
      content:"";
      clear: both;
      display: block;
    }
    .section-left {
      flex: 1;
      order: 1;
    }
    .section-right {
      background-color: #ddd;
      display: flex;
      flex-direction: column;
      align-content: center;
      justify-content: center;
      min-height: 30vh;
      min-width: 30vw;
      margin: 0 0 .5em .5em;
      padding: 0 2em;
      order: 2;
    }
    .section-right p {
      margin: 0 auto;
      text-align: center;
    }
    /* do the things when the things change size */
    @container section (width < 825px) {
      .wrapper {
        display: block !important;
      }
      .section-left {
        flex: none;
        width: 100%;
        container-type: normal;
      }
      .section-right {
        float: right;
      }
    }
    <section>
      <div class="wrapper">
        <div class="section-right">
          <p>Fixed height block.</p>
        </div>
        <div class="section-left">
          <p>The way they make shows is, they make one show. That show's called a pilot. Then they show that show to the people who make shows, and on the strength of that one show they decide if they're going to make more shows. Some pilots get picked and become television programs. Some don't, become nothing. She starred in one of the ones that became nothing. Your bones don't break, mine do. That's clear. Your cells react to bacteria and viruses differently than mine. You don't get sick, I do. That's also clear. But for some reason, you and I react the exact same way to water. We swallow it too fast, we choke. We get some in our lungs, we drown. However unreal it may seem, we are connected, you and I. We're on the same curve, just on opposite ends.</p>
        </div>
      </div>
    </section>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search