Yagayente
Yagayente

Reputation: 341

Define a width for each words and compose a title automatically

I’m searching for a way of automatically compose a sentence using javascript.

Here is an example using this sentence :
«here is an amazing sentence well composed» enter image description here Then I’d like the block size to change dependind on the word width
Different sizes So that finally, it could look like this :Final result So far, I only found how to cut the sentences in words.
How could I define a width for each «words / text block» depending on their width ?

function wordsinblocks() {
    var str = document.getElementById("demo").innerHTML;
    var res = str.split(" ");
    document.getElementById("demo").innerHTML = res; 
}
 body{
    font-family:"helvetica";
    font-size: 40px;
    }
p {border: 1px solid black;}
<button onclick="wordsinblocks();">Design the sentence</button>
<p id="demo">Here is an amazing sentence well composed</p>

Upvotes: 3

Views: 147

Answers (3)

Gabriele Petrioli
Gabriele Petrioli

Reputation: 196187

Here is an implementation that finds the relevant grid size to apply. (and reruns the fitting code when resizing the browser so that it will work responsively)

function wordsinblocks(self) {
    var demo = document.getElementById("demo"),
        initialText = demo.textContent,
        wordTags = initialText.split(" ").map(function(word){
          return '<span class="word">' + word + '</span>';
        });
  
    demo.innerHTML = wordTags.join('');
    self.disabled = true;
    fitWords();
    window.addEventListener('resize', fitWords);
}

function fitWords(){
  var demo = document.getElementById("demo"),
      width = demo.offsetWidth,
      sizes = [10,30,50, 100],
      calculated = sizes.map(function(size){return width*size/100}),
      node, 
      i, 
      nodeWidth,
      match,
      index;
  
     
    for (i=0;i<demo.childNodes.length;i++){
      node = demo.childNodes[i];
      node.classList.remove('size-1','size-2','size-3','size-4');
      
      nodeWidth = node.clientWidth;
      match = calculated.filter(function(grid){
        return grid >= nodeWidth;
      })[0];
      index = calculated.indexOf(match);
      
      
      node.classList.add( 'size-' + (index+1));
    }
}
#demo{
  display:block;
  padding:0 0 0 1px;
  overflow:auto;
}

#demo .word{
  float:left;
  box-sizing:border-box;
  padding:5px;
  border:1px solid #999;
}

#demo .size-1{width:10%}
#demo .size-2{width:30%}
#demo .size-3{width:50%}
#demo .size-4{width:100%}
<button onclick="wordsinblocks(this);">Design the sentence</button>
<p id="demo">Here is an amazing sentence well composed</p>

Upvotes: 2

Aziz
Aziz

Reputation: 7793

What about something like this? The result might not fully represent your picture but it does calculate the length of each word and apply a class accordingly:

$("p span").each(function() {
  // get length of word characters
  var l = $(this).text().length; 
  // apply 10 percent class if equal or to less than 2 characters
  if (l <= 2) {
    $(this).addClass('p10'); }
  // apply 30 percent class if equal or to less than 5 characters
  else if (l <= 5) {
    $(this).addClass('p30'); }
  // otherwise, apply a 50 percent class
  else {
    $(this).addClass('p50')
  }
});
p {
  border: 1px dashed red;
}

span {
  border: 1px solid #000;
  padding: 5px;
  display: inline-block;
  box-sizing: border-box;
}

.p10 {
  width: 10%;
  background: lightblue;
}

.p30 {
  width: 30%;
  background: lightgreen;
}

.p50 {
  width: 50%;
  background: lightyellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<span class="p10">10 percent</span>
<span class="p30">30 percent</span>
<span class="p50">50 percent</span>

<p>
  <span>Here</span>
  <span>is</span>
  <span>an</span>
  <span>amazing</span>
  <span>sentence</span>
  <span>well</span>
  <span>composed</span>
</p>

Upvotes: 0

beerwin
beerwin

Reputation: 10327

Before you put your words back in html, wrap each word into a span and style the spans. This is just the part of how would you design the spans. Based on letter count you could add grid classes to them.

Please note that i didn't write the styles for the grid classes, therefore that won't be visible.

function wordsinblocks() {
    var str = document.getElementById("demo").innerHTML;
    var res = str.split(" ");

    for (var x in res) {
      var l = res[x].length;
      var className = "grid-1";

      switch(true) {
          case (l < 3):
             className = "grid-1";
          break;
          case (l > 2 && l < 5):
             className = "grid-2";
          break;
          // and so on until you get all cases you wish to cover
          default: // and finally longer words would have the widest column class
             className = "grid-4";
          break;
      }

      res[x] = '<span class="word-item ' + className + '">' + res[x] + '</span>';
    }

    document.getElementById("demo").innerHTML = res.join(""); 
}
 body{
    font-family:"helvetica";
    font-size: 40px;
    }
p span.word-item {border: 1px solid black; padding: 0 0.5em; box-sizing: border-box; display: inline-block;}
<button onclick="wordsinblocks();">Design the sentence</button>
<p id="demo">Here is an amazing sentence well composed</p>

Upvotes: 2

Related Questions