csslayoutflexboxflexboxgrid

Is this flexbox layout possible without adding more to the HTML structure?


I was wondering if the layout I draw on the following image is possible using flexbox and this HTML structure:

<div class="box">
    <img src="url..." alt="" />
    <h5>Lorem Ipsum</h5>
    <p>Lorem Ipsum Dolor Sit Amet...</p>
</div>

It would be great if this could be done with flexbox and without adding more boxes inside.

Flexbox Layout


Solution

  • For fixed image width and height, it's possible. The main idea is in the following snippet.

    .box {
      display: flex;
      flex-direction: column;
      flex-wrap: wrap;
      align-content: space-between;
      height: 300px;
    }
    
    .img {
        width: 300px; height: 300px;
    }
    
    h5, p {
      /* 100% - image width - margin between */
      width: calc(100% - 300px - 16px); 
    }
    

    Since the height of the parent is the same as the height of the image, the content overflows and gets wrapped to the right. Then we have to manually set the width because it's otherwise going to 100% of the parent.

    .box {
      background-color: #ddd;
      padding: 16px;
      margin-bottom: 24px;
      display: flex;
      flex-direction: column;
      flex-wrap: wrap;
      height: 300px;
      align-content: space-between;
    }
    
    .img {
      background-color: #333;
      color: #ddd;
      width: 300px;
      height: 300px;
    }
    
    h5, p {
      padding: 0;
      margin: 0;
      background-color: #ccc;
      /* 100% - image width - margin between */
      width: calc(100% - 300px - 16px); 
    }
    
    h5 {
      font-size: 18px;
      margin-bottom: 8px;
    }
    
    .box:nth-child(even) .img {
      order: 3;
    }
    <div class="box">
        <div class="img">&lt;img&gt;</div>
        <h5>Lorem Ipsum</h5>
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur mollis cursus hendrerit. Suspendisse potenti. Aliquam posuere ex ut lacus euismod dictum. Proin et ligula posuere leo viverra tempor a in tellus</p>
    </div>
    
    <div class="box">
        <div class="img">&lt;img&gt;</div>
        <h5>Lorem Ipsum</h5>
        <p>Lorem Ipsum Dolor Sit Amet...</p>
    </div>
    
    <div class="box">
        <div class="img">&lt;img&gt;</div>
        <h5>Lorem Ipsum</h5>
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur mollis cursus hendrerit. Suspendisse potenti. Aliquam posuere ex ut lacus euismod dictum. Proin et ligula posuere leo viverra tempor a  </p>
    </div>

    Full-height paragraph

    You might want to extend your paragraph all the way to the bottom (maybe add some links there). It's easy to extend it so you can turn p into flexbox to snap something to the bottom, for example (this example not in the demo below, you can only notice this by the gray background).

    .box {
      /* ... */
      justify-content: space-between;
    }
    
    p {
      flex-grow: 1;
    }
    

    .box {
      background-color: #ddd;
      padding: 16px;
      margin-bottom: 24px;
      display: flex;
      flex-direction: column;
      flex-wrap: wrap;
      height: 300px;
      align-content: space-between;
      justify-content: space-between;
    }
    
    .img {
      background-color: #333;
      color: #ddd;
      width: 300px;
      height: 300px;
    }
    
    h5, p {
      padding: 0;
      margin: 0;
      background-color: #ccc;
      /* 100% - image width - margin between */
      width: calc(100% - 300px - 16px); 
    }
    
    h5 {
      font-size: 18px;
      margin-bottom: 8px;
    }
    
    p {
      flex-grow: 1;
    }
    
    .box:nth-child(even) .img {
      order: 3;
    }
    <div class="box">
        <div class="img">&lt;img&gt;</div>
        <h5>Version 2</h5>
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur mollis cursus hendrerit. Suspendisse potenti. Aliquam posuere ex ut lacus euismod dictum. Proin et ligula posuere leo viverra tempor a in tellus</p>
    </div>
    
    <div class="box">
        <div class="img">&lt;img&gt;</div>
        <h5>Lorem Ipsum</h5>
        <p>Lorem Ipsum Dolor Sit Amet...</p>
    </div>
    
    <div class="box">
        <div class="img">&lt;img&gt;</div>
        <h5>Lorem Ipsum</h5>
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur mollis cursus hendrerit. Suspendisse potenti. Aliquam posuere ex ut lacus euismod dictum. Proin et ligula posuere leo viverra tempor a in tellus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur mollis cursus hendrerit. Suspendisse potenti. </p>
    </div>

    Both versions above breaks when the text cannot fit (try changing browser window size).

    Doesn't show all, but never breaks

    You can set the max-height for the paragraph if you don't want it to break and clip the text which cannot fit with overflow: hidden.

    p {
      max-height: 250px;
      overflow: hidden;
    }
    

    .box {
      background-color: #ddd;
      padding: 16px;
      margin-bottom: 24px;
      display: flex;
      flex-direction: column;
      flex-wrap: wrap;
      height: 300px;
      align-content: space-between;
      justify-content: space-between;
    }
    
    .img {
      background-color: #333;
      color: #ddd;
      width: 300px;
      height: 300px;
    }
    
    h5, p {
      padding: 0;
      margin: 0;
      background-color: #ccc;
      /* 100% - image width - margin between */
      width: calc(100% - 300px - 16px); 
    }
    
    h5 {
      font-size: 18px;
      margin-bottom: 8px;
    }
    
    p {
      flex-grow: 1;
    }
    
    .box:nth-child(even) .img {
      order: 3;
    }
    
    p {
      max-height: 250px;
      overflow: hidden;
    }
    <div class="box">
        <div class="img">&lt;img&gt;</div>
        <h5>Version 3</h5>
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur mollis cursus hendrerit. Suspendisse potenti. Aliquam posuere ex ut lacus euismod dictum. Proin et ligula posuere leo viverra tempor a in tellus</p>
    </div>
    
    <div class="box">
        <div class="img">&lt;img&gt;</div>
        <h5>Lorem Ipsum</h5>
        <p>Lorem Ipsum Dolor Sit Amet...</p>
    </div>
    
    <div class="box">
        <div class="img">&lt;img&gt;</div>
        <h5>Lorem Ipsum</h5>
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur mollis cursus hendrerit. Suspendisse potenti. Aliquam posuere ex ut lacus euismod dictum. Proin et ligula posuere leo viverra tempor a in tellus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur mollis cursus hendrerit. Suspendisse potenti. Aliquam posuere ex ut lacus euismod dictum. Proin et ligula posuere leo viverra tempor a in tellus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur mollis cursus hendrerit. Suspendisse potenti. Aliquam posuere ex ut lacus euismod dictum. Proin et ligula posuere leo viverra tempor a in tellus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur mollis cursus hendrerit. Suspendisse potenti. Aliquam posuere ex ut lacus euismod dictum. Proin et ligula posuere leo viverra tempor a in tellus. </p>
    </div>