How can you use flexbox to vertically center text in a fixed-height div without overflowing above?

后端 未结 3 953
谎友^
谎友^ 2021-01-14 04:45

The first line of text in the third .box is raised above the top of the div and cut off. I would like it to appear the same as the second box (well actually ide

相关标签:
3条回答
  • 2021-01-14 05:28

    You can center the single line of text by simply wrapping it in a <span> and giving it a width.

    <div class='box'>
       <span>one line of text</span>
    </div>
    
    div.box > span { width: 100%; }
    

    OR, you can apply the justify-content property to the flex container:

    .box {
        display: flex;
        align-items: center; /* center vertically */
        justify-content: center; /* center horizontally */
        height: 40px;
        font-size: 16px;
        width: 150px;
        border: 1px solid black;
        margin-bottom: 40px;
        text-align: center;
        overflow-y: hidden;
    }
    

    In terms of adding ellipsis ("...") to overflow text, yes it's possible, but it's tricky with multi-line text.

    CSS has a text-overflow property that takes several values, including ellipsis. Unfortunately, ellipsis only works on single-line text.

    CSS doesn't provide a standard way to apply ellipsis to multi-line text. There are various workarounds, but they can be hit and miss depending on the method and the situation. See my answer here for more details: Applying Ellipsis to Multiline Text

    0 讨论(0)
  • 2021-01-14 05:40

    Question 1/2

    Yes! You can do it with flexbox:

    .box {
      /* Firefox */
      display: -moz-flex;
      -moz-justify-content: center;
      -moz-align-items: center;
    
      /* IE */
      display: -ms-flex;
      -ms-justify-content: center;
      -ms-align-items: center;
    
      /* Chrome | Safari */
      display: -webkit-flex;
      -webkit-justify-content: center;
      -webkit-align-items: center;
    
      /* Modern browsers */
      display: flex;
      justify-content: center;
      align-items: center;
    
      height: 40px;
      width: 150px;
      overflow: hidden;
      border: 1px solid black;
      margin-bottom: 40px;
      font-size: 16px;
      text-align: center;
    }
    
    .truncate {
      white-space: nowrap;
      overflow: hidden;
      -ms-text-overflow: ellipsis;  /* IE */
      -o-text-overflow: ellipsis;   /* Opera */
      text-overflow: ellipsis;      /* Other browsers */
    }
    <div class='box'>
      <p class="truncate">one line of text<p>
    </div>
    
    <div class='box'>
      <p class="truncate">two lines of text lorem ipsum<p>
    </div>
    
    <div class='box'>
      <p class="truncate">thre lines of text lorem ipsum sin dolor whatever etc<p>
    </div>

    If you like to use Sass/SCSS and Compass your stylesheet will be like:

    @import 'compass';
    
    .box {
      @include flexbox((
        display: flex,
        justify-content: center,
        align-items: center 
      ), 1 2 3);
      height: 40px;
      width: 150px;
      overflow: hidden;
      border: 1px solid black;
      margin-bottom: 40px;
      font-size: 16px;
      text-align: center;
    }
    
    .truncate {
      @include ellipsis();
    }
    

    Question 3

    Javascript is required only if you want to truncate your text in multiple lines (on second/third line and so on..) So if it's a single line, CSS is the right way. Otherwise use Succinct

    Question 4

    You don't see text centered because your .box has display: flex property. Remove it and you will see it centered

    0 讨论(0)
  • 2021-01-14 05:43

    When align-self computes to center, the flex item is centered in the cross axis within the line.

    That's problematic if the flex item is bigger than the flex container, because it will overflow it both from above and below. And in case overflow is not visible, the upper part will be cut.

    To avoid this, you can center by using auto margins:

    .box {
      display: flex;
      height: 40px;
      width: 150px;
      overflow: auto;
      border: 1px solid black;
      margin-bottom: 20px;
      font-size: 16px;
      text-align: center;
    }
    .box > div {
      margin: auto;
    }
    <div class='box'>
      <div>one line of text</div>
    </div>
    <div class='box'>
      <div>two lines of text lorem ipsum</div>
    </div>
    <div class='box'>
      <div>thre lines of text lorem ipsum sin dolor whatever etc</div>
    </div>

    Note margin: auto needs to be added to each flex item. However, you can't select the anonymous flex item which wraps contiguous run of texts in the flex container. Therefore, I wrapped the text in div elements, which can be selected.

    If you don't want to alter the HTML, you can use pseudo-elements.

    .box {
      display: flex;
      flex-direction: column;
      height: 40px;
      width: 150px;
      overflow: auto;
      border: 1px solid black;
      margin-bottom: 40px;
      font-size: 16px;
      text-align: center;
    }
    .box::before, .box::after {
      content: '';
      margin-top: auto;
    }
    <div class='box'>
      one line of text
    </div>
    <div class='box'>
      two lines of text lorem ipsum
    </div>
    <div class='box'>
      thre lines of text lorem ipsum sin dolor whatever etc
    </div>

    0 讨论(0)
提交回复
热议问题