14

I'm building an e-commerce website. All products are displayed in separate divs. I have one problem: In each product's Div, I want to display a part of the product description. When the product description is longer than the div, it simply displays the description over the edges of the div. I have tried to put the problem in a picture: enter image description here

Now, as you can see in the picture, I would like to solve three problems:

  • I want to limit the text to fit the div.
  • I want to make sure this is not done somewhere in the middle of a word
  • I want to add an "read more" link at the end of the description preview.

Now I have seen this a lot in other e-commerce websites, but after looking for hours I have not found a clear description on how to do this.

This is the code that generates all the product cards:

for($i = 0; $i<$numberOfItems; $i++) {
    //echo $output_array[$i]["itemName"];
    echo '<a href="/itemDetails.php?itemCode=';echo $output_array[$i]["itemCode"]; echo '&itemName='; echo $output_array[$i]["itemName"];echo'">
    <div id="item" style="background-color: transparent; width:243px;height:auto;float:left; margin-left:20px; margin-top:20px; max-width:800px; display:inline-block;">
    <div id="itemPicture" class="itemImage"; > 
    <div id="price" class="pricetag">
    <div id="priceText" class="priceText";>';
    echo "€".$output_array[$i]["itemPrice"];

    echo '</div></div>';
    $imageSource = "http://www.imagine-app.nl/ProductImages/".$output_array[$i]["firstImage"].".jpg";
    echo '<img src="';echo $imageSource; echo'" style="max-width:100%; border:0px;"> 

    </div>

    <div id="itemName" class="itemName"">';
        echo $output_array[$i]["itemName"];
    echo '</div>'; ?>

    <div id="itemDescription" class="itemDescription" style="height:">
    <?  echo $output_array[$i]["itemDescription"];
    echo '</div>';
    ?>

    <?php
    echo '<div id="itemComment" class="itemComment"">
          Lees verder! 
    </div>

</div></a>';
}

Does anyone know how to solve these problems? Any help would be much appreciated. Thanks in advance!

UPDATE

Answers have led me to "Line Clamping", which seem to be css or javascript codes that perform the task I need. Implementing both the javascript code provided by musically_ut and the css from Unamata Sanatarai bring me to this: enter image description here

I can say that progress has been made, as the text does not just over cross the borders of my div. I only have 2 problems left:

  • The text clamped text is for some reason running through underneath the footer of my product card
  • It sometimes interrupts a word. (it is dutch. the word that should be there is "beschikt".)

any suggestions are welcome

PS: The second screenshot was taken with the css implementation, as the javascript implementation only worked on one product (probably because product cards are divs generated by a php 'for' loop)

Vadim Kotov
  • 7,103
  • 8
  • 44
  • 57
Joris416
  • 4,410
  • 4
  • 26
  • 47

3 Answers3

9

What you want is multiple line clamping. Unfortunately, CSS so far only allows clamping of the first line of text. Webkit/Opera allow for clamping of multiple lines, but I suspect it will not help you much here.

There are several workarounds (even one which is all-CSS) described here: http://css-tricks.com/line-clampin/

The most reliable, however, seems to be using javascript for the task: Clamp.js.

musically_ut
  • 33,232
  • 8
  • 87
  • 102
  • Hi! Thanks for your reply! I have updated the question with the progress made so far. I have an issue with implementing the javascript code: It only works on one product card. This is probably because all divs are generated by a php 'for' loop, and thus have the same id property. do you know a workaround for this? – Joris416 Apr 13 '14 at 13:15
  • 1
    @Imaginedigital Use a `class` attribute in the `php` for loop instead of `id`? Also, they should not have the same `id`, it would render the HTML illegal. – musically_ut Apr 13 '14 at 13:37
  • I can make that php gives the div the name of the product as id, that would be fine I think? thanks. Also, do you know how to solve the issues in my updated question? – Joris416 Apr 13 '14 at 15:24
  • @Imaginedigital Yes, as long as the name of the product contains only [valid characters](http://stackoverflow.com/questions/70579/what-are-valid-values-for-the-id-attribute-in-html) and are unique. As for the problem, it looks like an `overflow: hidden` is missing on the container but I cannot be sure without looking at the source. – musically_ut Apr 13 '14 at 15:43
  • this is the source as it is now (css implementation) .itemDescription{ background-color:rgb(255,255,255); width:243px; height:80px; text-align:left; font-family:"Gill Sans"; font-size:16px; color:#000; display: block; display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow:hidden; } – Joris416 Apr 13 '14 at 18:34
6

Using CSS text-overflow and Line Clamping:

div {
  display: block; 
  display: -webkit-box;
  width: 200px;
  height: 40px;
  margin: 0 auto;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  padding:20px;
  overflow:hidden;
  text-overflow: ellipsis;
}

Live example: http://jsfiddle.net/5Z4Wu/

Unamata Sanatarai
  • 5,609
  • 3
  • 22
  • 46
  • 3
    Doesn't this clamp at the first line break? I think the OP wants a multi-line clamp. – musically_ut Apr 13 '14 at 11:52
  • Thanks for adjusting your answer. However, now I suspect that the solution is webkit specific? The demo does not seem to work in Firefox. – musically_ut Apr 13 '14 at 12:44
  • Hi! Your solution makes best progress of far, so thank you very much!! I have edited the question with the remaining issues. Do you know how to solve them? (words are interrupted and clamped text is visible.) – Joris416 Apr 13 '14 at 13:05
2

Check this Fiddle I created myself:

The script in the fiddle sets the Know More link exactly at the right-bottom corner of the limited area/overflow set(hidden) div according to screen size.On clicking the Know More the visibility of the overflowing content is toggled.

jQuery

/*Only change required in this script if id name of div containing text is different*/
var txtCont = $('#wrappingText');
/*******************************/
var lines = txtCont.get(0).getClientRects();
txtCont.css('display','inline-block');

jQuery.fn.exists = function(){return this.length>0;}

function debugTxt(txt)
{
    var lineHeight = txtCont.css('line-height').replace("px", '');
    var txtContHeight = txtCont.height();
    txtCont.parent().height(lineHeight*Math.floor(txtContHeight/lineHeight));
    if (txt*lineHeight>txtContHeight){
       if(!txtCont.parent().find('.knowMore').exists()){
       txtCont.parent().append('<div class="knowMore">Know </div>');
    }}
    else
       txtCont.parent().find('.knowMore').remove();
}
debugTxt(lines.length);

$('.knowMore').click(function(){
    $(this).prev().toggleClass("visible");
    $(this).toggleClass('knowLess');
    $(this).parent().toggleClass("parentClick");
});

Use of appropriate CSS is required for getting the correct output.Below is the CSS used in the fiddle:

#wrapper{
    position:relative;
}
html,body,#wrapper,#wrappingText{
    margin:0px;
    padding:0px;
    width:100%;
    height:100%;
}
#wrappingText{
    display:inline;
    overflow:hidden;
}
.knowMore{
    position:absolute;
    bottom:0px;
    right:0px;
    background-color:white;
    color:blue;
    cursor:pointer;
}
.knowMore:before{
    content:"...";
}
.knowMore:after{
    content:"More";
}
.knowLess:before{
    content:"";
}
.knowLess:after{
    content:"Less";
}

.visible{
    overflow:visible !important;
}

.parentClick{
    width:auto !important;
    height:auto !important;
}

Updated

<div class="container">
.
.
.
<div class="wrapper">
<div class="wrappingText"></div>
</div>
.
.
.
</div>

The above structure should be used for the plugin that is used in the fiddle.You can use the class names that you want.In the above HTML wrappingText is the div containing text.It must be wrapped in another div ,in the above HTML wrappingText is wrapped in div with classname wrapper.

For using the plugin you just have to call the plugin with the classname of div containing text and pass main parent classname as parameter:

$('.wrappingText').knowMoreLess('.container'); // CALLING PLUGIN

Other Instructions and Details are added in the comments in the updated fiddle below:

Updated Fiddle

Community
  • 1
  • 1
Zword
  • 5,933
  • 2
  • 22
  • 51
  • ah, so if I understand it right only the '#wrappingText' has to be changed to the div name and then it should work? – Joris416 Apr 14 '14 at 12:19
  • Yes replace '#wrappingText' in JS. In CSS replace '#wrapper' & '#wrappingText' with the name u r using in your HTML. – Zword Apr 14 '14 at 14:57
  • I added one more fiddle.Check it – Zword Apr 14 '14 at 15:39
  • sorry for the late response! I have question about this approach. As all my product cards are generated by a php for loop, The names of my div's are variable to the product name (the web page doesn't know the name). can I put a piece of html/php in this script, so that it knows which DIV it needs to adjust? (I hoop this is clear, sorry for poor english) – Joris416 Apr 15 '14 at 09:52
  • Can you post the html output the loop generates? – Zword Apr 15 '14 at 09:56
  • updated my question with it. Thanks for quick response! – Joris416 Apr 15 '14 at 10:03
  • Ok I will look at it and post an update.Check for update later – Zword Apr 15 '14 at 10:05
  • @Imaginedigital I have updated my answer with more info and an updated fiddle.Make appropriate changes needed according to what is needed for the plugin and you will get the output you want. – Zword Apr 15 '14 at 13:58
  • I'm sorry but it does not seem to work. when I add your code, all that happens is that is instantly extends the height of my product cards to fit the text, which is not what I want. Are you familliar with this issue? – Joris416 Apr 16 '14 at 17:17
  • Are you using required CSS , jquery and html structure that is needed? – Zword Apr 17 '14 at 11:18
  • yess, as you said. my container the div containing the entire product was given the class "container", the text area was given the class "wrapper" and in that div I added a div to which I assigned the class wrappingText. all css was implemented. the javascript was added first in the loop, the outside of the loop. it didn't work. For now I am using the css way to do this as suggested in another answer. If you know the solution, please let me know – Joris416 Apr 18 '14 at 18:28