8

Есть заголовок внутри адаптивного блока.

Необходимо чтобы сам текст занимал свободное пространство родительского блока по ширине и соответственно увеличивался и уменьшался в размерах.

<div class='container'>
 <h1>Заголовок</h1>
</div>
DmitryZ
  • 110
  • http://stackoverflow.com/questions/15649244/responsive-font-size – soledar10 Apr 13 '17 at 05:38
  • Извините, я плохо понимаю английский язык. Но как я понял, там речь идёт о медиа запросах. Данный вариант также не имеет место быть, т.к придётся писать слишком много лишних запросов создавая новый блок и.или "формат" блоков. – DmitryZ Apr 13 '17 at 05:47
  • Возможно есть решение от яваскрипт (в нём я тоже не силён) которое позволяет высчитать ширину блока и относительно данной ширины увеличить или уменьшить шрифт? – DmitryZ Apr 13 '17 at 05:54
  • 2
    вот вариант еще такой - http://jsfiddle.net/soledar10/w34a1f0t/1/, более подробно https://github.com/davatron5000/FitText.js – soledar10 Apr 13 '17 at 06:54

5 Answers5

2

Вариант на CSS.

vw - еденица измерения, равная проценту ширины документа:

div{   
    font-size: 8.1vw;
    white-space: nowrap;
}
<div>Некоторый тестовый текст</div>

Он довольно неточен, поэтому я поставил white-space: nowrap;

Вариант с масштабированием.

Блок с текстом масштабируется с помощью JS и CSS transform

function fillDiv(div, proportional) {

var div=$('#test') var currentHeight = div.outerHeight(); var currentWidth = div.outerWidth()+3; var availableHeight = window.innerHeight; var availableWidth = window.innerWidth;

var scale = availableWidth / currentWidth;

div.css({ "left": "0px", "top": "0px", "transform": "scale3d(" + scale + ", " + scale + ", 1)", "transform-origin": "0 0" }); } fillDiv(); $( window ).resize(fillDiv)

#test{
    position:absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="test">Некоторый тестовый текст</div>

Стырено и адаптировано из amazon

Crantisz
  • 9,730
  • 2
  • 17
  • 49
1

Довольно интересная задача. чтобы её решить нужно знать

  1. ширину контейнера
  2. fontSize текста
  3. Ширину текста

Получаем коэффициент: fontSize делим на ширину текста

Умножаем ширину контейнера на этот коэффициент

Получившееся значение будет являться размером шрифта в пикселях которое нужно применить к тексту чтобы тот занимал всю ширину контейнера.

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

let child = document.querySelector('.child');
const k = child.computedStyleMap().get('font-size').value / child.getBoundingClientRect().width;

let observer = new ResizeObserver((mutations) => { const containerWidth = mutations[0].contentRect.width; child.style.fontSize = k * containerWidth + 'px'; });

observer.observe(document.querySelector('.parent'));

.parent {
  resize: horizontal;
  overflow: hidden;
  background-color: #fec;
  width: 300px;
}

.child {
  background-color: tomato;
  color: #fec;
}

body {
  margin: 0;
}
<div class="parent">
  <span class="child">Широко</span>
Изменяй ширину →
</div>

До этого решения я 10 лет назад додумался сам )

https://github.com/jt3k/text-autofitter (там можно поиграть в демо)

jt3k
  • 111
1
  1. Обернём текст инлайн-элементом (в нашем случае это <span>) для того, чтобы вычислять ширину текста. Добавим для этого элемента свойство white-space: nowrap — так при инкрементальном увеличении текст не перенесется на другую строку и высчитываемая ширина не изменится.

  2. Проверяем что больше — ширина страницы или ширина текста. Если текст больше, то в цикле уменьшаем его до тех пор, пока он не станет меньше. Если текст меньше, то в цикле увеличиваем его. Если в каком-либо из этих циклов произошел перебор с увеличением или уменьшением, то откатываем изменения назад и выходим из цикла.

  3. Навешиваем на событие resize исполнение этой функции. Чтобы она не вызывалась при каждом событии и чтобы не сильно нагружать браузер, добавим функцию debounce() — так она вызовется один раз спустя 250 мс после окончания события.

P.S. пример не слишком хорош, потому что будет слишком часто дергаться DOM и начинаться перерисовка страницы, так что рекомендую подумать над тем, чтобы его улучшить :-)

start();

window.addEventListener('resize', debounce(start, 250));

function getCurrentFz(selector) { let style = window.getComputedStyle(selector, null).getPropertyValue('font-size'), fontSize = parseFloat(style)

return fontSize; };

function debounce(func, wait, immediate) { let timeout; return function() { let context = this, args = arguments, later = function() { timeout = null; if (!immediate) func.apply(context, args); }, callNow = immediate && !timeout; clearTimeout(timeout); timeout = setTimeout(later, wait); if (callNow) func.apply(context, args); }; };

function start() { let body = document.body, bodyWidth = body.getBoundingClientRect().width, selectorInner = document.querySelector('h1 span'), fz = getCurrentFz(selectorInner);

if (bodyWidth > selectorInner.offsetWidth) { while (bodyWidth > selectorInner.offsetWidth) { fz += 1; selectorInner.style.fontSize = fz + 'px';

  if (bodyWidth &lt; selectorInner.offsetWidth) {
    selectorInner.style.fontSize = fz - 1 + 'px';
    break;
  }
}

} else { while (bodyWidth < selectorInner.offsetWidth) { fz -= 1; selectorInner.style.fontSize = fz + 'px';

  if (bodyWidth &gt; selectorInner.offsetWidth) {
    selectorInner.style.fontSize = fz + 1 + 'px';
    break;
  }
}

} };

h1 {
  margin: 0;
}

h1 span {
  white-space: nowrap;
}
<h1><span>Some text in header</span></h1>
0

Используйте относительные единицы rem, em. Еще можно использовать vw, вот стаття с ришением похожей проблемы как у вас. Статья

  • Спасибо за ответ, но в статье описывается решение относительно размеров окна, а rem это относительная единица значение которой объединено параметрами шрифта. То есть, если я изменю размер блока, размер шрифта останется фиксированным и никак не примет относительных значений. – DmitryZ Apr 13 '17 at 06:14
0

Например вот так:

$('.jsFontSize').each(function(){
  var fontSize = 14;
  var rowHeight = $(this).height();
  while(rowHeight>20){
      fontSize=fontSize-1;
      $(this).css({fontSize: fontSize+'px'});
      rowHeight = $(this).height();
  }
});
.wrapper {
  font-size: 14px;
  min-height: 20px;
  line-height: 20px;
}
.jsFontSize {
  display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="wrapper"> <div class="jsFontSize"> Текст текст текст текст текст текст </div> </div>

<div class="wrapper"> <div class="jsFontSize"> Текст текст текст текст текст текст Текст текст текст текст текст текст Текст текст текст текст текст текст Текст текст текст текст текст текст Текст текст текст текст текст текст </div> </div>

kizoso
  • 9,333
  • пример не работает .. как минимум в Хр и старых броузерах –  Apr 13 '17 at 12:55
  • в каком именно браузере не работает? если вы смотрите в старом ие, то нужно jquery со 2-ой заменить на 1-ую – kizoso Apr 13 '17 at 13:48
  • Нет не ие ! А яндэкс браузер в Хр , не работает а точнее текст вообще мизерного размера –  Apr 13 '17 at 14:03
  • так в этом и суть, я так и поняла, что нужно сделать, чтобы текст был в одну строчку и уменьшался относительно ширины экрана, или я не правильно поняла?) – kizoso Apr 13 '17 at 16:44
  • А я понял что типа шрифт сам уменьшиться должен, с изменением размера экрана или div –  Apr 13 '17 at 16:46
  • 1
    @kizoso Относительно блока а не экрана) Чуть позже я попробую все варианты которые мне предложили, но пока кандидатом на решение является ответ в комментарии | вот вариант еще такой - jsfiddle.net/soledar10/w34a1f0t/1, более подробно github.com/davatron5000/FitText.js - Пользователь "soledar" – DmitryZ Apr 14 '17 at 17:02