Сделайте моноширинный текст максимально большим, не вызывая переполнения или переноса текста - PullRequest
5 голосов
/ 26 апреля 2020

Я ищу способ сделать моноширинный текст как можно более широким в своем контейнере без переполнения или разрушения. Я уже рассмотрел CSS3, чтобы сделать текст максимально большим, чтобы заполнить элемент без переполнения , и попытался реализовать предложенное решение, но в моем случае это не работает. Если я установлю размер шрифта на 3vw вместо 7vw, как предложено в ответе на связанный вопрос, он кажется близким, но когда я изменяю длину строк или ширину страницы, он снова отключается.

Вот мой код:

https://jsfiddle.net/de7qbu19/ (код на скрипке тот же)

#song-container {
    text-align: center;
    margin: 20px;
}
#song {
    color: #000;
    font: normal 3vw Courier New,monospace,Courier;
    white-space: pre;
    word-break: break-all;
    text-align: left;
    display: inline-block;
}

#song > span { /* Chords*/
    color: #007fbf;
    cursor: pointer;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
            
<div class="container-fluid">
    <div id="song-container">
        <div class="panel panel-default">
            <div class="panel-body">
                <span id="song">
[Placeholder]

<span>Em</span>         <span>G</span>
Placeholder Placeholder Placeholder Placeholder
<span>D</span>          <span>C</span>
Placeholder Placeholder Placeholder Placeholder
                </span>
            </div>
        </div>
    </div>
</div>

Когда я запускаю фрагмент, кажется, что он почти занимает всю ширину: small Но когда я нажимаю Full page становится ясно, что это не так и что это ненадежно, особенно когда я уменьшаю размер окна: full screen small win

Поэтому установка размера шрифта с помощью vw юниты, кажется, не справляются со мной.

Есть идеи, как мне этого добиться?

Ответы [ 3 ]

3 голосов
/ 04 мая 2020

Давайте сначала посмотрим, почему размер текста такой, какой он есть в настоящее время. 3vw означает 3% ширины области просмотра. Важно отметить, что это значение используется для высоты символов. Мы можем вычислить ширину полного текста в процентах от ширины области просмотра. Это работает только для моно шрифта.

Для начала нам понадобится соотношение ширины / высоты шрифта. Ширина символа с одним интервалом зависит от шрифта. Я буду работать с Courier New для этого примера. Я не уверен, где именно это найти, поэтому я буду использовать приблизительное значение 99/188.

image of character measurement

Если максимальное количество символов :

11 * 4 (Placeholder) + 3 (spaces) = 47

Тогда ширина 47 символов равна:

47 * 3vw * (99/188) = 74.25vw

Так что около 75% от ширины области просмотра. Это означает, что когда отступы, поля и границы занимают более чем 25% ширины (из-за изменения размера окна), содержимое текста больше не помещается в его контейнер.

Так как же нам сделать содержание подходит? Мы можем использовать функцию CSS calc(), чтобы вычесть некоторое значение stati c из значения Dynami c. Для этого сначала нужно узнать ширину значений c. В вашем примере это stati c widths:

  • 20px поле для #song-container
  • 15px отступ для .container-fluid
  • 1px border для .panel
  • 15px padding для .panel-body

Не забывайте, что все эти значения присутствуют с обеих сторон, поэтому они занимают:

(20px + 15px + 1px + 15px) * 2 = 102px

Мы не можем вычесть это из 3vw, потому что 3vw - высота одного символа, тогда как 102px - ширина строки c элементов. Теперь нам нужно преобразовать 102px в высоту одного символа. Это делается путем распределения ширины по всем символам с последующим применением соотношения для преобразования ширины символов в высоту.

102px / 47 / (99/188) ≈ 4.121212121

Теперь мы сравниваем яблоки с яблоками и можем использовать calc(3vw - 102px / 47 / (99/188)) для размера шрифта , Теперь вы можете свободно играть со значением 3vw. В примере я увеличил это значение до 3.5vw.

Обратите внимание, что это не на 100% точно, я не учитывал интервал между символами, а соотношение ширины / высоты шрифта основано на измерении, а не данное.

#song-container {
    text-align: center;
    margin: 20px;
}
#song {
    color: #000;
    font-size: calc(3.5vw - 102px / 47 / (99/188));
    font-family: "Courier New",monospace,Courier;
    white-space: pre;
    word-break: break-all;
    text-align: left;
    display: inline-block;
}

#song > span { /* Chords*/
    color: #007fbf;
    cursor: pointer;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
            
<div class="container-fluid">
    <div id="song-container">
        <div class="panel panel-default">
            <div class="panel-body">
                <span id="song">
[Placeholder]

<span>Em</span>         <span>G</span>
Placeholder Placeholder Placeholder Placeholder
<span>D</span>          <span>C</span>
Placeholder Placeholder Placeholder Placeholder
                </span>
            </div>
        </div>
    </div>
</div>

Это работает, но при изменении ширины stati c, максимального количества символов или соотношения ширины / высоты шрифта необходимо пересчитать значение компенсации , По этой причине лучше всего подойдет библиотека JavaScript. Вы можете найти некоторые из них, описанные в посте CSS -Trics Подгонка текста к контейнеру .

Я бы также посоветовал взглянуть на Масштабирование шрифтов на основе ширина контейнера вопрос, который имеет некоторые другие предложения.

3 голосов
/ 29 апреля 2020

Если у вас точная ширина как javascript решение, вот простое.

Оно состоит из получения ширины div и размера шрифта, оно вычисляет ширину одного символа и, наконец, вычисляет новый максимальный размер шрифта в соответствии с этой информацией.

Вы также должны указать в скрипте максимальное количество символов, которое вы можете иметь в самой длинной строке текста:

Placeholder Placeholder Placeholder Placeholder

В приведенном выше примере в самой длинной строке текста 47 символов;

var container = document.getElementById("container"),
  cs = getComputedStyle(container),
  containerPB = parseFloat(cs.paddingLeft) + parseFloat(cs.paddingRight) + parseFloat(cs.borderLeftWidth) + parseFloat(cs.borderRightWidth), //containerPadding + containerBorderWidth
  containerWidth = container.offsetWidth - containerPB,
  containerFontSize = parseFloat(cs.fontSize),
  containerFontFamily = cs.fontFamily,
  span = document.createElement("SPAN"),
  char = document.createTextNode("a"),
  charMax = 47, //max characters per line
  alpha = 1.00; //represent font scaling based on width
span.style.fontFamily = containerFontFamily;
span.appendChild(char);
span.style.visibility = "hidden";
document.body.appendChild(span);
//GETTING THE WIDTH OF A SINGLE CHAR
var charWidth = span.getBoundingClientRect().width;
document.body.removeChild(span);
container.style.fontSize =
  (containerWidth * containerFontSize * alpha) / (charWidth * charMax) + "px";
window.addEventListener("resize", function(e) {
  //update the width of container
  containerWidth = container.offsetWidth - containerPB;
  //update the font-size
  container.style.fontSize =
    (containerWidth * containerFontSize * alpha) / (charWidth * charMax) + "px";
});
* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

#container {
  border: 1px solid #ddd;
  color: #000;
  font-family: Courier New, monospace, Courier;
  margin: 0 auto;
  padding: 0.375rem;
  width: 90%;
}

#container>span {
  /* Chords*/
  color: #007fbf;
  cursor: pointer;
}
[Placeholder]

Em         G
Placeholder Placeholder Placeholder Placeholder
D          C
Placeholder Placeholder Placeholder Placeholder
0 голосов
/ 05 мая 2020

У меня есть несколько вещей, которые улучшат отзывчивость:

#song-container{
 text-align: center;
 margin:0;
overflow: hidden;
}

.panel-body{
 margin: 0;
}

Если вы хотите, чтобы переполнение было прокручиваемым, вы можете просто добавить overflow-x: scroll; Также, если вы используете медиазапросы, которые сделают его более отзывчивым, потому что даже при моем подходе доходит до того, что, если размер экрана составляет всего 220px, он обрезает некоторые слова из-за недостаточно быстрого масштабирования шрифтов, что можно изменить в своем медиазапросе, чтобы масштабировать шрифт быстрее после достижение этой точки, чтобы держать его в своем контейнере. Надеюсь это поможет!

РЕДАКТИРОВАТЬ:

  #song-container {
    text-align: center;
    /*margin: 20px;*/
    padding: 1%;
}
#song {
    color: #000;
    font: normal 3vw Courier New,monospace,Courier;
    white-space: pre;
    word-break: break-all;
    text-align: left;
    display: inline-block;
}

#song > span { /* Chords*/
    color: #007fbf;
    cursor: pointer;
}
.panel-body{
  padding:0;
}

Это должно сделать это, я редактирую его в скрипке.

...