user1328021
user1328021

Reputation: 9850

Make a DIV expandable

I have a div and it contains a paragraph that is populated dynamically. Sometimes the paragraph is 20 lines, and sometimes it is 3.

I want to set a height limit upon which if the div is larger than this (due to there being more lines in the paragraph) it will shrink it down to only show 3 lines of text and then have a "View More" button that will expand and/or collapse the div upon request to show the remaining lines in the paragraph.

<div class="hero-unit">
  <h1>Product Description</h1>
  <p>{{paragraph}}</p>
</div>

Any tips on how I can do this as easily as possible?

Upvotes: 4

Views: 28135

Answers (8)

tremendows
tremendows

Reputation: 4382

If you're available to use bootstrap, take a look at bootstrap.javascript.collapse and you'll find and easy fast solution like the one I've wroten: http://getbootstrap.com/javascript/#collapse

<div class="collapse" id="collapseExample">
<div class="hero-unit collapse" id="collapseHeroeUnit">
  <h1>Product Description</h1>
  <p>{{paragraph}}</p>
</div>
<button class="btn btn-primary" type="button" data-toggle="collapse" data-target="#collapseExample" aria-expanded="false" aria-controls="collapseExample">
  Expand the div
</button>

Upvotes: 0

Pratik Patel
Pratik Patel

Reputation: 1355

Here is the solution that uses pure javascript, html and css.

Problem with many answers is that even if the text is less than the limit, it is given the maximum height. Thus the element containing text will always have the fixed height, even when not required.

This code does not use the maximum height parameter when not necessary i.e. if the text is not exceeding the limit then it renders text with default height and not the fixed height. The text is applied the maximum height only when text exceeds the limit. Similarly, the "show more" is displayed only when required.

Here is the demo

HTML

<div class="hero-unit">
  <h1>Product Description</h1>
    <div id='tagList'>this is really long text; this is really long text ; this is really long text ; this is really long text ; this is really long text ; this is really long text ; this is really long text ; this is really long text ; this is really long text ; this is really long text ; this is really long text ; this is really long text ; this is really long text ; this is really long text ; this is really long text ; this is really long text ; this is really long text ; this is really long text ; this is really long text ; this is really long text ; this is really long text ; this is really long text ; this is really long text ; this is really long text ; this is really long text ; this is really long text ; this is really long text ; this is really long text ; this is really long text ; this is really long text ; this is really long text ; this is really long text ; this is really long text ; 
    </div>   

    <div id="toggleExpandBtn" style = "text-align:right">More</a>
</div>

Javascript

window.onload = function(){
    var tagList = document.getElementById('tagList')
    var style = window.getComputedStyle(tagList)
    var lineheight = parseInt(style.getPropertyValue('line-height'));
    var height = parseInt(style.getPropertyValue('height'));
    tagList.style.height = 'auto';
    if (height < lineheight*3) {
        document.getElementById('toggleExpandBtn').style.display = 'none';
    }
    else{
        tagList.style.height = lineheight*3 + 'px';
        document.getElementById('toggleExpandBtn').style.display = 'inline';
    }
}

document.getElementById('toggleExpandBtn').addEventListener('click',function(){
     var tagList = document.getElementById('tagList')
     var style = window.getComputedStyle(tagList)
     var lineheight = parseInt(style.getPropertyValue('line-height'));
     var height = parseInt(style.getPropertyValue('height'));
     if (height == lineheight*3) {
        tagList.style.height = 'auto';
        document.getElementById('toggleExpandBtn').textContent = 'Less';
     } else {
        tagList.style.height = lineheight*3 + 'px';
        document.getElementById('toggleExpandBtn').textContent = 'More';
     }
});

CSS

#tagList {
    line-height: 18px;
    overflow: hidden;
}

Upvotes: 0

isherwood
isherwood

Reputation: 61143

http://jsfiddle.net/zRjdD/2/

$('.hero-unit').each(function () {
    var ht = $(this).height();
    if (ht > '200') {
        var button = $('<span class="btn">Show all</button>');
        $(this).children('p').css('height', '50px');
        $(this).append(button);
    }
});

$('.btn').on('click', function () {
    $(this).hide();
    $(this).prev('p').css('height', 'auto');
});

Upvotes: 0

melhosseiny
melhosseiny

Reputation: 10154

If you want exactly 3 lines, notice that this means that the height should be 3*line-height. You could then do this:

HTML

<div class="hero-unit">
  <h1>Product Description</h1>
  <p>...</p>
  <a>More</a>
</div>

CSS

p {
    line-height: 18px;
    height: 54px;
    overflow: hidden;
}

overflow: hidden will hide content that exceed the container boundaries.

jQuery

We then toggle the height constraint.

$('a').click(function() {
    var p = $('a').prev('p')
    var lineheight = parseInt(p.css('line-height'))
    if (parseInt(p.css('height')) == lineheight*3) {
       p.css('height','auto');
       $(this).text('Less')
    } else {
       p.css('height',lineheight*3+'px');
       $(this).text('More')
    }
});

See demo.

Upvotes: 5

ThinkingStiff
ThinkingStiff

Reputation: 65391

You can do this with some simple Javascript (no jQuery needed) and some CSS classes. To simplify design, assume a set min and max height.

Demo: jsFiddle

Script:

document.getElementById( 'slide' ).addEventListener( 'click', function() {
    var body = document.getElementById( 'slide-body' );
    if( body.className == 'expanded' ) {
        body.className = '';
        document.getElementById( 'more' ).textContent = 'more...';
    } else {
        body.className = 'expanded';
        document.getElementById( 'more' ).textContent = 'less...';
    };
} );

HTML:

<div id="slide">
    <div id="slide-body">
    A really long paragraph. A really long paragraph. A really long paragraph. A really long paragraph. A really long paragraph. A really long paragraph. A really long paragraph. A really long paragraph. A really long paragraph. A really long paragraph. A really long paragraph. A really long paragraph. A really long paragraph. A really long paragraph. A really long paragraph. A really long paragraph. A really long paragraph. A really long paragraph. A really long paragraph. A really long paragraph. A really long paragraph. A really long paragraph. A really long paragraph. 
    </div>
    <div id="more">more...</div>
</div>

CSS:

#slide {
    border: 1px solid black;
}
#slide-body{
    height: 55px;    
    overflow: hidden;
    transition:             height 500ms ease;
        -moz-transition:    height 500ms ease;
        -ms-transition:     height 500ms ease;
        -o-transition:      height 500ms ease;
        -webkit-transition: height 500ms ease;
}
.expanded {
    height: 150px !important;
}
#more {    
    cursor: pointer;
    text-align: right;
}

Upvotes: 4

Praveen Kumar Purushothaman
Praveen Kumar Purushothaman

Reputation: 167250

The simple solution would be having a fixed height.

<div class="hero-unit">
  <h1>Product Description</h1>
  <p>{{paragraph}}</p>
</div>

As you are sure that there will be at least one <h1> (ps: it is not a good idea to have multiple <h1> tags) and <p>, we can be sure of the height would be roughly about, say 100px.

The first simple way would be setting a fixed height:

.hero-unit {height: 100px; overflow: hidden;}

This would abruptly cut the contents. If you need something better, you can go ahead with placing an image, which fades from transparent to white. Say, something like this:

.hero-unit {height: 100px; overflow: hidden; position: relative;}
.hero-unit img.fade {position: absolute; bottom: 0;}

So, this technique will not cut the contents abruptly, but will give a smooth fade effect.

The final one would be using plugins. You can choose either you show the full content and give a scrollbar, or showing it after some user interactions. If you prefer the first one, go for jScrollPane. Or, if you prefer the latter, go for either dotdotdot, or the below script might help:

var p = $('.hero-unit p');
var divh = $('.hero-unit').height();
while ($(p).outerHeight() > divh) {
    $(p).text(function (index, text) {
        return text.replace(/\W*\s(\S)*$/, '...');
    });
}

Upvotes: 0

PhazingAzrael
PhazingAzrael

Reputation: 741

Personally I find the best method is to set a max-height and overflow:auto;. This way it keeps it small enough to just fit the three lines, or easily expand to a set height to have proper accommodation for the rest of the paragraph. Hope this helps.

Upvotes: 0

StackExchange User
StackExchange User

Reputation: 1220

You might want to try something along the lines of what adnbutton.com did to view the code. I think that's what you want to do. If you only want to do this when there is more than 3 lines, you'd have to do this with jQuery or the like.

Upvotes: 0

Related Questions