Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set font size for a paragraph whose content is being constantly replaced

I want to set a box with a paragraph in it. The text of this paragraph is supposed to be replaced after every time I click on the button. And what is important to me is that this text should stay inside the box as a one line and not break. To do that I decided to use FitText.js plugin because words have different lengths (given words are just an example). By setting it as a table and table-cell I've achieved a nice align (both vertical and horizontal). Do you have any ideas why given code doesn't work as it should?

var words = ["Emily", "William Callum Smith Jr.", "Edwaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaard", "Bradley"];

var button1 = document.getElementById("give_me_a_name_please");

button1.addEventListener("click", function1);

function getRandomItem(array){
    return array.splice(Math.floor(Math.random() * array.length), 1)[0];
}
   
function function1(){
    var randomWord = getRandomItem(words); 
    document.getElementById('word').innerHTML = randomWord;
}

$('#give_me_a_name_please').click(function() { 
    function resize () { $("#word").fitText(0.6); } 
});
#parent_of_word {
  width: 20%;
  height: 20%;
  top: 10%;
  left: 10%;
  display: flex;
  position: absolute;
  text-align: center;
  justify-content: center;
  line-height: 100%;
  border: 5px solid black;
  word-break: keep-all;
  white-space: nowrap;
}

#word {
  color: brown;
  display:flex;
  align-items: center;
  justify-content: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.rawgit.com/davatron5000/FitText.js/0b4183af/jquery.fittext.js"></script>


<div id="parent_of_word">
    <p id="word">----------------</p>
</div>
<button id="give_me_a_name_please">Button</button>
like image 314
wymyszony Avatar asked Apr 14 '18 18:04

wymyszony


2 Answers

Edit: updated code snippet and JSFiddle with a more optimal loop.

I've adapted your example code to be a bit leaner and easier to understand. It also uses pure jQuery instead of a mix of jQuery and pure JS and won't stop at 'undefined' after pressing the button several times, resulting in an empty array. It will instead cycle through all the words again.

There are two main solutions in effect here.

  • One takes inspiration from this iterative approach to JavaScript Scale Text to Fit in Fixed Div where the font size starts at a fixed value, then scales down as necessary until the word's width is less than its container's width. No need for a plugin as this is extremely trivial.
  • The second part implements overflow:hidden so that in the event that the text is so massive that it cannot possibly be shrunk small enough (see the lower limit of 8 in the while-loop), it will still not break out of its container.

See also the JSFiddle version.

var words = [
  "Emily",
  "William Callum Smith Jr.",
  "Edwaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaard",
  "EdwaaaaaaaaaaaaaaaaaaaAAAAAAAAAaaaaaAAaaaaAAAaaaaaaaaaaaaaaaaaaaaaaaaard",
  "Bradley",
  "The quick brown fox"
];

var changeWord = $("#change_word");
var parentOfWord = $("#parent_of_word");
var word = $("#word");
var idx = 0;

changeWord.click(function() {
  word.text(words[idx++ % words.length]);
  var size = 40;
  word.css("font-size", size);
  while (word.width() > parentOfWord.width() && size > 8) {
    word.css("font-size", --size);
  }
});
#parent_of_word {
  width: 200px;
  height: 50%;
  top: 50px;
  left: 50%;
  margin-left: -100px;
  display: flex;
  position: absolute;
  text-align: center;
  justify-content: center;
  line-height: 100%;
  border: 5px solid black;
  word-break: keep-all;
  white-space: nowrap;
  overflow: hidden;
}

#word {
  color: brown;
  display: flex;
  align-items: center;
  justify-content: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<p>
  <button id="change_word">Button</button>
</p>
<div id="parent_of_word">
  <p id="word">----------------</p>
</div>
like image 195
BoffinBrain Avatar answered Oct 12 '22 17:10

BoffinBrain


To have your text in one line, without breaking:

white-space: nowrap;

To center anything vertically and horizontally:

display:flex;
align-items: center;
justify-content: center;

Applied to your example:

var words = ["Emily", "William Callum Smith Jr.", "Edwaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaard", "Resize this to see how it behaves on narrower screens. Lorem ipsum dolor sit amet bla bla bla, lorem ipsum dolor sit amet bla bla bla, lorem ipsum dolor sit amet bla bla bla.", "Bradley"];


var button1 = document.getElementById("give_me_a_name_please");


button1.addEventListener("click", function1);

function getRandomItem(array){
  return array.splice(Math.floor(Math.random() * array.length), 1)[0];
}
   
function function1(){
var randomWord = getRandomItem(words) || 'No more options.'; 
document.getElementById('word').innerHTML = randomWord;
}

$( '#give_me_a_name_please' ).click(function() { 
function resize () { $("#word").fitText(0.6); 
} 
});
#parent_of_word {
  display: flex;
  align-items: center;
  justify-content: center;
  /* rest optional, just to demo 
  * vertical alignment 
  */  
  height: calc(100vh - 40px); 
  border: 1px solid red;
  padding: 1rem;
}

#word {
  white-space: nowrap;
  border: 5px solid;
  padding: 1rem;
  flex: 0 1 auto;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
}
 * {
  margin: 0;
  box-sizing: border-box;
 }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.rawgit.com/davatron5000/FitText.js/0b4183af/jquery.fittext.js"></script>


<div id="parent_of_word">
<p id="word">----------------</p>
</div>
<button id="give_me_a_name_please">Button</button>
like image 32
tao Avatar answered Oct 12 '22 16:10

tao