13

So I have the following Fiddle that has set an ellipsis in a text into two lines. Then I want to have a 'More' link inline with the text.

http://jsfiddle.net/csYjC/2876/

So if our text has more than two lines, it should look like this:

enter image description here

That's correct. However:

enter image description here

That's not correct (should be inline with the text).

Code is like follows:

<div class="text">
  <div>Lorem ipsum dolor sit amet, Lorem Lorem ipsum dolor sit amet, Lorem ipsum dolor sit amet, Lorem Lorem i</div>
  <a href="#">More</a>
</div>

And the css:

.text{
   display: inline;
   overflow: hidden;
   text-overflow: ellipsis;
   display: -webkit-box;
   line-height: 24px;     /* fallback */
   max-height: 48px;      /* fallback */
   -webkit-line-clamp: 2; /* number of lines to show */
   -webkit-box-orient: vertical;
}

.text a {
    position: absolute;
}

I guess must be easy... Thank you in advance.

Ferran Negre
  • 3,712
  • 3
  • 34
  • 56

8 Answers8

0

The div inside of .text is still being displayed as a block element. Use this to fix:

.text > div { display: inline; }

http://jsfiddle.net/csYjC/2880/

Adam Fratino
  • 1,245
  • 10
  • 23
  • Hi, that put the "More" inline with the text in a correct way. But notice that if you resize the windows, the More is not in the right place (gets bit crazy). Moreover, I just realized that in Firefox, ellipsis is not working. – Ferran Negre Sep 23 '14 at 19:35
  • @FerranNegre Change to `.text a{position: relative;}` http://jsfiddle.net/hegsgwrv/ – OJFord Sep 23 '14 at 19:39
  • Hi. I tried that. Still not working. Now is always inline with the text (when I want it below when two lines are completed). If you resize it a lot, you will see that the 'More' link dissapears. And still not ellipsis with Firefox... that might be another thing. – Ferran Negre Sep 23 '14 at 19:42
  • @FerranNegre this won't work in Firefox because you are using the `-webkit` prefix only. Firefox doesn't use webkit. – Adam Fratino Sep 23 '14 at 19:44
  • Unfortunately I'm not sure how to solve this without using Javascript. I assumed forcing a height on the inner div would solve your problem, but the clamp is overriding it. So far it seems Ollie's addition to my answer is the best possibility. – Adam Fratino Sep 23 '14 at 20:00
  • Ollie's solution does not show the More button when you re-size it very small (also not putting the link under when the text fits the two line). And there is also the Firefox problem... easy way to do it in JS? – Ferran Negre Sep 23 '14 at 20:13
0

DEMO: http://jsbin.com/hatuv/1/edit

<div class="text">
    <p>Lorem ipsum dolor sit amet, Lorem Lorem ipsum dolor sit amet, Lorem ipsum dolor sit amet, Lorem Lorem i </p>  <a href="#">More</a>
    </div>

CSS

.text {
    overflow: hidden /* just for clearing */
}
.text p {
    display: inline-block;
    text-overflow: ellipsis;
    width: 100%;
    white-space: nowrap;
    overflow: hidden;
    margin-top: 0;
    box-sizing: border-box;
    padding-right: 40px;
    margin-right: -40px;
}
.text a {
    float: right
}
Christina
  • 34,296
  • 17
  • 83
  • 119
  • That looks nice. Is it also possible to make the "More" button going under the text when the text is already fitting all the line? Moreover, you are using only 1 line, I am trying with 2 lines. – Ferran Negre Sep 23 '14 at 19:48
  • I couldn't get multi-line to work without a jQuery script, that's what I ended up using. jQuery Succinct plugin – Christina Sep 23 '14 at 19:49
  • @FerranNegre -- Firefox and multi-line gave me issues so I gave up and ended up using jQuery Succinct plugin – Christina Sep 23 '14 at 19:50
  • Do you have an example of it? Also with the "More" link? Just wanted to be inline the text when lines don't fit all space and under when they do. I thought could be done in pure CSS. – Ferran Negre Sep 23 '14 at 19:52
  • This is the only thing I found that works in Firefox too, it's a pain to implement and so I opted for jQuery, which does not reflow on resize, only on load. I don't care since barely anyone except for testers are sizing their viewports all over the place. http://www.mobify.com/blog/multiline-ellipsis-in-pure-css/ – Christina Sep 23 '14 at 19:56
  • I see.. still that example has no 'More' button. I matter about 'resizing' cause it must be responsive. – Ferran Negre Sep 23 '14 at 19:59
0

a pure css method base on -webkit-line-clamp, and you can custom the ...more content like a boss:

@-webkit-keyframes ellipsis {/*for test*/
    0% { width: 622px }
    50% { width: 311px }
    100% { width: 622px }
}
.ellipsis {
    max-height: 40px;/* h*n */
    overflow: hidden;
    background: #eee;

    -webkit-animation: ellipsis ease 5s infinite;/*for test*/
    /**
    overflow: visible;
    /**/
}
.ellipsis .content {
    position: relative;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-box-pack: center;
    font-size: 50px;/* w */
    line-height: 20px;/* line-height h */
    color: transparent;
    -webkit-line-clamp: 2;/* max row number n */
    vertical-align: top;
}
.ellipsis .text {
    display: inline;
    vertical-align: top;
    font-size: 14px;
    color: #000;
}
.ellipsis .overlay {
    position: absolute;
    top: 0;
    left: 50%;
    width: 100%;
    height: 100%;
    overflow: hidden;

    /**
    overflow: visible;
    left: 0;
    background: rgba(0,0,0,.5);
    /**/
}
.ellipsis .overlay:before {
    content: "";
    display: block;
    float: left;
    width: 50%;
    height: 100%;

    /**
    background: lightgreen;
    /**/
}
.ellipsis .placeholder {
    float: left;
    width: 50%;
    height: 40px;/* h*n */

    /**
    background: lightblue;
    /**/
}
.ellipsis .more {
    position: relative;
    top: -20px;/* -h */
    left: -50px;/* -w */
    float: left;
    color: #000;
    width: 50px;/* width of the .more w */
    height: 20px;/* h */
    font-size: 14px;

    /**
    top: 0;
    left: 0;
    background: orange;
    /**/
}
<div class='ellipsis'>
    <div class='content'>
        <div class='text'>text text text text text text text text text text text text text text text text text text text text text </div>
        <div class='overlay'>
            <div class='placeholder'></div>
            <div class='more'>...<a href="http://hai.li">more</a></div>
        </div>
    </div>
</div>
Defims
  • 233
  • 1
  • 2
  • 11
0

well using flexbox make it simple. Try this around

.text {
  display: flex;
  > div {
    flex: 0 0 40%;
    text-overflow: ellipsis;
    white-space: nowrap;
    overflow: hidden;
  }
}

https://codepen.io/baagii95/pen/byeNqZ

btw i used sass. If you want in css version try this.

.text {
  display: flex;
}

.text > div {
  flex: 0 0 40%;
  text-overflow: ellipsis;
  white-space: nowrap;
  overflow: hidden;
}
batgerel.e
  • 837
  • 1
  • 10
  • 31
0

I used canvas to get the width of the string occupied by the content in the div(as for different fonts there will be slight differences in the measurement).Here i calculated the number of lines in which the content is divided into by dividing the width of string(i.e content.textContent) by div content's width

The moment it reaches above or equal to 3 the display property of anchor tag would change to block and when it is less than 3 it would revert back to inline.

OUTPUT:

enter image description here

This will work

var content = document.getElementsByClassName('content')[0];
var more = document.getElementsByClassName('more');

var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
var font = "30px times new roman";
context.font = font;
var text = content.textContent;
var width = context.measureText(text).width;
var w = Math.ceil(width);



window.onload = function() {
  change_more();
}

window.onresize = function() {
  change_more();
}


function change_more() {
  var check = Math.ceil(w / content.offsetWidth);

  if (check > 2) {
    more[0].style.display = "none";
    more[1].style.display = "block";
    content.style.textOverflow = "ellipsis";
  } else {
    more[0].style.display = "inline";
    more[1].style.display = "none";
    content.style.textOverflow = "clip";
  }
}
* {
  margin-left: 0px;
  padding: 0px;
}

.content {
  overflow: hidden;
  display: -webkit-box;
  /* fallback */
  font-size: 30px;
  max-height: 90px;
  /* fallback */
  -webkit-line-clamp: 2;
  /* number of lines to show */
  -webkit-box-orient: vertical;
}

a {
  font-size: 30px;
}
<div class="text">
  <div class="content" style="">Lorem ipsum dolor sit amet, Lorem Lorem ipsum dolor sit amet, Lorem ipsum dolor sit amet, Lorem Lorem Lorem ipsum dolor sit amet, Lorem Lorem ipsum dolor sit amet, <a href="#/" class="more">MORE</a></div>
  <a href="#/" class="more">MORE</a>
</div>
ac_mmi
  • 2,302
  • 1
  • 5
  • 14
0

Well, here's a kind of a funny solution with pure CSS using pseudo elements. http://jsfiddle.net/j8ekzvLq/

.text {
   display: inline;
   overflow: hidden;
   text-overflow: ellipsis;
   display: -webkit-box;
   line-height: 24px;     /* fallback */
   max-height: 48px;      /* fallback */
   -webkit-line-clamp: 2; /* number of lines to show */
   -webkit-box-orient: vertical;
   position: relative;
   padding-bottom: 24px;
}

.text::before {
    content: "";
    position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
    height: 24px;
    background-color: #fff;
    z-index: 1;
}

.text div {
    background-color: #fff;
    display: inline;
    position: relative;
}

.text div::after {
    content: "";
    background-color: #fff;
    position: absolute;
    bottom: -24px;
    left: 0;
    width: 100%;
    height: 24px;
    z-index: 2;
}

.text a::before {
    content: "More";
    position: absolute;
    bottom: 0;
    left: 0;
    text-decoration: underline;
    z-index: 1;
}
Adam
  • 79
  • 9
0

Unfortunately, the problem cannot be solved without javascript. It is necessary to calculate link position. One of the implementation options can be as follows (used jquery for convenience):

positionMore();
$(window).on('resize', positionMore);

function positionMore(){
    $('.text').each(function(){
        const t = $(this);
        const container = t.closest('.container-text');
        const more = t.find('.text-more');
        if(
            Math.ceil(more.position()?.left + more.width()) > t.width() ||
            Math.ceil(more.position()?.top) >= t.height()
        ){
            container.addClass('active');
        }else{
            container.removeClass('active');
        }
    })
}
.container-text > .text-more {
  display: none;
}
.container-text.active > .text-more {
  display: inline;
}
.container-text.active .text .text-more {
  opacity: 0;
}
.text {
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  line-height: 24px;
  /* fallback */
  max-height: 48px;
  /* fallback */
  -webkit-line-clamp: 2;
  /* number of lines to show */
  -webkit-box-orient: vertical;
  position: relative;
  font-size: 18px;
}
.text .text-more {
  position: absolute;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container-text">
  <div class="text">
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Alias eveniet sequi quos accusantium fuga corrupti voluptate nihil reprehenderit voluptatem tenetur, et modi nisi, consequatur dolore fugit iusto perferendis consequuntur illum, nemo esse natus fugiat? Et, ratione? Asperiores sequi, eaque ullam mollitia quos quidem vitae. Nihil velit provident accusamus est corporis nobis harum fugiat!&nbsp;
    <a href="#" class="text-more">More</a>
  </div>
  <a href="#" class="text-more">More</a>
</div>
imhvost
  • 4,750
  • 2
  • 8
  • 10
-2

Just add to div some class and give it display:inline; :

<div class="text">
    <div class="loremclass">Lorem ipsum dolor sit amet, Lorem Lorem ipsum dolor sit amet, Lorem ipsum dolor sit amet, Lorem Lorem ipsum dolor sit amet</div>
    <a href="#">More</a>
</div>

and

body {
   margin: 20px;
}

.text{
   display: inline;
   overflow: hidden;
   text-overflow: ellipsis;
   display: -webkit-box;
   line-height: 24px;     /* fallback */
   max-height: 48px;      /* fallback */
   -webkit-line-clamp: 2; /* number of lines to show */
   -webkit-box-orient: vertical;
}

.text a {
    position: absolute;
}
.loremclass{display:inline;}
  • That does not put the 'More' link inline the text when the text is not fitting all 2 lines. – Ferran Negre Sep 23 '14 at 19:53
  • Yea now is like we tried before. The 'More' gets in crazy position when is not inline with the text (re-size the window to see it). – Ferran Negre Sep 23 '14 at 19:55
  • This is a duplicate of my answer except you've added an arbitrary class for the inner div. – Adam Fratino Sep 23 '14 at 19:57
  • @88 MPG and that is the reason you gived me -? I didn't look at you solution – developppper Sep 23 '14 at 19:59
  • Yes, that's exactly why. In the future, please read all current answers before posting an answer. If someone has posted your solution and you have something to add, comment on the existing answer. If you agree with the answer, vote for it. – Adam Fratino Sep 23 '14 at 20:02
  • I accidentally downvoted it please edit the question –  Jan 12 '21 at 03:49