Масштабирование шрифта в зависимости от ширины контейнера
Мне трудно разобраться с масштабированием шрифтов.
У меня в настоящее время есть этот сайт с телом font-size
100%. 100% чего хотя? Это, кажется, вычислить в 16px.
У меня сложилось впечатление, что 100% будет как-то относиться к размеру окна браузера, но, очевидно, не потому, что это всегда 16px, независимо от того, уменьшено ли окно до ширины мобильного устройства или полноэкранного рабочего стола.
Как сделать так, чтобы текст на моем сайте масштабировался относительно его контейнера? Я пытался с помощью em
но это тоже не масштабируется.
Я считаю, что такие вещи, как мое меню, уменьшаются при изменении размера, поэтому мне нужно уменьшить px font-size
из .menuItem
среди других элементов по отношению к ширине контейнера. (Например, в меню на большом рабочем столе 22px работает отлично. Перейдите к ширине планшета, а 16px более подходит.)
Я знаю, что могу добавить точки останова, но я действительно хочу, чтобы текст масштабировался как ХОРОШО, чтобы иметь дополнительные точки останова, в противном случае я получу сотни точек останова на каждые 100px уменьшение ширины для управления текстом.
42 ответа
РЕДАКТИРОВАТЬ: Если контейнер не является телом CSS Tricks охватывает все ваши параметры здесь: https://css-tricks.com/fitting-text-to-a-container/
Если контейнер является телом, то вы ищете длины просмотра в процентах:
Длина области просмотра в процентах относится к размеру исходного содержащего блока. Когда высота или ширина исходного содержащего блока изменяется, они масштабируются соответственно. Однако когда значение переполнения корневого элемента равно auto, предполагается, что любые полосы прокрутки не существуют.
Значения:
vw
(% от ширины области просмотра)vh
(% от высоты окна просмотра)vi
(1% от размера области просмотра в направлении встроенной оси корневого элемента)vb
(1% от размера области просмотра в направлении оси блока корневого элемента)vmin
(меньший изvw
или жеvh
)vmax
(чем больше илиvw
или жеvh
)
1 v * равно 1% исходного содержащего блока.
используя это выглядит так:
p {
font-size: 4vw;
}
Как вы можете видеть, когда ширина области просмотра увеличивается, увеличивается и размер шрифта, без необходимости использовать медиа-запросы.
Эти значения являются единицей измерения, как px
или же em
, поэтому они могут быть использованы для определения размера других элементов, таких как ширина, поля или отступы.
Поддержка браузеров довольно хорошая, но вам, вероятно, понадобится запасной вариант, такой как:
p {
font-size: 16px;
font-size: 4vw;
}
Проверьте статистику поддержки: http://caniuse.com/.
Также ознакомьтесь с CSS-хитростями для более широкого взгляда: http://css-tricks.com/viewport-sized-typography/
Вот хорошая статья о настройке минимальных / максимальных размеров и более строгом контроле размеров: http://madebymike.com.au/writing/precise-control-responsive-typography/
А вот статья о настройке размера с помощью calc(), чтобы текст заполнял область просмотра: http://codepen.io/CrocoDillon/pen/fBJxu
Также, пожалуйста, просмотрите эту статью, которая использует технику, названную "расплавленный отвод", чтобы отрегулировать высоту линии. https://css-tricks.com/molten-leading-css/
Но что, если контейнер не является областью просмотра (телом)?
Этот вопрос задает в комментариях Алексей под принятым ответом.
Этот факт не означает vw
не может быть использован в некоторой степени для размера этого контейнера. Теперь, чтобы увидеть какое-либо изменение, нужно предположить, что контейнер каким-то образом является гибким по размеру. Будь через прямой процент width
или через 100% минус поля. Дело становится "спорным", если контейнер всегда устанавливается, скажем, 200px
широкий - тогда просто установите font-size
это работает для этой ширины.
Пример 1
Однако с контейнером с гибкой шириной необходимо понимать, что каким-то образом размер контейнера все еще находится вне области просмотра. Таким образом, это вопрос корректировки vw
установка на основе этой процентной разницы в размере в окне просмотра, что означает учет размеров родительских оболочек. Возьмите этот пример:
div {
width: 50%;
border: 1px solid black;
margin: 20px;
font-size: 16px;
/* 100 = viewport width, as 1vw = 1/100th of that
So if the container is 50% of viewport (as here)
then factor that into how you want it to size.
Let's say you like 5vw if it were the whole width,
then for this container, size it at 2.5vw (5 * .5 [i.e. 50%])
*/
font-size: 2.5vw;
}
Предполагая, что здесь div
это дитя body
, это 50%
того, что 100%
ширина, которая является размером области просмотра в этом базовом случае. По сути, вы хотите установить vw
это будет хорошо выглядеть для вас. Как вы можете видеть в моем комментарии в приведенном выше css, вы можете "обдумать" это математически относительно полного размера области просмотра, но вам не нужно это делать. Текст будет "сгибаться" с контейнером, потому что контейнер сгибается с изменением размера области просмотра. ОБНОВЛЕНИЕ: вот пример двух разных размеров контейнеров.
Пример 2
Вы можете помочь в определении размера области просмотра, форсируя вычисления, основанные на этом. Рассмотрим этот пример:
html {width: 100%;} /* force html to be viewport width */
body {width: 150%; } /* overflow the body */
div {
width: 50%;
border: 1px solid black;
margin: 20px;
font-size: 16px;
/* 100 = viewport width, as 1vw = 1/100th of that
Here, the body is 150% of viewport, but the container is 50%
of viewport, so both parents factor into how you want it to size.
Let's say you like 5vw if it were the whole width,
then for this container, size it at 3.75vw
(5 * 1.5 [i.e. 150%]) * .5 [i.e. 50%]
*/
font-size: 3.75vw;
}
Размер по-прежнему зависит от области просмотра, но по сути настраивается исходя из самого размера контейнера.
Должен ли размер контейнера меняться динамически...
Если размер элемента контейнера заканчивался динамическим изменением его процентного отношения либо через @media
точки останова или через javascript, тогда, какой бы ни была базовая "цель", потребуется пересчет, чтобы сохранить те же "отношения" для определения размера текста.
Возьмите пример № 1 выше. Если div
был переключен на 25%
ширина либо @media
или JavaScript, то в то же время font-size
необходимо будет откорректировать либо в медиа-запросе, либо с помощью javascript для нового расчета 5vw * .25 = 1.25
, При этом размер текста будет таким же, как если бы он имел ширину оригинала. 50%
Контейнер был уменьшен вдвое от размера окна просмотра, но теперь был уменьшен из-за изменения в его собственном процентном расчете.
Вызов
С помощью CSS3 calc()
использование функции, стало бы трудно настроить динамически, так как эта функция не работает для font-size
Цели в это время. Таким образом, вы не можете сделать чистую настройку CSS3, если ваша ширина меняется на calc()
, Конечно, небольшая корректировка ширины для полей может быть недостаточной, чтобы оправдать любое изменение font-size
, так что это может не иметь значения.
Решение с SVG:
<div style="width: 60px;">
<svg width="100%" height="100%" viewBox="0 -200 1000 300"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<text font-size="300" fill="black">Text</text>
</svg>
</div>
Запросы контейнера CSS
Дополнение конца 2022 года к набору функций CSS упрощает масштабирование размера шрифта с помощью контейнеров.
Запросы- контейнеры поставляются с новым набором единиц CSS / ( ширина запроса- контейнера / высота восемь). Чтобы использовать их, вам нужно установить свойство родительского элемента, размер которого вы хотите использовать. Минимальный пример:
Размер шрифта будет плавно увеличиваться по мере роста контейнера. При ширине контейнера 1000 пикселейp
размер шрифта будет1000px / 100 * 5 = 50px
.
container-type
может быть илиinline-size
.size
отслеживает как высоту, так и ширину контейнера, что позволяет использовать обаcqw
иcqh
. Большую часть времени в Интернете высота рассчитывается на основе контента, и вы указываете только ширину. Чтобы сэкономить браузеру некоторую работу, вы обычно хотите установитьcontainer-type: inline-size;
поэтому браузер отслеживает только встроенный размер, который обычно равен ширине (если вы не установитеwriting-mode
к вертикали).
Поддержка браузерами контейнерных запросов быстро росла во 2-й половине 2022 года и в настоящее время составляет 75% (01.01.2023).
В одном из моих проектов я делаю "смесь" между vw и vh, чтобы настроить размер шрифта в соответствии с моими потребностями, например:
font-size: calc(3vw + 3vh);
Я знаю, что это не отвечает на вопрос ОП, но, возможно, это может быть решением для кого-либо еще.
Чисто CSS решение с calc()
, CSS-единицы и математика
Это точно не то, что просит ОП, но может сделать чей-то день. Этот ответ не просто кормить с ложечки и нуждается в некоторых исследованиях для разработчиков.
Наконец-то я пришел, чтобы получить чистое CSS-решение для этого, используя calc()
с разными единицами. Вам нужно некоторое базовое математическое понимание формул, чтобы выработать выражение для calc()
,
Когда я решил это, мне нужно было получить отзывчивый заголовок на всю ширину страницы с некоторыми дополнениями в DOM. Я буду использовать мои значения здесь, замените их своими.
Математике
Тебе понадобится:
- в некотором окне просмотра я корректировал соотношение, я использовал 320px, таким образом, я получил 24px в высоту и 224px в ширину, поэтому соотношение составляет 9.333... или 28 / 3
- ширина контейнера у меня была
padding: 3em
и полная ширина, так что это должно100wv - 2 * 3em
X - ширина контейнера, поэтому замените его собственным выражением или измените значение, чтобы получить полностраничный текст. R - это соотношение, которое у вас будет. Вы можете получить его, настроив значения в некотором окне просмотра, проверив ширину и высоту элемента и заменив их своими собственными значениями. Кроме того, это width / heigth
;)
x = 100vw - 2 * 3em = 100vw - 6em
r = 224px/24px = 9.333... = 28 / 3
y = x / r
= (100vw - 6em) / (28 / 3)
= (100vw - 6em) * 3 / 28
= (300vw - 18em) / 28
= (75vw - 4.5rem) / 7
И взрыв! Это сработало! я написал
font-size: calc((75vw - 4.5rem) / 7)
в мой заголовок, и он корректно корректируется в каждом окне просмотра.
Но как это работает?
Нам нужны некоторые константы здесь. 100vw
означает полную ширину области просмотра, и моей целью было установить заголовок полной ширины с некоторыми отступами.
Соотношение. Получив ширину и высоту в одном окне просмотра, я получил соотношение для игры, и с отношением я знаю, какой должна быть высота в другой ширине окна просмотра. Вычисление их вручную заняло бы много времени и, по крайней мере, заняло бы много времени, так что это не очень хороший ответ.
Заключение
Интересно, почему никто не понял этого, а некоторые люди даже говорят, что с CSS невозможно было бы повозиться. Мне не нравится использовать Javascript для настройки элементов, поэтому я не принимаю JS или даже ответы JQuery, не копая больше. В общем, хорошо, что это выяснили, и это один из шагов к реализации чистого CSS в дизайне сайта.
Я прошу прощения за любое необычное соглашение в моем тексте, я не являюсь носителем английского языка, а также совершенно новичок в написании SO ответов.
Изменить: следует также отметить, что у нас есть злые полосы прокрутки в некоторых браузерах. Например, при использовании Firefox я заметил, что 100vw
означает полную ширину области просмотра, простирающуюся под полосой прокрутки (там, где контент не может расширяться!), поэтому весь текст ширины должен быть аккуратно размечен и желательно тестироваться на многих браузерах и устройствах
Есть способ сделать это без JavaScript!
Вы можете использовать встроенный SVG. Вы можете использовать CSS на SVG, если он встроен. Вы должны помнить, что использование этого метода означает, что ваш svg будет реагировать на размер своего контейнера.
Попробуйте использовать следующее решение...
HTML
<div>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 360.96 358.98" >
<text>SAVE $500</text>
</svg>
</div>
CSS
div {
width: 50%; /* set your container width */
height: 50%; /* Set your container height */
}
svg {
width: 100%;
height: auto;
}
text {
transform: translate(40px, 202px);
font-size: 62px;
fill: #000;
}
пример: https://jsfiddle.net/k8L4xLLa/32/
Хотите что-нибудь более роскошное?
SVG также позволяет делать крутые вещи с формами и мусором. Проверьте этот отличный вариант использования для масштабируемого текста...
Существует большая философия для этого вопроса. Самое простое, что можно сделать, это дать определенный размер шрифта для тела (я рекомендую 10), и тогда у всех остальных элементов будет их шрифт в em или rem. Я дам вам и пример, чтобы понять эти единицы. Эм всегда по отношению к своему родителю
body{font-size:10px;}
.menu{font-size:2em;} /* that means 2*10px = 20px */
.menu li{font-size:1.5em;} /* that means 1.5*20px = 30px */
Рем всегда относительно тела
body{font-size:10px;}
.menu{font-size:2rem;} /* that means 2*10px = 20px */
.menu li{font-size:1.5rem;} /* that means 1.5*10px = 15px */
И тогда вы могли бы создать скрипт, который бы изменял размер шрифта относительно ширины вашего контейнера. Но это не то, что я бы рекомендовал. Потому что в контейнере шириной 900px, например, у вас будет p
скажем, элемент с размером шрифта 12 пикселей. И по вашей идее, это будет в контейнере шириной 300px с размером шрифта 4px. Там должен быть нижний предел. Другое решение будет с медиа-запросами, чтобы вы могли установить шрифт для различной ширины.
Но решения, которые я бы порекомендовал, заключается в использовании библиотеки JavaScript, которая поможет вам в этом. И fittext.js, который я нашел до сих пор.
Обновлено, потому что я получил отрицательный голос.
Вот функция:
document.body.setScaledFont = function(f) {
var s = this.offsetWidth, fs = s * f;
this.style.fontSize = fs + '%';
return this
};
Затем преобразуйте все размеры шрифтов дочерних элементов ваших документов в em или%.
Затем добавьте что-то подобное в ваш код, чтобы установить базовый размер шрифта.
document.body.setScaledFont(0.35);
window.onresize = function() {
document.body.setScaledFont(0.35);
}
Это может быть не очень практично, но если вы хотите, чтобы шрифт был прямой функцией родителя, без наличия JS, который прослушивает / зацикливается (интервал) для чтения размера div / страницы, есть способ сделать это. Iframes. Все в пределах iframe будет рассматривать размер iframe как размер области просмотра. Таким образом, хитрость заключается в том, чтобы просто создать iframe, ширина которого равна максимальной ширине, которую вы хотите, чтобы ваш текст был, и чья высота равна максимальной высоте * соотношения сторон конкретного текста.
Если не принимать во внимание ограничение на то, что единицы видового экрана не могут также встречаться с боковыми родительскими единицами для текста (например, если размер% ведет себя как все остальные), единицы видового экрана действительно предоставляют очень мощный инструмент: возможность получить измерение min/max, Вы не можете сделать это где-нибудь еще - вы не можете сказать... сделайте высоту этого div равной ширине родительского * что-то.
При этом хитрость заключается в том, чтобы использовать vmin и установить размер iframe таким образом, чтобы [фракция] * общая высота была хорошим размером шрифта, когда высота является ограничивающим размером, и [дробь] * общая ширина, когда ширина является предельное измерение. Вот почему высота должна быть произведением ширины и соотношения сторон.
для моего конкретного примера у вас есть
.main iframe{
position: absolute;
top: 50%;
left: 50%;
width: 100%;
height: calc(3.5 * 100%);
background: rgba(0,0,0,0);
border-style: none;
transform: translate3d(-50%,-50%,0);
}
Небольшое неудобство с этим методом заключается в том, что вы должны вручную установить CSS для iframe. Если вы прикрепите весь CSS-файл, это займет много трафика для многих текстовых областей. Итак, что я делаю, так это прикрепляю правило, которое хочу, прямо из моего CSS.
var rule = document.styleSheets[1].rules[4];
var iDoc = document.querySelector('iframe').contentDocument;
iDoc.styleSheets[0].insertRule(rule.cssText);
Вы можете написать небольшую функцию, которая получает правило CSS / все правила CSS, которые будут влиять на текстовую область.
Я не могу думать о другом способе сделать это без некоторого JS езды на велосипеде / слушания. Реальным решением было бы для браузеров предоставить способ масштабирования текста как функции родительского контейнера И также обеспечить те же функциональные возможности типа vmin / vmax.
JS fiddle: https://jsfiddle.net/0jr7rrgm/3/(нажмите один раз, чтобы зафиксировать красный квадрат для мыши, нажмите еще раз, чтобы отпустить)
Большая часть JS в скрипке - это просто моя пользовательская функция перетаскивания мышью
С помощью vw
, em
& co. работает точно, но imo всегда нуждается в человеческом прикосновении для тонкой настройки.
Вот скрипт, который я только что написал на основе ответа @tnt-rox, который пытается автоматизировать прикосновение этого человека:
$('#controller').click(function(){
$('h2').each(function(){
var
$el = $(this),
max = $el.get(0),
el = null
;
max =
max
? max.offsetWidth
: 320
;
$el.css({
'font-size': '1em',
'display': 'inline',
});
el = $el.get(0);
el.get_float = function(){
var
fs = 0
;
if (this.style && this.style.fontSize) {
fs = parseFloat(this.style.fontSize.replace( /([\d\.]+)em/g, '$1' ));
}
return fs;
};
el.bigger = function(){
this.style.fontSize = (this.get_float() +0.1) +'em';
};
while ( el.offsetWidth < max ) {
el.bigger();
}
// finishing touch.
$el.css({
'font-size': ((el.get_float() -0.1) +'em'),
'line-height': 'normal',
'display': '',
});
}); // end of ( each )
}); // end of ( font scaling test )
div {
width: 50%;
background-color: tomato;
font-family: 'Arial';
}
h2 {
white-space: nowrap;
}
h2:nth-child(2) {
font-style: italic;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input type="button" id="controller" value="Apply" />
<div>
<h2>Lorem ipsum dolor</h2>
<h2>Test String</h2>
<h2>Sweet Concatenation</h2>
<h2>Font Scaling</h2>
</div>
Это в основном уменьшает размер шрифта до 1em
и затем начинает увеличиваться на 0,1, пока не достигнет максимальной ширины.
Используйте CSS-переменные
Никто еще не упомянул CSS-переменные, и этот подход работал лучше всего для меня, поэтому:
Допустим, на вашей странице есть столбец, который на 100% ширины экрана мобильного пользователя, но имеет max-width
800px, так что на рабочем столе есть место по обе стороны от столбца. Поместите это в верхней части вашей страницы:
<script> document.documentElement.style.setProperty('--column-width', Math.min(window.innerWidth, 800)+'px'); </script>
И теперь вы можете использовать эту переменную (вместо встроенного vw
блок), чтобы установить размер вашего шрифта. Например
p {
font-size: calc( var(--column-width) / 100 );
}
Это не чистый подход CSS, но это довольно близко.
100% по отношению к базовому размеру шрифта, который, если вы не установите его, будет по умолчанию пользовательским агентом браузера.
Чтобы получить желаемый эффект, я бы использовал кусочек JavaScript, чтобы отрегулировать базовый размер шрифта относительно размеров окна.
С художественной точки зрения, если вам нужно уместить две или более строк текста одинаковой ширины, независимо от количества их символов, у вас есть хорошие варианты.
Лучше всего найти динамическое решение, чтобы при вводе текста мы получали красивое отображение.
Посмотрим, как мы можем подойти.
var els = document.querySelectorAll(".divtext"),
refWidth = els[0].clientWidth,
refFontSize = parseFloat(window.getComputedStyle(els[0],null)
.getPropertyValue("font-size"));
els.forEach((el,i) => el.style.fontSize = refFontSize * refWidth / els[i].clientWidth + "px")
#container {
display: inline-block;
background-color: black;
padding: 0.6vw 1.2vw;
}
.divtext {
display: table;
color: white;
font-family: impact;
font-size: 4.5vw;
}
<div id="container">
<div class="divtext">THIS IS JUST AN</div>
<div class="divtext">EXAMPLE</div>
<div class="divtext">TO SHOW YOU WHAT</div>
<div class="divtext">YOU WANT</div>
</div>
Все, что мы делаем, это получаем ширину (els[0].clientWidth
) и размер шрифта (parseFloat(window.getComputedStyle(els[0],null).getPropertyValue("font-size"))
) первой строки в качестве ссылки, а затем просто рассчитайте размер шрифта последующих строк соответственно.
Мое собственное решение, основанное на jQuery, работает путем постепенного увеличения размера шрифта до тех пор, пока контейнер не увеличится в высоту (что означает, что он получил разрыв строки). Это довольно просто, но работает довольно хорошо и очень прост в использовании. Вы не должны знать НИЧЕГО об используемом шрифте, все заботится браузером.
Вы можете поиграть с ним на http://jsfiddle.net/tubededentifrice/u5y15d0L/2/
Волшебство происходит здесь:
var setMaxTextSize=function(jElement) {
//Get and set the font size into data for reuse upon resize
var fontSize=parseInt(jElement.data(quickFitFontSizeData)) || parseInt(jElement.css("font-size"));
jElement.data(quickFitFontSizeData,fontSize);
//Gradually increase font size until the element gets a big increase in height (ie line break)
var i=0;
var previousHeight;
do
{
previousHeight=jElement.height();
jElement.css("font-size",""+(++fontSize)+"px");
}
while(i++<300 && jElement.height()-previousHeight<fontSize/2)
//Finally, go back before the increase in height and set the element as resized by adding quickFitSetClass
fontSize-=1;
jElement.addClass(quickFitSetClass).css("font-size",""+fontSize+"px");
return fontSize;
};
Я подготовил простую функцию масштабирования, используя преобразование CSS вместо font-size. Вы можете использовать его внутри любого контейнера, вам не нужно задавать медиа-запросы и т. Д.:)
Сообщение в блоге: https://blog.polarbits.co/2017/03/07/full-width-css-js-scalable-header/
Код:
function scaleHeader() {
var scalable = document.querySelectorAll('.scale--js');
var margin = 10;
for (var i = 0; i < scalable.length; i++) {
var scalableContainer = scalable[i].parentNode;
scalable[i].style.transform = 'scale(1)';
var scalableContainerWidth = scalableContainer.offsetWidth - margin;
var scalableWidth = scalable[i].offsetWidth;
scalable[i].style.transform = 'scale(' + scalableContainerWidth / scalableWidth + ')';
scalableContainer.style.height = scalable[i].getBoundingClientRect().height + 'px';
}
}
Рабочая демонстрация: https://codepen.io/maciejkorsan/pen/BWLryj
Внутри вашего CSS попробуйте добавить это внизу, изменяя ширину 320 пикселей, где бы ваш дизайн не ломался:
@media only screen and (max-width: 320px) {
body { font-size: 1em; }
}
Затем укажите желаемый размер шрифта в "px" или "em".
Вы пробовали http://simplefocus.com/flowtype/?
Это то, что я использую для своих сайтов и отлично сработало. Надеюсь, поможет.
Этот веб-компонент изменяет размер шрифта, чтобы ширина внутреннего текста соответствовала ширине контейнера. Проверьте демо.
Вы можете использовать это так:
<full-width-text>Lorem Ipsum</full-width-text>
Ты ищешь что-то подобное? =>
http://jsfiddle.net/sijav/dGsC9/4/
http://fiddle.jshell.net/sijav/dGsC9/4/show/
Я использовал flowtype, и он отлично работает (однако это JS, а не чистое решение CSS)
$('body').flowtype({
minFont : 10,
maxFont : 40,
minimum : 500,
maximum : 1200,
fontRatio : 70
});
Я был очень разочарован, пытаясь добиться плотного обтекания текста, поэтому в итоге я использовал метод на основе холста, к которому я пришел, безуспешно пробуя другие методы. То, к чему я стремился, похоже на прилагаемое, что оказалось на удивление трудным (для меня). Надеюсь, однажды у нас будет простой способ сделать это только с помощью CSS. Недостатком этого подхода является то, что текст обрабатывается больше как изображение, но для некоторых случаев использования это нормально.
https://codesandbox.io/s/create-a-canvas-tightly-holding-a-word-st2h1?file=/index.html
Это изображение представляет собой снимок экрана с макетом CSS Grid из четырех холстов без полей.
Вот чистое решение CSS с пониманием того, что вы признаете, что точки останова необходимы, но также хотите масштабировать текст:
Я знаю, что могу добавить точки останова, но я действительно хочу, чтобы текст масштабировался, а также имел дополнительные точки останова, иначе....
Вот подход, использующий:
- Пользовательские свойства
- Медиа-запросы для точек останова
- ( поддержка браузера в феврале 2022 года довольно хорошая — 93%)
calc()
Если для управления ВСЕМ масштабированием текста внутри контейнера на экране можно использовать один общий коэффициент масштабирования , все, что вам нужно сделать, — это масштабировать пользовательское свойство на каждом экране.
Базовая настройка начинается так:
:root {
--scaling-factor: 1
}
.parent {
font-size: 30px
}
.largest {
font-size: clamp(60%, calc(var(--scaling-factor) * 100%), 100%);
}
.middle {
font-size: clamp(60%, calc(var(--scaling-factor) * 85%), 100%);
}
.smallest {
font-size: clamp(60%, calc(var(--scaling-factor) * 70%), 100%);
}
Затем вложите свои медиа-запросы примерно так (или что вам нужно для ваших точек останова):
@media (max-width: 1200px) {
:root {
--scaling-factor: 0.9
}
@media (max-width: 800px) {
:root {
--scaling-factor: 0.8
}
@media (max-width: 600px) {
:root {
--scaling-factor: 0.5 /* nope, because the font-size is floored at 60% thanks to clamp() */
}
}
}
}
Это минимизирует разметку вашего медиа-запроса.
Преимущества
- Одно пользовательское свойство управляет ВСЕМ масштабированием... нет необходимости добавлять несколько объявлений для каждой точки останова мультимедиа
- Использование
устанавливает нижний предел того, что должно быть, поэтому вы гарантируете, что ваш текст никогда не будет слишком маленьким (здесь нижний предел составляет 60% от родительского)
См. этот JSFiddle для демонстрации. Измените размер окна до тех пор, пока при наименьшей ширине все абзацы не станут одинаковыми.
Моя проблема была похожа, но связана с масштабированием текста внутри заголовка. Я попробовал Fit Font, но мне нужно было включить компрессор, чтобы получить какие-либо результаты, так как он решал немного другую проблему, как Text Flow. Поэтому я написал свой собственный маленький плагин, который уменьшает размер шрифта, чтобы соответствовать размеру контейнера, предполагая, что у вас есть overflow: hidden
а также white-space: nowrap
так что даже если сокращение шрифта до минимума не позволяет отобразить полный заголовок, оно просто отсекает то, что может показать.
(function($) {
// Reduces the size of text in the element to fit the parent.
$.fn.reduceTextSize = function(options) {
options = $.extend({
minFontSize: 10
}, options);
function checkWidth(em) {
var $em = $(em);
var oldPosition = $em.css('position');
$em.css('position', 'absolute');
var width = $em.width();
$em.css('position', oldPosition);
return width;
}
return this.each(function(){
var $this = $(this);
var $parent = $this.parent();
var prevFontSize;
while (checkWidth($this) > $parent.width()) {
var currentFontSize = parseInt($this.css('font-size').replace('px', ''));
// Stop looping if min font size reached, or font size did not change last iteration.
if (isNaN(currentFontSize) || currentFontSize <= options.minFontSize ||
prevFontSize && prevFontSize == currentFontSize) {
break;
}
prevFontSize = currentFontSize;
$this.css('font-size', (currentFontSize - 1) + 'px');
}
});
};
})(jQuery);
Попробуйте использовать плагин fitText, потому что размеры Viewport не являются решением этой проблемы. Просто добавьте библиотеку
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="jquery.fittext.js"></script>
и изменить размер шрифта для правильной настройки параметров текста:
$("#text_div").fitText(0.8);
Вы можете установить максимальные и минимальные значения текста:
$("#text_div").fitText(0.8, { minFontSize: '12px', maxFontSize: '36px' });
Всегда имейте свой элемент с этим атрибутом:
Javascript: element.style.fontSize = "100%";
или же
CSS: style = "font-size: 100%;"
Когда вы переходите в полноэкранный режим, у вас уже должна быть рассчитана переменная масштаба (масштаб> 1 или масштаб = 1). Затем на весь экран:
document.body.style.fontSize = (scale * 100) + "%";
Это работает хорошо с небольшим кодом.
Взгляните на мой код, он делает font size smaller
в fit
что там
но я думаю, что это не привело к хорошему пользовательскому опыту
var containerWidth = $("#ui-id-2").width();
var items = $(".quickSearchAutocomplete .ui-menu-item");
var fontSize = 16;
items.each(function(){
//display value depend sometimes on your case you may make it block or inline-table instead of inline-block or whatever value that make the div take overflow width
$(this).css({"whiteSpace":"nowrap","display":"inline-block"});
while ($(this).width() > containerWidth){
console.log("$(this).width()"+ $(this).width() + "containerWidth" + containerWidth)
$(this).css("font-size", fontSize -= 0.5);
}
});
надеюсь, это поможет вам
Это сработало для меня:
Я пытаюсь приблизить размер шрифта на основе ширины / высоты, полученной при установке размера шрифта: 10 пикселей. По сути, идея такова: "если у меня ширина 20 пикселей и высота 11 пикселей с размером шрифта: 10 пикселей, то какой будет максимальный размер шрифта для вычисления контейнера шириной 50 пикселей и высотой 30 пикселей?"
Ответ - система двойной пропорции:
{20: 10 = 50: X, 11: 10 = 30: Y} = {X = (10 * 50) / 20, Y = (10 * 30) / 11}
Теперь X - это размер шрифта, который будет соответствовать ширине, Y - это размер шрифта, который будет соответствовать высоте; принять наименьшее значение
function getMaxFontSizeApprox(el){
var fontSize = 10;
var p = el.parentNode;
var parent_h = p.offsetHeight ? p.offsetHeight : p.style.pixelHeight;
if(!parent_h)parent_h = 0;
var parent_w = p.offsetHeight ? p.offsetWidth : p.style.pixelWidth;
if(!parent_w)parent_w = 0;
el.style.fontSize = fontSize + "px";
var el_h = el.offsetHeight ? el.offsetHeight : el.style.pixelHeight;
if(!el_h)el_h = 0;
var el_w = el.offsetHeight ? el.offsetWidth : el.style.pixelWidth;
if(!el_w)el_w = 0;
//0.5 is the error on the measure that js does
//if real measure had been 12.49 px => js would have said 12px
//so we think about the worst case when could have, we add 0.5 to
//compensate the round error
var fs1 = (fontSize*(parent_w + 0.5))/(el_w + 0.5);
var fs2 = (fontSize*(parent_h) + 0.5)/(el_h + 0.5);
fontSize = Math.floor(Math.min(fs1,fs2));
el.style.fontSize = fontSize + "px";
return fontSize;
}
NB: аргумент функции должен быть элементом span или элементом, который меньше своего родителя, в противном случае, если у детей и у родителя одинаковая функция width/height, произойдет сбой
Для динамического текста этот плагин весьма полезен http://freqdec.github.io/slabText/. Просто добавьте CSS
.slabtexted .slabtext
{
display: -moz-inline-box;
display: inline-block;
white-space: nowrap;
}
.slabtextinactive .slabtext
{
display: inline;
white-space: normal;
font-size: 1em !important;
letter-spacing: inherit !important;
word-spacing: inherit !important;
*letter-spacing: normal !important;
*word-spacing: normal !important;
}
.slabtextdone .slabtext
{
display: block;
}
и сценарий
$('#mydiv').slabText();
HTML
<div style="height:100px; width:200px;">
<div id='qwe'>
test
</div>
</div>
Код JavaScript для максимизации размера шрифта:
el = document.getElementById('qwe');
maxFontPixels = 50;
maxHeight = el.parentElement.offsetHeight;
fontSize = Number(maxFontPixels || maxHeight);
el.style.width = '100%';
el.style.overflowWrap = 'break-word';
var minFS = 3, maxFS = fontSize;
while (fontSize != minFS) {
el.style.fontSize = `${fontSize}px`;
if (el.offsetHeight < maxHeight) {
minFS = fontSize;
}
else {
maxFS = fontSize;
}
fontSize = Math.floor((minFS + maxFS)/2);
}
el.style.fontSize = `${minFS}px`;
В случае, если это кому-нибудь пригодится, большинство решений в этой теме заключалось в переносе текста в несколько строк в форме e.
Но потом я нашел это, и это сработало:
https://github.com/chunksnbits/jquery-quickfit
Пример использования:
$('.someText').quickfit({max:50,tolerance:.4})