Масштабирование шрифта в зависимости от ширины контейнера


1189

Мне трудно разобраться с масштабированием шрифтов.

В настоящее время у меня есть этот сайт с телом font-size100%. 100% чего хотя? Это, кажется, вычислить в 16 пикселей.

У меня сложилось впечатление, что 100% будет как-то относиться к размеру окна браузера, но, видимо, не потому, что это всегда 16 пикселей, независимо от того, уменьшено ли окно до ширины мобильного устройства или полноэкранного рабочего стола.

Как я могу сделать текст в моем масштабе сайта относительно его контейнера? Я пытался использовать em, но это не масштабируется либо.

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

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


34
font-size: 100%;означает 100% размера текста (т.е. тот, который он наследует от своего родителя). По умолчанию это 16px. Так что, если бы вы использовали 50%, это был бы размер шрифта: 8px
Энди

31
То, что вы ищете, называется отзывчивой или типографикой размером с область просмотра. css-tricks.com/viewport-sized-typography
gearsdigital

8
Дайте FitText посмотреть.
Пэтси Исса

12
@Andy: На самом деле «по умолчанию» - это любой размер текста браузера, который необязательно может быть равен 16px.
ScottS

1
взгляните на этот ответ stackoverflow.com/a/28485608/4251431
Башир АЛЬ-МОМАНИ

Ответы:


1495

РЕДАКТИРОВАТЬ: Если контейнер не является телом CSS Tricks охватывает все ваши параметры в Подгонка текста к контейнеру .

Если контейнер является телом, то вы ищете длины просмотра в процентах :

Длина области просмотра в процентах относится к размеру исходного содержащего блока . Когда высота или ширина исходного содержащего блока изменяется, они масштабируются соответственно. Однако когда значение переполнения корневого элемента равно auto, предполагается, что любые полосы прокрутки не существуют.

Значения:

  • 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


548
Но что, если контейнер не является окном просмотра (телом)?
Алекс

12
@ Алекс, это территория JS. Попробуйте FitText.jsальтернативу, представленную внизу статьи @jbenjohnson.
Робберт

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

140
Понизил, потому что это не отвечает на вопрос. Он спросил о контейнере, а не о смотровом окне. Совершенно другой вариант использования.
SongBox

6
«Начальный содержащий блок» относится к корневому элементу. Это не правильный ответ на заданный вопрос.
Символ

321

Но что, если контейнер не является окном просмотра (телом)?

Этот вопрос задается в комментарии Алекса под принятым ответом .

Этот факт не означает, что не 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%ширину либо с помощью @mediaJavaScript, либо в то же самое время, font-sizeто необходимо было бы настроить либо в медиа-запросе, либо с помощью JavaScript новый расчет 5vw * .25 = 1.25. При этом размер текста будет таким же, как если бы «ширина» исходного 50%контейнера была уменьшена вдвое от размера окна просмотра, но теперь была уменьшена из-за изменения его собственного процентного расчета.

Вызов

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


(Существует ошибка Chrome с длиной в процентах от области просмотра и изменением размера окна: code.google.com/p/chromium/issues/detail?id=124331 )
тридцатое

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

20
Хороший ответ, однако, он не будет работать, если содержащий элемент имеет максимальную ширину.
Химматоры

3
@KristofferNolgren: Это относится к двум пунктам, сделанным в моем ответе: (1) «если предположить, что контейнер каким-то образом является гибким по размеру» (после достижения максимальной ширины он больше не сгибается, поэтому возникает проблема ). (2) Если можно определить, в какой точке будет достигнута «максимальная ширина», то, как я заметил, вы можете установить @mediaточку останова, чтобы изменить размер шрифта в этой точке (по сути, придав ему фиксированный размер при достижении max-width) , Просто мысль поработать с max-widthситуацией.
ScottS

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

59

Решение с 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
Вы можете полностью
стилизовать

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

8
Это лучшее, наиболее предсказуемое решение, которое масштабируется на основе динамического контейнера.
Джошуа Дэвид

35

В одном из моих проектов я использую «смесь» между vw и vh, чтобы настроить размер шрифта в соответствии со своими потребностями, например:

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

Я знаю, что это не отвечает на вопрос ОП, но, возможно, это может быть решением для кого-либо еще.


3
Вам может быть лучше использовать vminи / или vmaxвместо этого.
sebastian_k

4
chrome dev tools называет это недействительным значением свойства
phil294

31

Чисто-CSS решение с calc(), CSS-единицы и математика

Это точно не то, что просит OP, но может сделать чей-то день. Этот ответ не просто кормить с ложечки и требует некоторого изучения на стороне разработчика.

Наконец-то я пришел, чтобы получить решение для чистого 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
hegez

Примечание: это работает, только если у вас есть текст размером 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 ... но хороший ответ :)
Джонатан Марзулло

fittext.js делает свою работу, я рекомендовал это решение!
Яцек Дзюрдзиковски

FitText был победителем для меня. Перепробовал несколько альтернатив, но это казалось самым простым и хорошо интегрировалось с Drupal / Backdrop CMS. 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
Я думаю, мое невежество проявляется здесь. Но ПОЧЕМУ вышеуказанное ужасно?

Я не думаю, что это ужасно. Я бы порекомендовал некоторые небольшие изменения форматирования, чтобы сделать его более читабельным. Я бы поставил каждую переменную как минимум на отдельную строку. Это может быть необязательно return thisв конце функции. Для повышения производительности вы также можете отменить изменение размера, чтобы оно не перерисовывалось при перетаскивании. Это довольно простой код, поэтому кто-то может основать свое улучшенное решение на нем без особых усилий.
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 / страницы, есть способ сделать это , Iframes.

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

Если не принимать во внимание ограничение на то, что единицы видового экрана не могут также встречаться с боковыми родительскими единицами для текста (например, если размер% ведет себя как все остальные), единицы видового экрана предоставляют очень мощный инструмент: возможность получить минимальное / максимальное измерение , Вы не можете сделать это где-нибудь еще - вы не можете сказать ... сделайте высоту этого 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, которые будут влиять на текстовую область.

Я не могу придумать другой способ сделать это без некоторого зацикливания / прослушивания JavaScript. Реальным решением было бы для браузеров предоставить способ масштабирования текста в зависимости от родительского контейнера и также обеспечить ту же функциональность типа vmin / vmax.

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

Большая часть JavaScript в скрипте - это просто моя пользовательская функция перетаскивания мышью.


@quemeful Не так, когда мы вводим атрибут «новый» и «блестящий» (барабанная дробь, пожалуйста ...) srcdoc: jsfiddle.net/wauzgob6/3
Джек Гиффин,

9

Использование vw, em& Ко. работает точно, но IMO всегда нуждается в человеческом прикосновении для тонкой настройки.

Вот скрипт , я просто написал на основе @ тротил-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
Ориадам,

6

Этот веб-компонент изменяет размер шрифта, чтобы ширина внутреннего текста соответствовала ширине контейнера. Проверьте демо .

Вы можете использовать это так:

<full-width-text>Lorem Ipsum</full-width-text>


6

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

Сообщение в блоге: масштабируемый заголовок 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


Я думаю, что OP ищет решение CSS.
m02ph3u5

5

Используйте CSS-переменные

Никто еще не упомянул CSS-переменные, и этот подход работал лучше всего для меня, поэтому:

Допустим, на вашей странице есть столбец, который на 100% ширины экрана мобильного пользователя, но имеет max-width 800 пикселей, поэтому на рабочем столе по обе стороны от столбца есть место. Поместите это в верхней части вашей страницы:

<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 smallerTofit то , что там.

Но я думаю, что это не приводит к хорошему пользовательскому опыту

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

NB: аргумент функции должен быть элементом span или элементом, который меньше, чем его родитель, иначе, если у дочерних элементов и родительских функций одинаковая ширина / высота, произойдет сбой.



1

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

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