1

Suppose I have an array of tags (strings). I am displaying those tags on a quite narrow view.

Some tags are quite small so 2 can fit on the same line. Otherwise, there is one tag per line.

Ideally, if multiple tags can be placed on the same line, I'd like this to happen on the first lines.

So I need a way to evaluate the space those strings would take and sort my array of tags so that the shortest strings (when rendered) are first.

Sorting strings by their length (length of the char array) using the following functions don't work

{
  item.tags
    .sort(({ name }) => name.length)
    .map(({ name }, k) =>
    <li key={k}>#{name}</li>
  )
}

Example :

  • Assume my line can fit 50 pixels.
  • Assume the letter "i" uses 5 pixels, letter "m" uses 15 (arbitrary)
  • Given the tags (in this order)

    [ 
      "iiiii" (25px), 
      "mmm" (45px), 
      "iiiii" (25px) 
    ]
    

That would be rendered like this in HTML due to their actual rendered width

|   iiii    |
|    mmm    |
|   iiii    |

How can I easily evaluate their rendered width from their string (and maybe a reference to the font), and how can I sort the array according to this previously calculated width ? I need this for a React Component

The output should be

[ 
  "iiiii" (25px), 
  "iiiii" (25px), 
  "mmm" (45px)
]

So they can be displayed like this

| iiii iiii |
|    mmm    |
Cyril Duchon-Doris
  • 12,964
  • 9
  • 77
  • 164
  • Maybe relevant: HTML5 Canvas.measureText https://stackoverflow.com/questions/118241/calculate-text-width-with-javascript – katniss.everbean Aug 10 '17 at 22:09
  • Use a monotype font, and the problem goes away – adeneo Aug 10 '17 at 22:09
  • You may let [the engine to calculate the width of the DOM elements](https://developer.mozilla.org/en-US/docs/Web/API/Element/clientWidth) and sort them accordingly. Just an idea... – Redu Aug 10 '17 at 22:11

1 Answers1

1

You can render the tag like below and use jQuery to sort them.

//Now use jQuery to sort the tags just after the rendering.

    $('.tag').sort( function(a,b) {
       return $(a).width() - $(b).width();
    }).appendTo('.container');
 <div class="container">
  <i class="tag">iiii <br/></i> <!-- => (25px) -->
  <i class="tag">mmm <br/></i>  <!-- => (45px) -->
  <i class="tag">iiii <br/></i> <!-- => (25px) -->
</div>
<script
     src="http://code.jquery.com/jquery-3.2.1.min.js"
     integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
     crossorigin="anonymous"></script>

I added the <br/> in tags just for visibility.

Kamga Simo Junior
  • 1,679
  • 2
  • 16
  • 30