Масштабування шрифту залежно від ширини контейнера


1185

Мені важко обійтися масштабуванням шрифту.

На даний момент у мене є цей сайт із font-size100%. 100% що хоч? Здається, це обчислюється в 16 пікселів.

У мене було враження, що на 100% якимось чином посилається на розмір вікна браузера, але, мабуть, не тому, що це завжди 16 пікселів, незалежно від того, чи вікно буде змінено вниз до мобільної ширини або повнорозмірного широкоекранного робочого столу.

Як я можу зробити текст у масштабі свого сайту стосовно його контейнера? Я намагався використовувати em, але це також не масштабує.

Мої міркування полягають у тому, що такі речі, як моє меню, стають чіткішими, коли ви змінюєте розмір, тому мені потрібно зменшити px font-sizeкількість .menuItemінших елементів стосовно ширини контейнера. (Наприклад, у меню на великому робочому столі 22pxпрацює відмінно. Перемістіть вниз на ширину планшета і 16pxце більше.)

Я усвідомлюю, що можу додати точки перерви, але дуже хочу, щоб текст міг масштабуватися, а також мати додаткові точки прориву, інакше я закінчуватимуться сотнями точок перериву на кожні 100 пікселів зменшення ширини для керування текстом.


34
font-size: 100%;означає 100% розміру тексту, який би був текст (тобто той, який він успадковує від свого батьківського). За замовчуванням це 16 пікселів. Тож якщо ви використали 50%, це буде розмір шрифту: 8px
Енді

31
Те, що ви шукаєте, називається типографією, що реагує на екран, або розміром із переглядом. css-tricks.com/viewport-sized-typography
gearsdigital

8
Дайте FitText вид.
Патси Ісса

12
@Andy: Насправді "за замовчуванням" - це те, що у користувачів встановлено розмір тексту в браузері, який не обов'язково може дозволити 16 пікселів.
ScottS

1
прийняти погляд на цю відповідь stackoverflow.com/a/28485608/4251431
Башир Аль-MOMANI

Відповіді:


1494

РЕДАКТУВАННЯ: Якщо контейнер не є тілом CSS трюки, охоплює всі ваші параметри в " Вміст тексту" в контейнер .

Якщо контейнер - це тіло, то ви шукаєте відсоток перегляду :

Довжина перегляду в процентному співвідношенні відносно розміру початкового блоку, що містить . При зміні висоти або ширини початкового блоку вони відповідно змінюються. Однак, коли значення переповнення кореневого елемента є автоматичним, будь-які смуги прокрутки вважаються відсутніми.

Значення:

  • vw (% від ширини вікна перегляду)
  • vh (% від висоти вікна перегляду)
  • vi (1% від розміру вікна перегляду в напрямку осі кореневого елемента)
  • vb (1% розміру вікна перегляду в напрямку осі блоку кореневого елемента)
  • vmin(менший vwабо vh)
  • vmax(більший vwабо vh)

1 v * дорівнює 1% від початкового блоку, що містить.

Його використання виглядає приблизно так:

p {
    font-size: 4vw;
}

Як ви бачите, коли ширина вікна перегляду збільшується, це роблять font-size, не використовуючи медіа-запити.

Ці значення є одиницею розміру, як pxі em, тому їх можна використовувати і для розміру інших елементів, таких як ширина, запас або прокладка.

Підтримка веб-переглядача досить хороша, але вам, швидше за все, знадобиться резервна версія, наприклад:

p {
    font-size: 16px;
    font-size: 4vw;
}

Перегляньте статистику підтримки: http://caniuse.com/#feat=viewport-units .

Крім того, ознайомтеся з CSS-трюками для більш широкого погляду: Viewport Sized Typography

Ось приємна стаття про встановлення мінімальних / максимальних розмірів та здійснення трохи більшого контролю над розмірами: Точний контроль за чуйною типографією

Ось стаття про встановлення вашого розміру за допомогою calc (), щоб текст заповнював вікно перегляду: http://codepen.io/CrocoDillon/pen/fBJxu

Також перегляньте цю статтю, яка також використовує техніку, яка називається "розплавлений провідний", щоб регулювати висоту лінії. Лінійний лідер в CSS


547
Але що робити, якщо контейнер не є вікном перегляду (тілом)?
Олексій

12
@ Алекс, це територія JS. Спробуйте FitText.jsальтернативу, надану в нижній частині статті @jbenjohnson, що постачається.
Роберт

10
Тут наводяться так звані запити елементів. На відміну від медіа-запитів, елементи запиту розміщуватимуть речі на основі блоку, що містить його, а не вікна перегляду, що було б дивовижно! Але, на жаль, його ще немає. Однак деякі поліфіли та доказові концепції існують, якщо вас цікавить: coding.smashingmagazine.com/2013/06/25/… та filamentgroup.com/lab/element_query_workarounds
jbenjohnson

139
Понижений, тому що це не відповідає на питання. Він запитав про контейнер, а не про вікно. Зовсім інший випадок використання.
SongBox

6
"початковий блок містить" відноситься до кореневого елемента. Це не правильна відповідь на поставлене запитання.
Гліф

319

Але що робити, якщо контейнер не є вікном перегляду (тілом)?

Це запитання задається у коментарі Олексія під прийнятою відповіддю .

Цей факт не означає, що 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%контейнера була зменшена вдвічі від розміру вікна перегляду, але тепер була зменшена через зміну власного відсоткового обчислення.

Змагання

При використанні calc()функції CSS3 буде важко динамічно регулюватись, оскільки ця функція наразі не працює для font-sizeцілей. Таким чином, ви не можете виконати чисте регулювання CSS 3, якщо ваша ширина змінюється calc(). Звичайно, незначне регулювання ширини поля може бути недостатньо для того, щоб гарантувати будь-які зміни font-size, тому це може не мати значення.


(Існує помилка Chrome із відсотковою довжиною перегляду та зміною розміру вікна: code.google.com/p/chromium/isissue/detail?id=124331 )
тридцятьдо

@thirtydot: Це прикро (але добре знати, дякую). Сподіваюся, що помилка швидко вирішиться, але схоже, що вона зберігається вже деякий час.
ScottS

20
Чудова відповідь, однак, вона не спрацює, якщо елемент, що містить, має максимальну ширину.
Гімматори

3
@ KristofferNolgren: Це стосується двох моментів у моїй відповіді: (1) "припускаючи, що контейнер якимось чином є гнучким за розміром" (коли досягається "максимальна ширина", вона більше не згинається, тому виникає проблема ). (2) Якщо можна визначити, в якій точці буде досягнута "максимальна ширина", то, як я зазначив, ви можете встановити точку @mediaперерви, щоб змінити розмір шрифту в цій точці (по суті, надавши йому фіксований розмір при досягненні max-width) . Просто думка працювати з max-widthситуацією.
ScottS

Як ви думаєте, ви можете створити загадку про те, коли елемент контейнера динамічно змінюється за допомогою медіа-запитів? Я не впевнений, що розумію.
J82

58

Рішення з 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>

https://jsfiddle.net/qc8ht5eb/


Рішення за допомогою SVG та обгортання тексту за допомогою foreignObject:

<svg viewBox="0 0 100 100">
  <foreignObject width="100%" height="100%">
    <h1>heading</h1>

    lorem ipsum dolor sit amet
  </foreignObject>
</svg> 

https://jsfiddle.net/2rp1q0sy/


1
Ця ідея спочатку виглядає приємно. Тоді ви зрозумієте, що не можете легко керувати шрифтом у SVG всередині <html>. Шрифт відрізняється на мобільному та настільному комп’ютері, що впливає на остаточну ширину.
Стопі

@Stopi, що ви думаєте про рішення iFrame? приклад
Дантіо

10
Ви можете повністю стилізувати SVG з HTML / CSS
gman

1
SVG можна стилізувати за допомогою css, якщо SVG вбудований (не використовуйте тег img).

8
Це найкраще, найбільш передбачуване рішення, яке масштабується на основі динамічного контейнера.
ДжошуаДавид

35

В одному з моїх проектів я використовую "суміш" між vw і vh, щоб налаштувати розмір шрифту під мої потреби, наприклад:

font-size: calc(3vw + 3vh);

Я знаю, що це не відповідає на питання ОП, але, можливо, це може бути вирішенням для будь-кого іншого.


3
Можливо, вам буде краще використовувати vminта / або vmaxзамість цього.
sebastian_k

4
chrome dev tools називає це недійсним значенням властивості
phil294,

29

Pure-CSS рішення з calc(), CSS одиницями та математикою

Це точно не те, що просить ОП, але може зробити день когось. Ця відповідь не є годуванням ложкою легко і потребує певного дослідження щодо кінця розробника.

Нарешті я прийшов, щоб отримати чисте CSS рішення для цього за calc()допомогою різних одиниць. Вам знадобиться базове математичне розуміння формул, щоб виробити своє вираження calc().

Коли я це опрацював, мені довелося отримати заголовок на повну ширину сторінки з декількома батьками в DOM. Я тут використаю свої цінності, заміню їх своїми.

До математики

Ви будете потребувати:

  • Добре відрегульоване співвідношення в деякому вікні перегляду. Я використав 320 пікселів, таким чином я отримав 24 пікселів у висоту та 224 пікселів у ширину, тому співвідношення становить 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 для коригування елементів, тому я не приймаю відповіді на JavaScript (і забуваю про jQuery), не копаючи більше. Загалом, добре, що це з’ясувалося, і це один крок до впровадження чистого CSS у дизайні веб-сайтів.

Прошу вибачення за будь-яку незвичну умову в моєму тексті, я не є носієм англійської мови та я також абсолютно новачок у написанні відповідей на стек переповнення.

Слід також зазначити, що в деяких браузерах є злі смуги прокрутки. Наприклад, під час використання Firefox я помітив, що це 100vwозначає повну ширину вікна перегляду, що розширюється під панеллю прокрутки (там, де вміст не може розширюватися!), Тому текст повної ширини повинен бути ретельно обмежений і бажано пройти тестування з багатьма браузерами та пристроями.


13
Це рішення працює лише якщо (1) ви знаєте шрифт, (2) шрифт доступний на пристрої користувача, і (3) текст завжди однаковий. Це робить його дуже обмеженим випадком використання.
Андрій Волгін

я не розумію, що робити, якщо мій контейнер виправлений, наприклад: 640px і співвідношення 16: 9. які кальку я повинен написати?
pery mimon

1
Ваша ширина контейнера x- 640 пікс., А співвідношення r16: 9, тому: x = 640px, r = 16 / 9, y = x / r = 640px / (16 / 9) = 360px
гегез

Примітка. Це працює лише в тому випадку, якщо у вас є текст розміром 16: 9, що є незвичайною ситуацією. Можливо, читання відповіді вдруге може допомогти. Також це працює лише для однокласників.
гегез

Якщо чесно, ви не пояснюєте "Гарненько відрегульоване співвідношення в якомусь оглядовому вікні. Я використав 320 пікселів. Таким чином, я отримав 24 пікселів у висоту та 224 пікселя в ширину, тому співвідношення становить 9,333 ... або 28/3", я пропоную пояснити співвідношення трохи більше. Що таке співвідношення?
3limin4t0r

28

Існує велика філософія цього питання.

Найпростіше зробити це надати тілу певний розмір шрифту (я рекомендую 10), і тоді всі інші елементи мали б свій шрифт у emабо rem. Я надам вам приклад для розуміння цих підрозділів. Emзавжди відносно свого батька:

body{font-size: 10px;}
.menu{font-size: 2em;} /* That means 2*10 pixels  = 20 pixels */
.menu li{font-size: 1.5em;} /* That means 1.5*20 pixels = 30 pixels */

Rem завжди відносно тіла:

body{font-size: 10px;}
.menu{font-size: 2rem;} /* That means 2*10 pixels = 20 pixels */
.menu li{font-size: 1.5rem;} /* that means 1.5*10 pixels = 15 pixels */

І тоді ви можете створити скрипт, який змінив би розмір шрифту відносно ширини контейнера. Але це не те, що я рекомендував би. Тому що, наприклад, у контейнері шириною 900 пікселів у вас був би pелемент з розміром шрифту 12 пікселів. І по вашій ідеї, що став би контейнером шириною 300 пікселів розміром шрифту 4 пікселів. Має бути нижня межа.

Інші рішення стосуються медіа-запитів, щоб ви могли встановити шрифт різної ширини.

Але я рекомендую рішення використовувати бібліотеку JavaScript, яка допоможе вам у цьому. І fittext.js, який я знайшов поки що.


6
remПристрій щодо кореневої елемент, тобто htmlелемент, а НЕ bodyелемент. Кореневим елементом у DOM є htmlтег. developer.mozilla.org/en-US/docs/Web/CSS/length .. remзавжди відносно htmlтегу, який є кореневим елементом, а не тегом body .., але гарною відповіддю :)
Jonathan Marzullo

fittext.js робить роботу виконаною, я рекомендував це рішення!
Jacek Dziurdzikowski

FitText був для мене переможцем. Спробував декілька альтернатив, але це видалося найпростішим, а також добре поєдналося з CMS Drupal / Backdrop. github.com/davatron5000/FitText.js
допоміжний Джоель

23

Ось функція:

document.body.setScaledFont = function(f) {
  var s = this.offsetWidth, fs = s * f;
  this.style.fontSize = fs + '%';
  return this
};

Потім конвертуйте всі розміри шрифту дочірнього елемента в документах у ems або %.

Потім додайте щось подібне до свого коду, щоб встановити базовий розмір шрифту.

document.body.setScaledFont(0.35);
window.onresize = function() {
    document.body.setScaledFont(0.35);
}

http://jsfiddle.net/0tpvccjt/


1
Поки це найкраще рішення. Короткий і легкий
wp студент

Погані практики та сильно неефективні
Джек Гіффін

@tntrox Наскільки неефективний, як сьогодні, це було набагато неефективніше 4 роки тому. Я відкидаю цю відповідь замість набагато кращих альтернатив. Так, для підтримки IE потрібен Javascript. Але, не потрібен Javascript, який такий жахливий.
Джек Гіффін

3
Я здогадуюсь, тут проявляється моє незнання. Але ЧОМУ вищесказане страшне?

Я не думаю, що це страшно. Я рекомендую деякі незначні зміни форматування, щоб зробити його більш читабельним. Я хотів би поставити кожен var на окремий рядок принаймні. Можливо, це не буде потрібно return thisв кінці функції. Для продуктивності ви також можете скасувати розмір onresize, щоб він не перемальовувався під час перетягування. Це досить простий код, тому хтось міг базуватись на своєму вдосконаленому рішенні з невеликими зусиллями.
Mnebuerquo

19

Є спосіб зробити це без 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-зображення також дозволяють робити круті речі з формами і сміттям. Перевірте цей чудовий варіант використання масштабованого тексту ...

https://jsfiddle.net/k8L4xLLa/14/


4
Це рішення не відрізняється від прийнятого з vwрозміром. якщо ви зміните текст, все виходить зв'язане.
N69S

14

Це може бути не надто практично, але якщо ви хочете, щоб шрифт був прямою функцією батьків, не маючи JavaScript, який слухає / циклі (інтервал), щоб прочитати розмір div / page, є спосіб зробити це . Іфрейми.

Все, що знаходиться у кадрі iframe, вважатиме розмір iframe як розмір вікна перегляду. Таким чином, фокус полягає в тому, щоб просто зробити рамку, ширина якої - максимальна ширина, яку ви хочете, щоб ваш текст був, а висота якої дорівнює максимальній висоті * конкретного співвідношення сторін тексту.

Відміняючи обмеження, що одиниці огляду також не можуть надходити поряд із сторонніми батьківськими одиницями для тексту (як, наприклад, маючи% розміру поводитись, як і всі інші), оглядові одиниці забезпечують дуже потужний інструмент: можливість отримати мінімальний / максимальний розмір . Ви не можете цього робити більше ніде - ви не можете сказати ... зробіть висоту цього діва шириною батьківського * чогось.

При цьому, фокус полягає у використанні 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, які впливали б на область тексту.

Я не можу придумати інший спосіб зробити це, не маючи деякого циклічного / прослуховування JavaScript. Справжнє рішення полягало б у тому, щоб браузери запропонували спосіб масштабування тексту як функції батьківського контейнера, а також забезпечити ту ж функціональність типу vmin / vmax.

JSFiddle: https://jsfiddle.net/0jr7rrgm/3/ (клацніть один раз, щоб заблокувати червоний квадрат мишкою та натисніть ще раз, щоб звільнити)

Більшість JavaScript у скрипці - це лише моя спеціальна функція перетягування кліків.


@quemeful Не так, коли ми запроваджуємо атрибут 'new' та 'shiny' (барабанне прохання, будь ласка ...) srcdoc: jsfiddle.net/wauzgob6/3
Jack Giffin

9

Використання 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, поки не досягне максимальної ширини.

JSFiddle


1
+1 лише для того, хто визнає, що emsпотребують людського дотику та вертикального ритму - це не якась чаклунка.
serraosays

7

100% відносно базового розміру шрифту, який, якщо ви його не встановили, був би типовим користувачем-агентом браузера.

Для отримання ефекту, який ви шукаєте, я б скористався фрагментом коду JavaScript, щоб відрегулювати розмір базового шрифту щодо розмірів вікна.


7

Всередині свого CSS спробуйте додати це внизу, змінивши ширину 320 пікселів на те місце, де ваш дизайн починає ламатися:

    @media only screen and (max-width: 320px) {

        body { font-size: 1em; }

    }

Потім введіть розмір шрифту в "px" або "em" за вашим бажанням.


7

Моє власне рішення, засноване на 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 (i.e. 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;
};

1
Оскільки цей скрипт працюватиме на кожній події розміру та / або зміні орієнтації, я не рекомендую його використовувати. Замість використання рішення на основі JavaScript шукайте рішення на основі css, як зазначено вище.
Пілат

1
Зміни розміру та орієнтації - це "рідкісні" події, тут немає жодних проблем з продуктивністю. Якщо ви хочете, не пов'язуйте з подіями (якщо вони не змінюють розмір контейнерів, наприклад, для веб-сайтів, що не реагують на чутливість). CSS-рішення працюють не у всіх випадках, не думаючи ні про що (наприклад, про ширину шрифту чи так), як це робить.
Вінсент

Я пояснив вашу відповідь функцією jQuery. Він отримує максимально дозволену висоту, хв та макс. Розміри шрифту. Дивіться jsfiddle.net/oriadam/qzsy760k
oriadam



6

Я підготував просту функцію масштабування, використовуючи перетворення CSS замість розміру шрифту. Ви можете використовувати його всередині будь-якого контейнера, не потрібно встановлювати медіа-запити тощо. :)

Повідомлення в блозі: Повна ширина масштабованого заголовка CSS та JS

Код:

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.
m02ph3u5

5

Використовуйте змінні CSS

Ще ніхто не згадав змінні CSS, і цей підхід для мене працював найкраще, тому:

Скажімо, у вас на сторінці стовпець, який становить 100% від ширини екрану користувача мобільного телефону, але має max-width800 пікселів, тому на робочому столі є місце з обох боків стовпця. Розмістіть це вгорі сторінки:

<script> document.documentElement.style.setProperty('--column-width', Math.min(window.innerWidth, 800)+'px'); </script>

Тепер ви можете використовувати цю змінну (замість вбудованого vwблоку) для встановлення розміру вашого шрифту. Напр

p {
  font-size: calc( var(--column-width) / 100 );
}

Це не чистий підхід CSS, але він досить близький.


5

Спробуйте http://simplefocus.com/flowtype/ . Це те, що я використовую для своїх сайтів, і воно спрацювало чудово.


Посилання нестабільні. Будь ласка, поясніть рішення прямо у своїй відповіді. Також я не хочу натискати на якусь випадкову посилання з будь-яким вмістом.
lilalinux

5

Моя проблема була схожа, але пов’язана зі масштабуванням тексту в заголовку. Я спробував 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);

5

У художньому плані, якщо вам потрібно помістити два чи більше рядків тексту в межах однієї ширини незалежно від їх кількості символів, то у вас є хороші варіанти.

Найкраще знайти динамічне рішення, щоб будь-який текст вводився, ми в кінцевому підсумку маємо приємний дисплей.

Подивимось, як ми можемо підійти.

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"))) першого рядка як орієнтир, а потім просто обчислити розмір шрифту наступних рядків відповідно.


4

Спробуйте використовувати плагін fitText , оскільки розміри Viewport не є вирішенням цієї проблеми.

Просто додайте бібліотеку:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>

І змінити розмір шрифту на правильний, встановивши коефіцієнт тексту:

$("#text_div").fitText(0.8);

Ви можете встановити максимальні та мінімальні значення тексту:

$("#text_div").fitText(0.8, { minFontSize: '12px', maxFontSize: '36px' });

Це корисно лише для тексту з великим відображенням і не рекомендується для абзаців.
Шив

3

Погляньте на мій код. Це робить font size smallerна fitте , що там.

Але я думаю, що це не призводить до хорошого користувальницького досвіду

var containerWidth = $("#ui-id-2").width();
var items = $(".quickSearchAutocomplete .ui-menu-item");
var fontSize = 16;

items.each(function(){
    // Displaying a value depends 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);
    }
});

Результат


2

Як резервний модуль JavaScript (або єдине рішення) ви можете використовувати мій плагін jQuery Scalem , який дозволяє масштабувати відносно батьківського елемента (контейнера), передаючи referenceпараметр.


2

Якщо це комусь корисно, більшість рішень у цій темі були загортанням тексту у кілька рядків у формі e.

Але потім я знайшов це, і воно спрацювало:

https://github.com/chunksnbits/jquery-quickfit

Приклад використання:

$('.someText').quickfit({max:50,tolerance:.4})


2

Завжди мати свій елемент із цим атрибутом:

JavaScript: element.style.fontSize = "100%";

або

CSS: style = "font-size: 100%;"

Коли ви йдете в повноекранному режимі, ви вже повинні мати масштаб змінної обчислюється (масштаб> 1 або масштаб = 1). Потім на повноекранному екрані:

document.body.style.fontSize = (scale * 100) + "%";

Це добре працює з невеликим кодом.


2

Для динамічного тексту цей плагін є досить корисним:

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();

2

Це працювало для мене:

Я намагаюся наблизити розмір шрифту на основі ширини / висоти, отриманої від налаштування `font-size: 10px`. В основному ідея полягає в тому, "якби у мене була 20 пікселів ширина і 11 пікселів висота з` font-size: 10px`, то який би це був максимальний розмір шрифту для математики з контейнером шириною 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 JavaScript does
    // if the real measure had been 12.49 px => JavaScript 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;
}

Примітка: аргумент функції повинен бути прольотним елементом або елементом, меншим за його батьківський, в іншому випадку, якщо у дітей і батьків є однакові функції ширини / висоти, помилка.



1

Для того, щоб розмір шрифту підходив до його контейнера, а не до вікна, дивіться resizeFont()функцію, якою я поділився в цьому запитанні (поєднання інших відповідей, більшість з яких вже пов'язані тут). Він спрацьовує за допомогою window.addEventListener('resize', resizeFont);.

Ванільний JavaScript: розмір шрифту чудовий, щоб помістити контейнер

JavaScript:

function resizeFont() {
  var elements  = document.getElementsByClassName('resize');
  console.log(elements);
  if (elements.length < 0) {
    return;
  }
  _len = elements.length;
  for (_i = 0; _i < _len; _i++) {
    var el = elements[_i];
    el.style.fontSize = "100%";
    for (var size = 100; el.scrollHeight > el.clientHeight; size -= 10) {
      el.style.fontSize = size + '%';
    }
  }
}

Можливо, ви можете використовувати vw / vh як резервну копію, тому ви динамічно призначаєте emчи remодиниці за допомогою JavaScript, гарантуючи, що шрифти масштабуються у вікно, якщо JavaScript відключений.

Застосуйте .resizeклас до всіх елементів, що містять текст, який ви хочете масштабувати.

Запустіть функцію перед додаванням слухача подій для зміни розміру вікна. Тоді будь-який текст, який не відповідає контейнеру, буде зменшений при завантаженні сторінки, а також при зміні розміру.

Примітка: за замовчуванням font-sizeмає бути встановлено або em, remабо %для досягнення відповідних результатів.


1

HTML

<div style="height:100px; width:200px;">
  <div id='qwe'>
    test
  </div>
</div>

JavaScript-код для максимального розміру шрифту:

var fontSize, maxHeight, maxWidth, textElement, parentElement;
textElement = document.getElementById('qwe');
parentElement = textElement.parentElement;    
maxHeight = parentElement.clientHeight;
maxWidth = parentElement.clientWidth;
fontSize = maxHeight;
var minFS = 3, maxFS = fontSize;
while (fontSize != minFS) {
  textElement.style.fontSize = `${fontSize}px`;
  if (textElement.offsetHeight < maxHeight && textElement.offsetWidth <= maxWidth) {
    minFS = fontSize;
  } else{
    maxFS = fontSize;
  }
  fontSize = Math.floor((minFS + maxFS)/2);
}
textElement.style.fontSize = `${minFS}px`;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.