I\'m having a hard time getting my head around font scaling.
I currently have a website with a body font-size
of 100%. 100% of what though? This seems t
I've prepared a simple scale function using CSS transform instead of font-size. You can use it inside of any container, you don't have to set media queries, etc. :)
Blog post: Full width CSS & JS scalable header
The code:
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';
}
}
Working demo: https://codepen.io/maciejkorsan/pen/BWLryj
My problem was similar, but related to scaling text within a heading. I tried Fit Font, but I needed to toggle the compressor to get any results, since it was solving a slightly different problem, as was Text Flow.
So I wrote my own little plugin that reduced the font size to fit the container, assuming you have overflow: hidden
and white-space: nowrap
so that even if reducing the font to the minimum doesn't allow showing the full heading, it just cuts off what it can show.
(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);
I don't see any answer with reference to CSS flex property, but it can be very useful too.
My own solution, jQuery-based, works by gradually increasing the font size until the container gets a big increase in height (meaning it got a line break).
It's pretty simple, but works fairly well, and it is very easy to use. You don't have to know anything about the font being used, everything is taken care of by the browser.
You can play with it on http://jsfiddle.net/tubededentifrice/u5y15d0L/2/
The magic happens here:
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;
};
Take look at my code. It makes the font size smaller
to fit
whatever there.
But I think this doesn't lead to a good user experience
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);
}
});
100% is relative to the base font size, which, if you haven't set it, would be the browser's user-agent default.
To get the effect you're after, I would use a piece of JavaScript code to adjust the base font size relative to the window dimensions.