3

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 ideally like the second box plus a ...).

  1. Can this be done with flexbox?
  2. If not, can it be done with other CSS?
  3. If not, what's the best way to do it with JS?
  4. And on a separate note, why isn't the first box's text center-aligned?

enter image description here

http://codepen.io/loren/pen/ojxORN

<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>

.box 
  height 40px
  font-size 16px
  width 150px
  border 1px solid black
  margin-bottom 40px
  display flex
  align-items center
  text-align center
  overflow-y hidden
Loren
  • 13,903
  • 8
  • 48
  • 79
  • 1
    I think the reason the single line is left-aligned is because the flex-direction property has its default value of row, so the content of each box becomes a single flex item shrunk as small (narrow) as possible then laid out horizontally from the left. With longer text the item is forced to the full available width, and the text is then centered within that (due to text-align). Setting `flex-direction: column` changes that: the flex items then expand horizontally... but not vertically, so you lose the vertical centering. – deltab Sep 19 '15 at 02:23
  • 1
    In the first box the text is centered relatively to the anonymous flex item which wraps it, but that flex item is not centered relatively to the flex container. You can fix it using `justify-content: center` on the flex container. If you could select the flex item, you could also use `flex-grow: 1` or `width: 100%` to make it grow to cover all the container, or use `margin: 0 auto` to push it to the middle. – Oriol Sep 19 '15 at 20:09

3 Answers3

5

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>
Oriol
  • 274,082
  • 63
  • 437
  • 513
1

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

LorenzoD
  • 91
  • 5
  • Thanks! Is there any way with CSS to get the second and third boxes to display two lines of text? (and only the third box with ellipses) – Loren Sep 19 '15 at 04:18
  • You can't truncate multiple lines in CSS, you have to use Succinct ;) – LorenzoD Sep 19 '15 at 09:36
  • Thanks, how can you get the second and third boxes to display two lines of text without ellipses? – Loren Sep 19 '15 at 16:33
1

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

Community
  • 1
  • 1
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701