Динамическое изменение размера шрифта на jQuery

Публикация статьи «Умные динамические колонки с применением CSS и jQuery» стала поводом для написания сегодняшнего поста. Суть очень схожа и речь здесь пойдет про размер шрифта.

Задача — реализовать динамическое изменение размера шрифта сайта в зависимости от разрешения экрана, т.е. размера окна браузера.

Прежде чем приступить к описанию решения, хочу обозначить два момента:

  1. Лично для меня полезность данной штуки весьма сомнительна, и я скорее бы рассматривал такую возможность просто в качестве ознакомления. А вот Сергей, например, эту технику давно хотел применить на практике и видит в ней смысл. Поэтому, возможно, кому-нибудь еще эта информация также пригодится.
  2. Решение довольно простое, работает на моем любимом jQuery, но использование этого фреймворка только ради осуществления данной задачи — не очень разумно, поскольку один лишь фреймворк «весит» под 60 Кб, а сам скрипт при этом состоит из всего лишь 10 строк. Я полагаю, что на нативном JavaScript скрипт, реализующий то же самое, будет значительно меньшего размера.

Итак, приступим.

Сначала я подробно опишу работу jQuery-скрипта, а затем объясню, как его применить к той или иной части веб-сайта.

jQuery

За точку отсчета я взял ширину в 1000 пикселей. Как правило, это минимальная ширина, под которую верстаются сайты. Заносим этот показатель в переменную:


var width = 1000;

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


var fontSize = 12;

Далее считываем ширину хтмл-документа, которую также заносим в переменную:


var bodyWidth = $('html').width();

Определяем коэффициент, на который будет умножаться базовый (минимальный) размер шрифта в зависимости от размера окна браузера. Цифру получаем путем деления ширины хтмл-документа на базовую (минимальную) ширину. Т.е., к примеру, если ширина окна браузера составляет 1600 пикселей, то получим коэффициент 1,6.


var multiplier = bodyWidth / width;

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


if ($('html').width() >= width) fontSize = Math.floor(fontSize * multiplier);

Теперь полученный скорректированный размер шрифта применяем к тегу <body>:


$('body').css({fontSize: fontSize+'px'});

Все вышеописанные строки помещаем в функцию function fontSize() {}, затем запускаем эту функцию после загрузки хтмл-документа, а также после изменения размера окна браузера:


$(function() { fontSize(); });
$(window).resize(function() { fontSize(); });

Вот целиком код jQuery-скрипта, который получился у нас в итоге:


function fontSize() {
	var width = 1000; // ширина, от которой идет отсчет
	var fontSize = 12; // минимальный размер шрифта
	var bodyWidth = $('html').width();
	var multiplier = bodyWidth / width;
	if ($('html').width() >= width) fontSize = Math.floor(fontSize * multiplier);
	$('body').css({fontSize: fontSize+'px'});
}
$(function() { fontSize(); });
$(window).resize(function() { fontSize(); });

HTML

Рассмотрим применение вышеуказанного скрипта на примере 3-колоночного макета страницы, имеющего следующую структуру HTML-кода:


<div id="wrapper">
	<div id="header"></div>
	<div id="middle">
		<div id="container">
			<div id="content"></div>
		</div><!-- #container-->
		<div id="left"></div>
		<div id="right"></div>
	</div><!-- #middle-->
	<div id="footer"></div>
</div><!-- #wrapper -->

CSS

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

Все очень просто.

Во-первых, правой колонке мы просто-напросто устанавливаем свой фиксированный размер шрифта и высоту строки, и скрипт его не затронет:


#right {
  font-size: 12px;
  line-height: 18px;
}

Во-вторых, левой колонке ставим чуть меньший размер шрифта:


#left {
  font-size: 0.9em;
}

В-третьих, нужно либо у тега <body>, либо у соответствующего блока указать высоту строки в em, чтобы она тоже изменялась динамически.

Вот, в принципе, и все.

Пример динамического изменения размера шрифта на jQuery

Если вы хотите менять размер шрифта только у конкретного блока, допустим, у #content, тогда будет логичнее в скрипте поменять body (в строке $('body').css({fontSize: fontSize+'px'});) на нужный идентификатор или класс.

Комментарии (26)

  1. Если уж так приспичило использовать разный размер шрифта при разных размерах экрана для удобства чтения текста, то можно ведь воспользоваться абсолютными единицами измерения. Absolute length units

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

  2. Спасибо, Дима за подробную статью и пример.
    Он, как раз наглядно показывает, что при разрешении 1600*900 и выше читать текст в колонке, где не происходит динамической подстройки размера шрифта, практически невозможно :)
    Понятно, что предложенное решение далеко от идеала, но мне кажется, это правильный путь.

    Ведь не даром и у тебя и у многих других, есть возможность выбора размера шрифта не только средствами браузера.
    К тому же, если размер указан в px, то в IE не работает.

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

  3. Он, как раз наглядно показывает, что при разрешении 1600*900 и выше читать текст в колонке, где не происходит динамической подстройки размера шрифта, практически невозможно :)

    Абсолютно не соглашусь. Если говорить о данном конкретном примере, мне гораздо удобнее читать текст именно в этой колонке (независимо от разрешения экрана), чем в тех, где размер меняется.

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

    Да, недаром. Но здесь предоставляется ВЫБОР. А ты хочешь автоматизировать, лишая пользователя права выбора.

    Думаю, простому пользователю, будет гораздо удобнее, если автомат есть

    А у меня противоположное мнение =)))

    Да и скрипт нужен с более плавными регулировками и дополнительными настройками

    Вот с этим согласен. В таком виде, как сейчас, сложно говорить о практичности скрипта.

    • …мне гораздо удобнее читать текст именно в этой колонке…

      Дима, то, что нравится тебе или мне, никому не важно :)
      Главное, чтобы было удобно пользователю, без лишних действий с его стороны, вот за это он скажет, только спасибо.
      Ленивые мы все, нам автомат подавай :)
      К тому же не у всех 100% зрение.

      Но здесь предоставляется ВЫБОР.

      Тут, то же можно поспорить :)
      По жизни, часто выбора нет, никто от этого не умер, если все будет сделано грамотно и разумно, выбор по сути будет не нужен. Ты же не даешь пользователю возможности сменить начертание и гарнитуру шрифта, может ему больше «verdana» нравится и «italic» с «bold» в придачу:)
      Часто только кажется, что мы кому-то даем право выбора, на самом деле это не совсем так :)

      В таком виде, как сейчас…

      Думаем, делаем, решаем :)

  4. Нашел пример на чистом JavaScript — http://www.tinnedfruit.com/sandbox/textzoom.html

  5. Спасибо, Дима.
    Сейчас болею, потом внимательно посмотрю.

  6. 
    /*========CSS============*/
    html {font-size:100.01%}/*Для оперы*/
    body {font-size:62.5% } /*устанавливаем базовый шрифт в 10px, для простоты расчётов в относительных велечинах*/
    
    
    function fontSize() {
    	var width = 1000; // ширина, от которой идет отсчет
    	var fontSize = 62.5; // минимальный размер шрифта
    	var bodyWidth = document.documentElement.clientWidth;
    	var multiplier = bodyWidth / width; // проверку убрал, пусть шрифт уменьшается если разрешение меньше 1000
    	fontSize = Math.floor(fontSize * multiplier);
    	document.body.style.fontSize = fontSize+'%';
    }
    window.onload = fontSize; 
    window.onresize = fontSize; // так добавлять обработчики не тру, но для наглядности покатит
    

    Кстати офигенная тема, если большинство размеров указывать в относительных еденицах (em) не только размер шрифта но и ширину колонок и отступы, то получается псевдо резиновый макет. Вроде размерами всё зафиксировано, но если изменять базовый шрифт за счёт ресайза то и ширина колонок будет менятся.

    P.S. для тех кто не втеме — у боди выставляется font-size в 62.5% для простоты расчётов, так как 62.5% = 10px, то становится легчк расчитывать размеры например 200px = 20em 12px = 1.2em. Только важно помнить что em относительно рдительского блока, т.е. если вы поменяли блоку размер шрифта то надо уже считать от нового базового размера, но для этих целей есть полезная штука — em калькулятор

    • Спасибо за решение! Не зря я говорил, что на чистом JavaScript то же самое будет значительно меньшего размера. Здесь количество кода такое же, как в моем скрипте, но за вычетом веса целого фреймворка =)

  7. http://www.tinnedfruit.com/ — многа букафф в коде. Лучше написать 10 строчек (хотя если написать правильную функцию для назначения обработчика события, строчек будет больше, спасибо MSIE), под конкретный проэкт чем юзать готовый универсальный скрипт, в котором создаётся обьект в 2-3 раза больше чем малнеькая функция.

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

  9. Закрутился и забыл :)
    Вот линк, на ветку форума, где эта проблема нашла решение без библиотеки jQuery.
    Примеры соотвествующие там есть.

  10. увы, ничего не изменилось :(
    так же режет бока

  11. если на сайте всего 1 скрипт для шрифта, то конечно можно искать решение с наименьшими затратами, но если используешь jQuery не только для динамического шрифта, а для еще всяких украшательств и то это решение просто супер.

  12. Подскажите скрипт для динамического изменения зависимости величины em от ширины окна браузера?

  13. решение одной строчкой

    onload = onresize = function() { document.body.style.fontSize = parseInt(document.body.offsetWidth/80) + ‘px’ }

    http://forum.htmlbook.ru/index.php?s=10086d83503058ea0313941acbec4891&showtopic=14800&view=findpost&p=103593