Search code examples
htmlcssflexboxalignment

CSS - prevent text newlines from breaking flex alignment


I have the following CSS, which allows me to create a row that wraps based on screen size. If there is enough space all items appear on one row, else it wraps to the next row with proper alignment.

My problem is that I have a description text under each "square" div. If this text is only one line there is no issue, but if this text is 2 or more lines, the square it is beneath gets pushed up and is no longer aligned with it's siblings. How can I prevent this? I've included example code as a snippet, it's easiest to open as a full screen view to see what I'm talking about. I want the tops of the squares to always be aligned

.flex-row {
  display: flex;
  flex-direction: row;
  justify-content: space-evenly;
  flex-wrap: wrap;
  align-self: stretch;
}

.flex-col {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: center;
}

.sub-row {
  display: flex;
  flex-direction: row;
  justify-content: space-evenly;
  width: 300px;
}

.square {
  height: 250px;
  width: 250px;
  background-color: #900;
}
<body>
  <div class="flex-row">
    <div class="flex-col">
      <div class="square">
      </div>
      <div class="sub-row">
        <p>
          Placeholder text Placeholder text Placeholder text Placeholder text Placeholder text
        </p>
        <p>
          00
        </p>
      </div>
    </div>
        <div class="flex-col">
      <div class="square">
      </div>
      <div class="sub-row">
        <p>
          Placeholder text
        </p>
        <p>
          00
        </p>
      </div>
    </div>
        <div class="flex-col">
      <div class="square">
      </div>
      <div class="sub-row">
        <p>
          Placeholder text
        </p>
        <p>
          00
        </p>
      </div>
    </div>
        <div class="flex-col">
      <div class="square">
      </div>
      <div class="sub-row">
        <p>
          Placeholder text
        </p>
        <p>
          00
        </p>
      </div>
    </div>
  </div>
</body>

I've tried justifying the columns to flex-start and flex-end but that doesn't work. I've also messed with trying to use the align self property on the p element itself but I am unable to get the squares to be aligned if the text takes 2 or more lines.


Solution

  • Give align-items: flex-start to the flex-row (this overrides the default stretch behaviour).

    Your dyanmic text being below the squares makes things easy as when the flex items wrap, the wrapping flex lines will will adjust to the height of the dynamic text in the preceeding flex line.

    See demo below:

    .flex-row {
      display: flex;
      flex-direction: row;
      justify-content: space-evenly;
      flex-wrap: wrap;
      /* align-self: stretch;*/
      align-items: flex-start; /* ADDED */
    }
    
    .flex-col {
      display: flex;
      flex-direction: column;
      justify-content: flex-end;
      align-items: center;
    }
    
    .sub-row {
      display: flex;
      flex-direction: row;
      justify-content: space-evenly;
      width: 300px;
    }
    
    .square {
      height: 250px;
      width: 250px;
      background-color: #900;
    }
    <body>
      <div class="flex-row">
        <div class="flex-col">
          <div class="square">
          </div>
          <div class="sub-row">
            <p>
              Placeholder text Placeholder text Placeholder text Placeholder text Placeholder text
            </p>
            <p>
              00
            </p>
          </div>
        </div>
            <div class="flex-col">
          <div class="square">
          </div>
          <div class="sub-row">
            <p>
              Placeholder text
            </p>
            <p>
              00
            </p>
          </div>
        </div>
            <div class="flex-col">
          <div class="square">
          </div>
          <div class="sub-row">
            <p>
              Placeholder text
            </p>
            <p>
              00
            </p>
          </div>
        </div>
            <div class="flex-col">
          <div class="square">
          </div>
          <div class="sub-row">
            <p>
              Placeholder text
            </p>
            <p>
              00
            </p>
          </div>
        </div>
      </div>
    </body>