I have a container that has a % width and height, so it scales depending on external factors. I would like the font inside the container to be a constant size relative to the size of containers. Is there any good way to do this using CSS? The font-size: x%
would only scale the font according to the original font size (which would be 100%).
This question is related to
javascript
css
font-size
You may be able to do this with CSS3 using calculations, however it would most likely be safer to use JavaScript.
Here is an example: http://jsfiddle.net/8TrTU/
Using JS you can change the height of the text, then simply bind this same calculation to a resize event, during resize so it scales while the user is making adjustments, or however you are allowing resizing of your elements.
If you want to set the font-size as a percentage of the viewport width, use the vw
unit:
#mydiv { font-size: 5vw; }
The other alternative is to use SVG embedded in the HTML. It will just be a few lines. The font-size attribute to the text element will be interpreted as "user units", for instance those the viewport is defined in terms of. So if you define viewport as 0 0 100 100, then a font-size of 1 will be one one-hundredth of the size of the svg element.
And no, there is no way to do this in CSS using calculations. The problem is that percentages used for font-size, including percentages inside a calculation, are interpreted in terms of the inherited font size, not the size of the container. CSS could use a unit called bw
(box-width) for this purpose, so you could say div { font-size: 5bw; }
, but I've never heard this proposed.
I've given a more detailed answer of using vw
with respect to specific container sizing in this answer, so I won't just repeat my answer here.
In summary, however, it is essentially a matter of factoring (or controlling) what the container size is going to be with respect to viewport, and then working out the proper vw
sizing based on that for the container, taking mind of what needs to happen if something is dynamically resized.
So if you wanted a 5vw
size at a container at 100% of the viewport width, then one at 75%
of the viewport width you would probably want to be (5vw * .75) = 3.75vw
.
You can also try this pure CSS method:
font-size: calc(100% - 0.3em);
Here is the function:
document.body.setScaledFont = function(f) {
var s = this.offsetWidth, fs = s * f;
this.style.fontSize = fs + '%';
return this
};
Then convert all your documents child element font sizes to em's or %.
Then add something like this to your code to set the base font size.
document.body.setScaledFont(0.35);
window.onresize = function() {
document.body.setScaledFont(0.35);
}
It cannot be accomplished with css font-size
Assuming that "external factors" you are referring to could be picked up by media queries, you could use them - adjustments will likely have to be limited to a set of predefined sizes.
Another js alternative:
fontsize = function () {
var fontSize = $("#container").width() * 0.10; // 10% of container width
$("#container h1").css('font-size', fontSize);
};
$(window).resize(fontsize);
$(document).ready(fontsize);
Or as stated in torazaburo's answer you could use svg. I put together a simple example as a proof of concept:
<div id="container">
<svg width="100%" height="100%" viewBox="0 0 13 15">
<text x="0" y="13">X</text>
</svg>
</div>
If you want to scale it depending on the element width, you can use this web component:
https://github.com/pomber/full-width-text
Check the demo here:
https://pomber.github.io/full-width-text/
The usage is like this:
<full-width-text>Lorem Ipsum</full-width-text>
I had a similar issue but I had to consider other issues that @apaul34208 example did not tackle. In my case;
Not the most elegant of examples but it does the trick for me. Consider using throttling the window resize (https://lodash.com/)
var TextFit = function(){_x000D_
var container = $('.container');_x000D_
container.each(function(){_x000D_
var container_width = $(this).width(),_x000D_
width_offset = parseInt($(this).data('width-offset')),_x000D_
font_container = $(this).find('.font-container');_x000D_
_x000D_
if ( width_offset > 0 ) {_x000D_
container_width -= width_offset;_x000D_
}_x000D_
_x000D_
font_container.each(function(){_x000D_
var font_container_width = $(this).width(),_x000D_
font_size = parseFloat( $(this).css('font-size') );_x000D_
_x000D_
var diff = Math.max(container_width, font_container_width) - Math.min(container_width, font_container_width);_x000D_
_x000D_
var diff_percentage = Math.round( ( diff / Math.max(container_width, font_container_width) ) * 100 );_x000D_
_x000D_
if (diff_percentage !== 0){_x000D_
if ( container_width > font_container_width ) {_x000D_
new_font_size = font_size + Math.round( ( font_size / 100 ) * diff_percentage );_x000D_
} else if ( container_width < font_container_width ) {_x000D_
new_font_size = font_size - Math.round( ( font_size / 100 ) * diff_percentage );_x000D_
}_x000D_
}_x000D_
$(this).css('font-size', new_font_size + 'px');_x000D_
});_x000D_
});_x000D_
}_x000D_
_x000D_
$(function(){_x000D_
TextFit();_x000D_
$(window).resize(function(){_x000D_
TextFit();_x000D_
});_x000D_
});
_x000D_
.container {_x000D_
width:341px;_x000D_
height:341px;_x000D_
background-color:#000;_x000D_
padding:20px;_x000D_
}_x000D_
.font-container {_x000D_
font-size:131px;_x000D_
text-align:center;_x000D_
color:#fff;_x000D_
}
_x000D_
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>_x000D_
_x000D_
<div class="container" data-width-offset="10">_x000D_
<span class="font-container">£5000</span>_x000D_
</div>
_x000D_
I used Fittext on some of my projects and it looks like a good solution to a problem like this.
FitText makes font-sizes flexible. Use this plugin on your fluid or responsive layout to achieve scalable headlines that fill the width of a parent element.
Source: Stackoverflow.com