简体   繁体   中英

Width of _text_ in each list item

Best way to do this? I have tried:

var listWidth = [];
$('ul li').each(function() {
    listWidth.push($(this).width());
});

dummy code:

    <ul>
    <li>Item 1</li>
    <li>Longer item 
    <li>Even longer item</li>
    </ul>

css:

ul {
  width: some fixed width;
}

But it just returns the same width for all, which is also the width of the actual list item, and not the text.

Edit: I want the width of the text in pixels. Not the amount of characters of width of the list itself

Wrap the text in <span> s and get the widths of those. The <li> tags are blocks and will expand out to the width of the <ul> whereas <span> tags are inline and only take up as much width as they need (in this case, to surround the characters).

 var listWidth = []; $('ul > li > span').each(function() { listWidth.push($(this).width()); }); document.write(listWidth); 
 ul { width: 400px; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <ul> <li><span>Item 1</span></li> <li><span>Longer item </span></li> <li><span>Even longer item</span></li> </ul> 

One approach I'd suggest is the following:

(function($) {

  // creating a named function on the jQuery prototype,
  // which becomes a (very simple, in this case)
  // jQuery plugin
  $.fn.retrieveTextWidth = function() {

    // creating a <span> element into which the
    // content of the passed-in elements, the
    // collection to which the plugin is chained
    // will be temporarily inserted:
    var span = document.createElement('span'),

    // 'empty' variables for later use:
      tmp,
      clone;

    // creating a map of values based on
    // the passed-in collection (the
    // 'this'):
    var res = this.map(function() {

      // cloning the created <span>
      // element:
      clone = span.cloneNode();

      // inserting the cloned <span> ahead of the
      // first child of the current node (from the
      //  jQuery collection, here 'this' refers to
      //  a single Node):
      this.insertBefore(clone, this.firstChild);

      // while the inserted clone has a nextSibling
      // we move that nextSibling into the clone:
      while (clone.nextSibling) {
        clone.appendChild(clone.nextSibling);
      }

      // here we assign the width of the cloned
      // <span> element to a variable:
      tmp = clone.getBoundingClientRect().width;

      // then, while the clone has a firstChild
      // we remove that firstChild and insert it
      // before the clone:
      while (clone.firstChild) {
        clone.parentNode.insertBefore(clone.firstChild, clone);
      }

      // once the clone is empty (after the above
      // while loop has finished) we remove it from
      // the parentNode, removing it from the DOM:
      clone.parentNode.removeChild(clone);

      // once the temporary cloned element has been
      // removed (and the 'tidying up' completed),
      // we return the retrieved clientWidth via
      // the temporary variable:
      return tmp;

    // converting the jQuery map into an
    // Array, consisting only of the found
    // widths:
    }).get();

    // return the Array of widths to the calling
    // context:
    return res;

  };
})(jQuery);

console.log($('ul li').retrieveTextWidth());

 (function($) { $.fn.retrieveTextWidth = function() { var span = document.createElement('span'), tmp, clone; var res = this.map(function() { clone = span.cloneNode(); this.insertBefore(clone, this.firstChild); while (clone.nextSibling) { clone.appendChild(clone.nextSibling); } tmp = clone.getBoundingClientRect().width; while (clone.firstChild) { clone.parentNode.insertBefore(clone.firstChild, clone); } clone.parentNode.removeChild(clone); return tmp; }).get(); return res; }; })(jQuery); console.log($('ul li').retrieveTextWidth()); 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <ul> <li>one</li> <li>A string of arbitrary text</li> <li>3</li> <li>Lorem ipsum dolor sit amet...okay, I got bored. But, clearly, this is the longest textual content.</li> </ul> 

JS Fiddle demo .

References:

Do you mean the length of characters of text / html?

var listWidth = [];
$('ul li').each(function() {
    listWidth.push($(this).text().length);
});

Not exactly sure what you're looking for because, the width of all li in the same ul or ol will be the same, unless you've specified otherwise.

EDIT

The size of the character in each font is measure by the width of the capital M. In principle you can multiply the font-size with the text length but not all letters/characters are as wide as M. So you will definitely end-up with a huge number...

If you use this CSS, the li elements will have the width of their text content, then your JS should work:

ul {  
  overflow: hidden; 
}
li { 
  float: left;
  clear: left;
}

Here it's in a codepen: http://codepen.io/anon/pen/KgBvJW (made visible with background-colors)

You can calculate the width using canvas and measureText() .

function getWidth(text, font) {
    var canvas = document.createElement("canvas");
    var ctx = canvas.getContext("2d");
    ctx.font = font; // important for accurate metrics
    var metrics = ctx.measureText(text); // TextMetrics object
    return Math.ceil(metrics.width);
}

var listWidth = [];
$('ul li').each(function() {
    // put your own font for accurate metrics.
    listWidth.push(getWidth($(this).text(), 'normal 14pt Arial'));
});

listWidth will now contain calculated width of each element. If you want to apply the width to each li element you can use this instead:

$('ul li').each(function() {
    // put your own font for accurate metrics.
    $(this).css({width: getWidth($(this).text(), 'normal 14pt Arial') + 'px'});
});

This might be overkill, but it all depends on why you need the width. There might be other solutions that will solve what you try to achieve more efficiently.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM