2

While building an interface with lots of data, there are some <table> elements, that need to be responsive. Of course it is possible to replace <table> with any other kind of element.

The structure of the tables are always the same:

  • all columns are really small and can have a fixed width
  • except for one column, that sometimes contains words that need to be shortened

Problem:

There are some rows with a long and single word, like "intentionalamazingtoostrongawesomeness", which do not break in lines but stretch the whole table. This is not good on smartphones. I did create a snippet to illustrate the problem.

body {
  font-family: 'Helvetica Neue', Helvetica, sans-serif;
}

#wrapper {
  background: #eaeaea;
  width: 320px;
  margin: 0 auto;
}

#wrapper table {
  width: 100%;
  vertical-align: middle;
}

#wrapper .icon {
  background: #8da2b5;
  border-radius: 3px;
  display: block;
  height: 23px;
  width: 23px;
}

td {
  border-bottom: 1px solid #d3d6db;
}

td:nth-child(1) {
  padding: 10px;
}


/* demo styles */

body {
  background: #e4e8eb;
}

#wrapper {
  border: 1px solid #d3d6db;
  background: #f0f4f7;
  color: #63778b;
}

#legend {
  color: #63778b;
  width: 320px;
  margin: 40px auto 10px;
  font-size: 11px;
  text-transform: uppercase;
}
<div id="legend">|--------- This is the smallest width necessary ----------|</div>
<div id="wrapper">
  <table cellspacing="0">
    <tr>
      <td><span class="icon"></span></td>
      <td><span class="text">Lorem ipsum dolor.</span></td>
      <td><span class="icon"></span></td>
      <td><span class="number">123</span></td>
    </tr>
    <tr>
      <td><span class="icon"></span></td>
      <td><span class="text"><strong>I_am_the_long_trouble_maker_that_stretches</strong> asdasdasd</span></td>
      <td><span class="icon"></span></td>
      <td><span class="number">42</span></td>
    </tr>
    <tr>
      <td><span class="icon"></span></td>
      <td><span class="text">Sint, itaque, cupiditate Lorem ipsum dolor sit..</span></td>
      <td><span class="icon"></span></td>
      <td><span class="number">16</span></td>
    </tr>
    <tr>
      <td><span class="icon"></span></td>
      <td><span class="text">Velit et, laudantium?</span></td>
      <td><span class="icon"></span></td>
      <td><span class="number">24</span></td>
    </tr>
    <tr>
      <td><span class="icon"></span></td>
      <td><span class="text">Architecto, dolorem, cum!</span></td>
      <td><span class="icon"></span></td>
      <td><span class="number">13</span></td>
    </tr>
    <tr>
      <td><span class="icon"></span></td>
      <td><span class="text">Dolore, neque molestias.</span></td>
      <td><span class="icon"></span></td>
      <td><span class="number">24</span></td>
    </tr>
    <tr>
      <td><span class="icon"></span></td>
      <td><span class="text">Ratione, reprehenderit, deserunt.</span></td>
      <td><span class="icon"></span></td>
      <td><span class="number">52</span></td>
    </tr>
    <tr>
      <td><span class="icon"></span></td>
      <td><span class="text">Quidem, in, excepturi?</span></td>
      <td><span class="icon"></span></td>
      <td><span class="number">41</span></td>
    </tr>
    <tr>
      <td><span class="icon"></span></td>
      <td><span class="text">Voluptates, aperiam eos.</span></td>
      <td><span class="icon"></span></td>
      <td><span class="number">75</span></td>
    </tr>
    <tr>
      <td><span class="icon"></span></td>
      <td><span class="text">Explicabo delectus, illum.</span></td>
      <td><span class="icon"></span></td>
      <td><span class="number">45</span></td>
    </tr>
    <tr>
      <td><span class="icon"></span></td>
      <td><span class="text">Facilis, provident, debitis!</span></td>
      <td><span class="icon"></span></td>
      <td><span class="number">24</span></td>
    </tr>
    <tr>
      <td><span class="icon"></span></td>
      <td><span class="text">Corrupti, itaque voluptatem!</span></td>
      <td><span class="icon"></span></td>
      <td><span class="number">25</span></td>
    </tr>
    <tr>
      <td><span class="icon"></span></td>
      <td><span class="text">Expedita, ea, ab.</span></td>
      <td><span class="icon"></span></td>
      <td><span class="number">41</span></td>
    </tr>
    <tr>
      <td><span class="icon"></span></td>
      <td><span class="text">Necessitatibus, reiciendis, quisquam.</span></td>
      <td><span class="icon"></span></td>
      <td><span class="number">24</span></td>
    </tr>
    <tr>
      <td><span class="icon"></span></td>
      <td><span class="text">Quis, rem facilis!</span></td>
      <td><span class="icon"></span></td>
      <td><span class="number">35</span></td>
    </tr>
    <tr>
      <td><span class="icon"></span></td>
      <td><span class="text">Porro, ullam, esse.</span></td>
      <td><span class="icon"></span></td>
      <td><span class="number">14</span></td>
    </tr>
    <tr>
      <td><span class="icon"></span></td>
      <td><span class="text">Eveniet, laboriosam, in.</span></td>
      <td><span class="icon"></span></td>
      <td><span class="number">64</span></td>
    </tr>
    <tr>
      <td><span class="icon"></span></td>
      <td><span class="text">Est, nisi, dicta!</span></td>
      <td><span class="icon"></span></td>
      <td><span class="number">74</span></td>
    </tr>
    <tr>
      <td><span class="icon"></span></td>
      <td><span class="text">Iste, et, autem!</span></td>
      <td><span class="icon"></span></td>
      <td><span class="number">24</span></td>
    </tr>
    <tr>
      <td><span class="icon"></span></td>
      <td><span class="text">Mollitia, delectus, magnam!</span></td>
      <td><span class="icon"></span></td>
      <td><span class="number">52</span></td>
    </tr>
  </table>
</div>

Solution:

I want to shorten the words inside the table, like "intentionalamazingtoo…", while the word should be as long as possible. How can I achieve this?

Demo table with simulated solution

Requirements:

There is no fixed width for the <td> or table containing text and the shortened word. Both should be as large/long as possible.

As said at the beginning, it is ok to use divs instead of tables, a flex-box system or any other html markup, as soon as it works as described above.

I do prefer a css only solution, as I am not used to javascript, while the table is wrapped in a huge javascript component. The app is running on Meteor and TypeScriptReact.

Marian Rick
  • 3,350
  • 4
  • 31
  • 67
  • 2
    https://css-tricks.com/snippets/css/truncate-string-with-ellipsis/ – Taha Paksu Apr 05 '17 at 11:15
  • For CSS see http://stackoverflow.com/questions/802175/truncating-long-strings-with-css-feasible-yet/22811590; http://stackoverflow.com/questions/33058004/applying-an-ellipsis-to-multiline-text; http://stackoverflow.com/questions/536814/insert-ellipsis-into-html-tag-if-content-too-wide. Also some JS solutions in those questions. – Stuart Apr 05 '17 at 11:24

6 Answers6

4

You could use text-overflow: ellipsis; maybe in conjunction with white-space: nowrap; depending on context and it should do the trick nicely for you

FusionDesign
  • 353
  • 1
  • 4
  • 13
2

You can do this:

td {
  border-bottom: 1px solid #d3d6db;
  max-width: 200px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;  
}

Updated Snippet:

http://jsbin.com/qucavebebu/1/edit?html,css,output

But beware, it should have a pre defined width.

Taha Paksu
  • 15,371
  • 2
  • 44
  • 78
1

For a JavaScript solution you could use RegExp replace. You can change the character limit depending on the device size:

$(truncateText);

function truncateText() {
  var maxlength = 200;
  var screenWidth = window.innerWidth;
  if(screenWidth < 700) {
    maxlength = 23;
  }
  var regExp = new RegExp('([^\\s<>]{' + maxlength + '})([^\\s<>]+)','gi');
  $('#wrapper table .text').each(function(i, el) {
    var $el = $(el);
    var html = $el.data('full');
    if(!html) {
      $el.data('full', $el.html());
      html = $el.html();
    }
    $el.html(html.replace(regExp, '$1...'));
  });
}

window.onresize = truncateText;
body {
  font-family: 'Helvetica Neue', Helvetica, sans-serif;
}

#wrapper {
  background: #eaeaea;
  width: 320px;
  margin: 0 auto;
}

#wrapper table {
  width: 100%;
  vertical-align: middle;
}

#wrapper .icon {
  background: #8da2b5;
  border-radius: 3px;
  display: block;
  height: 23px;
  width: 23px;
}

td {
  border-bottom: 1px solid #d3d6db;
}

td:nth-child(1) {
  padding: 10px;
}


/* demo styles */

body {
  background: #e4e8eb;
}

#wrapper {
  border: 1px solid #d3d6db;
  background: #f0f4f7;
  color: #63778b;
}

#legend {
  color: #63778b;
  width: 320px;
  margin: 40px auto 10px;
  font-size: 11px;
  text-transform: uppercase;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="legend">|--------- This is the smallest width necessary ----------|</div>
<div id="wrapper">
  <table cellspacing="0">
    <tr>
      <td><span class="icon"></span></td>
      <td><span class="text">Lorem ipsum dolor.</span></td>
      <td><span class="icon"></span></td>
      <td><span class="number">123</span></td>
    </tr>
    <tr>
      <td><span class="icon"></span></td>
      <td><span class="text"><strong>I_am_the_long_trouble_maker_that_stretches</strong> asdasdasd</span></td>
      <td><span class="icon"></span></td>
      <td><span class="number">42</span></td>
    </tr>
    <tr>
      <td><span class="icon"></span></td>
      <td><span class="text">Sint, itaque, cupiditate Lorem ipsum dolor sit..</span></td>
      <td><span class="icon"></span></td>
      <td><span class="number">16</span></td>
    </tr>
  </table>
</div>
Arg0n
  • 8,283
  • 2
  • 21
  • 38
1

The flexbox model works if a single column is adjustable, as shown in this jsfiddle (you can modify the right panel width to test the behavior). The code is adapted from this answer given by Blender. As specified in your question:

  • The grid is as wide as possible, to fill the container width
  • The text column width is adjustable; other column widths are fixed
  • The text is truncated when necessary to avoid wrapping
  • No Javascript or jQuery code is involved, only HTML and CSS

The HTML markup is as follows:

<div class="wrapper-div">
    <div class="icon-div">
        <div class="icon"></div>
    </div>
    <div class="text-div">Lorem ipsum dolor</div>
    <div class="icon-div">
        <div class="icon"></div>
    </div>
    <div class="number-div">24</div>
</div>
<div class="wrapper-div">
    <div class="icon-div">
        <div class="icon"></div>
    </div>
    <div class="text-div"><strong>I_am_the_long_trouble_maker_that_stretches</strong></div>
    <div class="icon-div">
        <div class="icon"></div>
    </div>
    <div class="number-div">8</div>
</div>
...

The flexbox is set with this CSS:

.wrapper-div {
    display: flex;
    align-items: center;
}

.icon-div {
    flex: 0 0 auto;  /* Width adjusted to content, not allowed to grow or shrink */
    padding: 4px 6px;
}

.text-div {
    text-align: left;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
    flex: 1 0 0px;   /* Adjustable width, will grow to take available space */
}

.number-div {
    flex: 0 0 32px;  /* Width set to 32px, not allowed to grow or shrink */
}

.icon-div .icon {
    background: #8da2b5;
    border-radius: 3px;
    display: block;
    height: 23px;
    width: 23px;
}
Community
  • 1
  • 1
ConnorsFan
  • 70,558
  • 13
  • 122
  • 146
1

I think it's better to make the word shorten and add READ MORE AND READ LESS via Javascript. Code are the following below:

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
    <script type="text/javascript" src="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
</head>
<body>
    <p class="more" style="text-align: justify; margin: 5px; padding: 0px; font-size: 15px; line-height: 16px;">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodoconsequat. Duis aute irure dolor in reprehenderit in voluptate velit essecillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat nonproident, sunt in culpa qui officia deserunt mollit anim id est laborum.Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmodtempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodoconsequat. Duis aute irure dolor in reprehenderit in voluptate velit essecillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat nonproident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    <script type="text/javascript">
        $(document).ready(function() {
        // Configure/customize these variables.
        var showChar = 500 // How many characters are shown by default
        var ellipsestext = "...";
        var moretext = "Read More ";
        var lesstext = "Read Less";


        $('.more').each(function() {
            var content = $(this).html();

            if(content.length > showChar) {

                var c = content.substr(0, showChar);
                var h = content.substr(showChar, content.length - showChar);

                var html = c + '<span class="moreellipses">' + ellipsestext+ '&nbsp;</span><span class="morecontent"><span>' + h + '</span>&nbsp;&nbsp;<a href="" class="morelink">' + moretext + '</a></span>';

                $(this).html(html);
            }

        });

        $(".morelink").click(function(){
            if($(this).hasClass("less")) {
                $(this).removeClass("less");
                $(this).html(moretext);
            } else {
                $(this).addClass("less");
                $(this).html(lesstext);
            }
            $(this).parent().prev().toggle();
            $(this).prev().toggle();
            return false;
        });
    });
    </script>
</body>
</html>
Carl Angelo Nievarez
  • 573
  • 1
  • 11
  • 33
0

Or you could have it display on mutiple lines as follow when larger than the initial width:

span.text {
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
}
FusionDesign
  • 353
  • 1
  • 4
  • 13
  • -webkit-line-clamp: 3; will only work in webkit browsers as Chrome (http://caniuse.com/#feat=css-line-clamp) . On firefox you can trick that with a fade into from transparent to bg-color and creating the illusion of line clamp with a max height, calculated with line-height * font-size* lines_to_show. I you use SCSS or LESS you can achieve it quick with a mixin, otherwise you have to calculate manually and create situations. – Dinca Adrian Apr 05 '17 at 11:46
  • @Dinca Adrian -webkit-line-clamp: 3; will only work in webkit browsers as Chrome >>> I didn't know that, thanks for the head up ;-) – FusionDesign Apr 05 '17 at 11:55
  • Anything prefixed with `-webkit` only works in Webkit Browsers, Fusion. Chrome uses Blink, which is a fork of WebKit. Webkit was intiailly only used by Safari. The other two are Gecko (FF) and Trident (IE family). [Full list here](https://en.wikipedia.org/wiki/List_of_web_browsers). – tao Apr 09 '17 at 12:19