Как установить размер шрифта для абзаца, содержимое которого постоянно заменяется

Я хочу установить в нем поле с абзацем. Текст этого абзаца должен быть заменен после каждого нажатия кнопки. И для меня важно то, что этот текст должен оставаться внутри коробки как одна строка, а не ломаться. Для этого я решил использовать плагин FitText.js, потому что слова имеют разную длину (данные слова - всего лишь пример). Установив его как таблицу и таблицу, я достиг хорошего выравнивания (как вертикального, так и горизонтального). У вас есть идеи, почему данный код не работает должным образом?

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>

Ответ 1

Изменение: обновленный фрагмент кода и JSFiddle с более оптимальным циклом.

Я адаптировал ваш примерный код, чтобы быть немного более компактным и понятным. Он также использует чистый jQuery вместо сочетания jQuery и чистого JS и не останавливается на "undefined" после нажатия кнопки несколько раз, в результате получается пустой массив. Вместо этого он повторит все слова.

Здесь действуют два основных решения.

  • Один из них вдохновляет этот итерационный подход к JavaScript Scale Text to Fit в Fixed Div, где размер шрифта начинается с фиксированного значения, а затем масштабируется по мере необходимости, пока ширина слова меньше его ширины контейнера. Нет необходимости в плагине, поскольку это чрезвычайно тривиально.
  • Вторая часть реализует overflow:hidden так что в случае, если текст настолько массивный, что он не может быть уменьшен достаточно небольшим (см. Нижний предел 8 во время цикла), он все равно не выйдет из своего контейнера.

См. Также версию JSFiddle.

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>

Ответ 2

Чтобы текст был в одной строке, без нарушения:

white-space: nowrap;

Чтобы центрировать все вертикально и горизонтально:

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

Применяется к вашему примеру:

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>

Ответ 3

Это потому, что вы определили width #parent_of_word как 20%, что, конечно, связано с ее родительским элементом, то есть с элементом body, основанным на данном примере.

Таким образом, width #parent_of_word не может быть просто изменена динамически на основе ширины ее содержимого. Он может быть только "визуально изменен" вместе с его родительской шириной, но при этом он будет занимать 20%. Несмотря на то, что используемая единица равна % а ширина элемента динамическая, она по-прежнему фиксируется.

Поэтому моим решением было бы опустить свойство width и просто определить padding по вашему выбору:

Примечание. Я прокомментировал ненужное.

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 {
  display: flex;
  /*width: 20%; the culprit*/
  height: 20%;
  padding: 0 20px; /* can also use [%] */
  position: absolute;
  top: 10%;
  left: 10%;
  /*text-align: center;*/
  justify-content: center;
  align-items: center; /* added; vertical alignment */
  /*line-height: 100%;*/
  border: 5px solid black;
  /*
  word-break: keep-all;
  white-space: nowrap;
  */
  color: brown;
}

/*
#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>

<button id="give_me_a_name_please">Button</button>

<div id="parent_of_word">
  <p id="word">----------------</p>
</div>

Ответ 4

#parent_of_word решение вашей проблемы - изменить #parent_of_word ширины #parent_of_word на width:auto. Это будет автоматически регулироваться в зависимости от содержимого (автоматически настраивается в зависимости от длины абзаца).

Рабочий пример: https://jsfiddle.net/18faLbap/4/

Ответ 5

Обычно я делаю это с помощью этого подхода, когда хочу сохранить текст в строке. в частности я сетки. Таким образом, независимо от того, сколько времени у вас есть, это будет в одной строке, и когда вы наведете на нее, это будет хлеб, чтобы линии были удобочитаемыми.

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%;
  
  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;

}

#word {
  text-overflow: ellipsis;
  white-space: nowrap;
  overflow: hidden;
  color: brown;
  display:flex;
  align-items: center;
  justify-content: center;
}

#word:hover {
    white-space: normal;
    }
<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>

Ответ 6

#parent_of_word {
    min-width: 20%;
    width: auto;
    padding: 0px 20px;
}

Все, что я сделал, это добавить по width: auto и установить min-width:20%. Это делает динамическую ширину, когда текст обновляется внутри поля. Добавлен в небольшое padding чтобы он выглядел хорошо. Надеюсь это поможет.

Ответ 7

Увидев, что у вас уже есть jQuery на странице, рассмотрите возможность использования плагина jquery-textfill:

http://jquery-textfill.github.io/

Он обеспечит, чтобы ваш текст соответствовал вашему контейнеру.

Ответ 8

Существует способ CSS, который подходит для слов в содержании.

Я в основном отключил абсолютную ширину вашего #parent_of_word и изменил display на inline-block, чтобы его ширина соответствовала его контенту. Чтобы сделать его более красивым, я добавляю свойство padding. Ниже приведена уменьшенная и улучшенная версия вашего кода.

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;
}
#parent_of_word {
  top: 10%;
  left: 10%;
  display: inline-block;
  position: absolute;
  text-align: center;
  padding: 10px;
  border: 5px solid black;
  word-break: keep-all;
}

#word {
  text-overflow: ellipsis;
  white-space: nowrap;
  overflow: hidden;
  color: brown;
  display:flex;
  align-items: center;
  justify-content: center;
}

#word:hover {
    white-space: normal;
    }
<div id="parent_of_word">
    <p id="word">----------------</p>
</div>
<button id="give_me_a_name_please">Button</button>