htmlcssflexboxtext-justify

Text doesn't get right aligned in display flex


Please note that it's not a simple "how do I get XXX" question. I can achieve the look I'm going for but I'm surprised on how. Hence, I fear that I'm doing it in a bad way.

As shown in this fiddle, the text inside the divs is left aligned and the CSS text-adjust isn't effective. I suspect it's because the width of the div somehow is void, because setting the width to e.g. 15% for each numeric cell causes the expected behavior.

Of course, setting the width collides with the very point of enjoying flex, so that's not the right way to go. I'm reaching the requested look by applying justify-content but my understanding is that controlling the alignment that way (from the container div imposing placement on the child element) is supposed to be applied on blocks (i.e. div'ish not span'ish stuff). Am I confused/mistaken in this regard?

I've googled it but drowned in gazillions of posts on how to align children in a flex container. The closest relative to my issue is here but I don't really understand how it differs from what I'm trying to achieve. Also, it doesn't give me understanding of where my thinking went wrong (undoubtedly it did but I expected it not to).

Is it recommended to always have a non-flex'ish div inside the cell'ish div to encapsulate the text mass inside it? It seems like bad HTML markup.

div.data-row-cell {
  display: flex;
  padding: 3px;
}

div.data-row-value {
  text-align: right;
  flex: 1;
}

<div class="data-row">

  <div *ngFor="let data of data"
       class="data-row-cell data-row-value">
    {{data}}
  </div>

</div>

Solution

  • In order to understand how flex works, we should do some testing. Therefore I will build some example.

    First its important to know that the default behaviour of a flex container direction is set to row. That means that all child elements inside a flex container will be placed next to each other as long as possible. Also we don't think in left or right anymore when using flexbox. We no think in main axis and cross axis.

    The main axis is the direction, the child elements are layed out. So per default it would be from left to right.

    The cross axis would then be from top to bottom.

    Next it is important to know, that by default the child elements inside the flex container only take as much space as needed.

    /* just for some nice looking */
    * {
      font-family: sans-serif;
      box-sizing: border-box;
      }
    
    .flex-container {
      display: flex;
      width: 100%;
      padding: 1rem;
      background: #666;
    }
    
    .flex-item {
      padding: 0.5rem;
      font-weight: bold;
      color: white;
    }
    
    .r {
      background: red;
    }
    
    .g {
      background: darkgreen;
    }
    
    .b {
      background: blue;
    }
    <div class="flex-container">
      <div class="flex-item r">blue</div>
      <div class="flex-item g">red</div>
      <div class="flex-item b">green</div>
    </div>

    Since now we know the default behaviour of the flex container and the child elements, lets see what we have to do to make text-alignment work.

    One way could be to stretch the child elements, so that the text inside has enough space for alignment.

    We could do this with the property flex-grow for the child elements:

    /* just for some nice looking */
    * {
      font-family: sans-serif;
      box-sizing: border-box;
      }
    
    .flex-container {
      display: flex;
      width: 100%;
      padding: 1rem;
      background: #666;
    }
    
    .flex-item {
      padding: 0.5rem;
      font-weight: bold;
      color: white;
    }
    
    .r {
      background: red;
    }
    
    .g {
      background: darkgreen;
    }
    
    .b {
      background: blue;
    }
    
    /* Updated content */
    .flex-item {
      flex-grow: 1;
    }
    
    .r {
      text-align: left;
    }
    
    .g {
      text-align: center;
    }
    
    .b {
      text-align: right;
    }
    <div class="flex-container">
      <div class="flex-item r">blue</div>
      <div class="flex-item g">red</div>
      <div class="flex-item b">green</div>
    </div>

    So in your case, we could remove the display: flex from the .data-row-cell class and just add some flex-grow: 1

    Please see my updated fiddle: https://jsfiddle.net/7wfm1s0j/

    I hope it helps :-)