How to implement max-font-size? - css

I want to specify my font size using vw, as in
font-size: 3vw;
However, I also want to limit the font size to say 36px. How can I achieve the equivalent of max-font-size, which does not exist--is the only option to use media queries?

font-size: 3vw; means that the font size will be 3% of the viewport width. So when the viewport width is 1200px - the font size will be 3% * 1200px = 36px.
So a max-font-size of 36px can be easily implemented using a single media query to override the default 3vw font-size value.
Codepen demo (Resize Browser)
div {
font-size: 3vw;
}
#media screen and (min-width: 1200px) {
div {
font-size: 36px;
}
}
<div>hello</div>
Update: With the new CSS min() function, we can simplify the above code - without using media queries (caniuse)
div {
font-size: min(3vw, 36px);
}
In the above example, the font-size will be at most 36px, but will decrease to 3vw if the the viewport is less than 1200px wide (where 3vw computes to a value less than 36px )
That being said, using viewport units for font-size in the above way is problematic because when the viewport width is much smaller - say 320px - then the rendered font size will become 0.03 x 320 = 9.6px which is very (too) small.
In order to overcome this problem, I can recommend using a technique called Fluid Type AKA CSS Locks.
A CSS lock is a specific kind of CSS value calculation where:
there is a minimum value and a maximum value,
and two breakpoints (usually based on the viewport width),
and between those breakpoints, the actual value goes linearly from the minimum to the maximum.
So let's say we want to apply the above technique such that the minimum font-size is 16px at a viewport width of 600px or less, and will increase linearly until it reaches a maximum of 32px at a viewport width of 1200px.
This can be represented as follows (see this CSS-tricks article for more details):
div {
font-size: 16px;
}
#media screen and (min-width: 600px) {
div {
font-size: calc(16px + 16 * ((100vw - 600px) / 600));
}
}
#media screen and (min-width: 1200px) {
div {
font-size: 32px;
}
}
Alternatively, we could use this SASS mixin which does all of the math for us so that the CSS would look something like this:
/*
1) Set a min-font-size of 16px when viewport width < 600px
2) Set a max-font-size of 32px when viewport width > 1200px and
3) linearly increase the font-size from 16->32px
between a viewport width of 600px-> 1200px
*/
div {
#include fluid-type(font-size, 600px, 1200px, 16px, 32px);
}
// ----
// libsass (v3.3.6)
// ----
// =========================================================================
//
// PRECISE CONTROL OVER RESPONSIVE TYPOGRAPHY FOR SASS
// ---------------------------------------------------
// Indrek Paas #indrekpaas
//
// Inspired by Mike Riethmuller's Precise control over responsive typography
//
//
// `strip-unit()` function by Hugo Giraudel
//
// 11.08.2016 Remove redundant `&` self-reference
// 31.03.2016 Remove redundant parenthesis from output
// 02.10.2015 Add support for multiple properties
// 24.04.2015 Initial release
//
// =========================================================================
#function strip-unit($value) {
#return $value / ($value * 0 + 1);
}
#mixin fluid-type($properties, $min-vw, $max-vw, $min-value, $max-value) {
#each $property in $properties {
#{$property}: $min-value;
}
#media screen and (min-width: $min-vw) {
#each $property in $properties {
#{$property}: calc(#{$min-value} + #{strip-unit($max-value - $min-value)} * (100vw - #{$min-vw}) / #{strip-unit($max-vw - $min-vw)});
}
}
#media screen and (min-width: $max-vw) {
#each $property in $properties {
#{$property}: $max-value;
}
}
}
// Usage:
// ======
// /* Single property */
// html {
// #include fluid-type(font-size, 320px, 1366px, 14px, 18px);
// }
// /* Multiple properties with same values */
// h1 {
// #include fluid-type(padding-bottom padding-top, 20em, 70em, 2em, 4em);
// }
////////////////////////////////////////////////////////////////////////////
div {
#include fluid-type(font-size, 600px, 1200px, 16px, 32px);
}
#media screen and (max-width: 600px) {
div {
font-size: 16px;
}
}
#media screen and (min-width: 1200px) {
div {
font-size: 36px;
}
}
<div>Responsive Typography technique known as Fluid Type or CSS Locks.
Resize the browser window to see the effect.
</div>
Codepen Demo
Update: We can use the new clamp() CSS function (caniuse) to refactor the above code to simply:
div {
font-size: clamp(16px, 3vw, 32px);
}
see MDN:
clamp() allows you to set a font-size that grows with the size of the
viewport, but doesn't go below a minimum font-size or above a maximum
font-size. It has the same effect as the code in Fluid Typography but
in one line, and without the use of media queries.
p { font-size: clamp(1rem, 2.5vw, 1.5rem); }
<p>
If 2.5vw is less than 1rem, the font-size will be 1rem.
If 2.5vw is greater than 1.5rem, the font-size will be 1.5rem.
Otherwise, it will be 2.5vw.
</p>
--
Further Reading
Fluid Typography
How Do You Do max-font-size in CSS?
Fluid Responsive Typography With CSS Poly Fluid Sizing
Non-linear interpolation in CSS

Here is another idea. The calc function uses double precision float. Therefore it exhibits a step function near 1e18. For example,
width: calc(6e18px + 100vw - 6e18px);
This will snap to values 0px, 1024px, 2048px, etc. see pen https://codepen.io/jdhenckel/pen/bQNgyW
The step function can be used to create abs value and min/max with some clever maths. For instance
max(x, y) = x - (x + y) * step(y - x)
Given step(z) is zero when z<0 and one otherwise.
just an idea, not very practical, but maybe fun to try.
(Caution: this technique depends on an implementation detail that is not in any specification; currently, it works in Chrome and Safari, but not in Firefox, Edge or Internet Explorer, which don’t use double-precision floats for CSS values.)
UPDATE: this post is no longer useful (was it ever?) since CSS now supports min, max, and clamp.

Another way increases font size slowly, this will not limit max font size, but even on very wide screens, it will look better. Does not answer question in perfect way, but its 1 line...
font-size: calc(16px + 1vw);
Update: CSS improved and i recommend using clamp(min, preferred, max) function:
font-size: clamp(12px, 2vw, 20px);

At some point, the font-size exceeds the 36px scale right, find that. Assuming, it exceeds when the width: 2048px:
#media screen and (min-width: 2048px) {
.selector {
font-size: 36px;
}
}
Yes, unfortunately you need to use the #media queries. I hope that doesn't affect anything.

According to this website (there are ads in this site),
If you don't want to use clamp():
font-size: 24px;
font-size: min(max(3.5vw, 16px), 40px);
Line one for IE.
Line two for others, means font-size:3.5vw, max-font-size:40px, min-font-size:16px.

Related

How can I put a CSS variable for the users screen width into a calc function?

My website is designed on a larger monitor and has a screen width of 2560px (Samsung 32"). Therefore it must be scaled down to appear properly on any smaller screen; for example, a common laptop with a 17" screen has a pixel width of 1366px. So, by dividing 1366 / 2560 we get the right scale percentage of .53 for use in a CSS transform:scale(calc(1366 / 2560)); formula.
The entire page is wrapped in a div that I have called .omniScale
.omniScale {
display: table;
margin:0 auto;
transform-origin: top left;
transform:scale(calc(1366 / 2560));
}
This works just great, however the 1366 has to change dynamically on page load to the width of the user’s device no matter if it may be a tablet, laptop, mid-size desktop monitor or larger on up to a large television.
Using 100vw instead of the hardwired number does not work. I don't want to use JavaScript, if avoidable, so has to work for those who have js turned off.
Welcome to Stack Overflow :]
Sadly at this moment there is no mechanism to calculate integer ratio of two length values in pure CSS (calc(100vw / 2560px) won't work, because you can divide length only with integer to get other length, not with other length to get integer).
So if you want to get ratio of your reference element to actual viewport, JavaScript seems to be the only option. Reasonable approach would be use JS just to set CSS custom property and let styles do the rest:
function setScaleRatio() {
viewportWidth = document.documentElement.clientWidth;
fullWidth = 2560 + 200;
// (2560 is reference size, +200 just to make sure we'll see right border in this example)
scaleRatio = viewportWidth / fullWidth;
document.documentElement.style.setProperty('--ratio', scaleRatio);
};
setScaleRatio();
window.addEventListener('resize', setScaleRatio);
[style]::before {
content: attr(style);
}
<div style="
width: 2560px;
transform: scale(var(--ratio));
transform-origin: top left;
font-size: 100px;
background-color: black;
color: white;
"></div>
I don't think this is the right approach. to make something responsive to all screens it is best to use percentages and #madia.
for more info: https://blog.froont.com/9-basic-principles-of-responsive-web-design/
example:
.container {
width: 2560px;
}
#media only screen and (max-width: 2560px) {
.container {
width: 1366px;
}
}
#media only screen and (max-width: 1366px) {
.container {
width: 900px;
}
}
#media only screen and (max-width: 900px) {
.container {
width: 500px;
}
}

Font-size and device-pixel-ratio

Let's say that I have default font size set to 16px (this should be redundant since it's default in most browsers):
For brevity, my site contains some box with size 10em x 10em.
body, html
{
font-size: 16px;
}
.box {
border: 1px green solid;
background-color:green;
width:10em;
height:10em;
}
My site is already responsive with min-width media queries for specific breakpoints targetted at em values (36, 62 and 85em).
The only thing my site does is change width and color of the box.
#media (min-width:36em) {
.box {
width: 36em;
border:1px red solid;
background-color:red;
}
}
#media (min-width:62em) {
.box {
width: 62em;
border:1px blue solid;
background-color:blue;
}
}
#media (min-width:85em) {
.box {
width: 85em;
border:1px orange solid;
background-color:orange;
}
}
Now let's say that I have some device with resolution 1440x900 where browsers decide that the device's pixel density is 2dppx by default. As result, everything looks much bigger than it should be. And I don't like it.
But the solution should be easy, right? Just add a media query at start for 2dppx pixel density and since it's twice as much pixels, I just reduce the font size by half...that should work, right?
And since I use "em" on everything then by changing the font-size by half I automatically reduce size of everything "em"-sized by half...right?
#media ( min-resolution: 2dppx) {
body, html {
font-size: 50%;
}
}
relevant jsFiddle
Well I found it does not work as I thought it would...I tried to google answers but did not find anything relevant, I suspect I misunderstand how font-sizes, ems and pixel density works...
Reducing font-size by 50% reduces the font-size by much more than by half. The original size is 16px but font-size: 50%; results in a font much smaller than font-size:8px ... Tested in Firefox and Chrome. Does anyone know why is that?
When I set font-size:8px; in the media query for 2dppx then media queries for min-width:36em, 62em and 85em do not trigger as I would have expected, at least when I change layout.css.devPixelsPerPx in Firefox. The min-width in media query behaves like the font-size is still at 16px eventhough it's changed with the dppx media query. Tested in Firefox and Chrome. Does anyone know why is that?
UPDATE
Looks like media queries are loaded in 1dppx context, it does not matter if you use "em", it seems they are cached on load and values such as min-width are fixed to the first value and eventhough you change the base font-size in different media query, other queries don't refresh.
The only solution I can think of right now is to multiply all media queries. One media query for px value in 1 dppx context and another media query for px value in 2 dppx context (which is 50% of the first value).
Thanks to Mr Lister in comments, I found out that this:
#media ( min-resolution: 2dppx) {
body, html {
font-size: 50%;
}
}
...is not what I intended to do. The 50% rule works for <html> tag AND for <body> tag. The resulting font size is not 8px in body, but 4px, because 50% in html is 8px and another 50% in nested body tag results in 4px.
What I intended to do was this:
#media ( min-resolution: 2dppx) {
html {
font-size: 50%;
}
}
Font-size issue is solved.
For the media query: I found out that sizes in #media queries ignore pixel density but sizes in the CSS rule body do not. Since I use "em" sizes and SASS, I can simply replace all #media queries with this mixin (example with 2dppx):
#mixin media-min-width($min-width) {
#media(min-width:$min-width), (min-width: $min-width / 2) and (min-resolution: 2dppx) {
#content;
}
}

Can I update SASS variables in Media Queries?

Consider the following SASS code. I want to make sure that if the screen is above 1250px then the margin-top should be 750px and then it should change depending on size. However SASS does not allow me to update the variables inside the strings.
// Above 1250px
$pageTemplateMargin:750px;
// Below 1250px
#media screen and (max-width:1250px){
$pageTemplateMargin:550px;
}
// Below 950px
#media screen and (max-width:950px){
$pageTemplateMargin:450px;
}
#media screen and (max-width:850px){
$pageTemplateMargin:150px;
}
#media screen and (max-width:750px){
$pageTemplateMargin:250px;
}
// Render the correct code
.page-template {margin-top:$pageTemplateMargin}
Is there a better way for this, as it does not work and page-template stays at 750px.
Thanks
I agree with the accepted answer that it's better to use maps in this case but I want to point out a couple of things.
Variables can actually be updated inside of media queries. The problem is that a variable defined outside of a block is a global variable while one defined within a block is a local variable. You can let sass treat a variable within a block as a global variable using the !global keyword.
$pageTemplateMargin:750px;
#media screen and (max-width:1250px){
$pageTemplateMargin: 550px !global;
}
.page-template {
margin-top: $pageTemplateMargin //will use 550px instead of 750px
}
Just want to clarify that it is possible albeit it is not appropriate in this use case.
I also suggest using a loop for your code which will prove helpful especially if you add more screen widths and margin properties so you don't need to further write more media queries.
$breakpoints: (
1200px: 10px,
1000px: 15px,
800px: 20px,
);
#each $width, $margin in $breakpoints {
#media screen and (max-width: $width) {
.element {
margin-top: $margin;
}
}
}
Hope this helps.
No, you can't (in this situation, as pointed out in the other answer).
I'd suggest using mixins to work with this:
#mixin pageTemplateMargin($px) {
margin-top: $px
}
#media screen and (max-width:1250px) {
.element { #include pageTemplateMargin(10px);}
}
#media screen and (max-width:1000px) {
.element { #include pageTemplateMargin(15px);}
}
#media screen and (max-width:800px) {
.element { #include pageTemplateMargin(20px);}
}
There's also a way of mapping through sass objects, such as:
$breakpoints: (
1200: 10px,
1000: 15px,
800: 20px,
);
#media screen and (max-width:1200px) {
.element { margin-top: map-get($breakpoints, 1200);}
}
#media screen and (max-width:1000px) {
.element { margin-top: map-get($breakpoints, 1000);}
}
#media screen and (max-width:800px) {
.element { margin-top: map-get($breakpoints, 800);}
}
This would allow you to globally change the margin by adjusting 1 variable.
Working codepen example
I have tried this then i fixed my issue. It will calculate all media-breakpoint automatically by given rate (base-size/rate-size)
$base-size: 16;
$rate-size-xl: 24;
// set default size for all cases;
:root {
--size: #{$base-size};
}
// if it's smaller then LG it will set size rate to 16/16;
// example: if size set to 14px, it will be 14px * 16 / 16 = 14px
#include media-breakpoint-down(lg) {
:root {
--size: #{$base-size};
}
}
// if it is bigger then XL it will set size rate to 24/16;
// example: if size set to 14px, it will be 14px * 24 / 16 = 21px
#include media-breakpoint-up(xl) {
:root {
--size: #{$rate-size-xl};
}
}
#function size($px) {
#return calc(#{$px} / $base-size * var(--size));
}
div {
font-size: size(14px);
width: size(150px);
}

Pure CSS if/ else statement involving custom unit of size variables

I want to solve my issue only using pure CSS.
Here's the problematic code that I have:
#if (100vh > 830px) {:root { --cwv:100vh;}}
#else {:root { --cwv: 830px;}}
What I'm trying to do: if browser window size is smaller than 830px, the "- -cvw" (custom width variable/ unit) should be relative (another problem that my code probably has) to 830px rather than 100vw (built-in viewport "vertical width" unit), as the elements on the page get too small.
I know I can use multiple other ways to solve this problem using other languages, but I am just wondering how to make the CSS code work - as it is supposed to - according to the places that I have researched:
CSS custom properties (variables) - states that variables are declared in the following manner: :root{--variable-name: variable-value;}
CSS Conditionals (if/ else statements)
What am I doing wrong? I expect that I have multiple syntax errors in my code (that I've provided above) too... :/
Use media queries max-width.
Example:
Default --cwx set to viewport width:
:root{
--cwv: 100vw;
}
In case where viewport width is lesser or equal 830px, set --cwx to 830px:
#media all and (max-width: 830px){
:root{
--cwv: 830px;
}
}
Finally, example's black bar will be set to ½ of --cwx, thus ½ of viewport width, but not less than ½ of 830px (=415px):
:root{
--cwv: 100vw;
}
#media all and (max-width: 830px){
:root{
--cwv: 830px;
}
}
body{
margin: 0;
}
:root::after{
content: "";
display: block;
background: black;
height: 10px;
width: calc(var(--cwv) * .5);
}
use media queries for window size like this below
#media screen and (min-width : 830 px) {
/* your code */
}

Responsive font size in CSS

I've created a site using the Zurb Foundation 3 grid. Each page has a large h1:
body {
font-size: 100%
}
/* Headers */
h1 {
font-size: 6.2em;
font-weight: 500;
}
<div class="row">
<div class="twelve columns text-center">
<h1> LARGE HEADER TAGLINE </h1>
</div>
<!-- End Tagline -->
</div>
<!-- End Row -->
When I resize the browser to mobile size the large font doesn't adjust and causes the browser to include a horizontal scroll to accommodate for the large text.
I've noticed that on the Zurb Foundation 3 Typography example page, the headers adapt to the browser as it is compressed and expanded.
Am I missing something really obvious? How do I achieve this?
You can use the viewport value instead of ems, pxs, or pts:
1vw = 1% of viewport width
1vh = 1% of viewport height
1vmin = 1vw or 1vh, whichever is smaller
1vmax = 1vw or 1vh, whichever is larger
h1 {
font-size: 5.9vw;
}
h2 {
font-size: 3.0vh;
}
p {
font-size: 2vmin;
}
From CSS-Tricks: Viewport Sized Typography
The font-size won't respond like this when resizing the browser window. Instead they respond to the browser zoom/type size settings, such as if you press Ctrl and + together on the keyboard while in the browser.
Media Queries
You would have to look at using media queries to reduce the font-size at certain intervals where it starts breaking your design and creating scrollbars.
For example, try adding this inside your CSS at the bottom, changing the 320 pixels width for wherever your design starts breaking:
#media only screen and (max-width: 320px) {
body {
font-size: 2em;
}
}
Viewport percentage lengths
You can also use viewport percentage lengths such as vw, vh, vmin and vmax. The official W3C document for this states:
The viewport-percentage lengths are relative to the size of the initial containing block. When the height or width of the initial containing block is changed, they are scaled accordingly.
Again, from the same W3C document each individual unit can be defined as below:
vw unit - Equal to 1% of the width of the initial containing block.
vh unit - Equal to 1% of the height of the initial containing block.
vmin unit - Equal to the smaller of vw or vh.
vmax unit - Equal to the larger of vw or vh.
And they are used in exactly the same way as any other CSS value:
.text {
font-size: 3vw;
}
.other-text {
font-size: 5vh;
}
Compatibility is relatively good as can be seen here. However, some versions of Internet Explorer and Edge don’t support vmax. Also, iOS 6 and 7 have an issue with the vh unit, which was fixed in iOS 8.
h1{
font-size : clamp(2rem, 10vw, 5rem);
}
here clamp has 3 arguments.
first one is the minimum allowed font-size.
third one is the maximum allowed font-size.
second argument is font-size that you wish to always have. Its unit must be relative(vw, vh, ch) and not absolute(i.e not px, mm, pt). relative unit will make it change its size w.r.t the changing screen sizes.
Consider an example :
consider there is a large fontawesome icon that you want to resize dynamically (responsive icon)
fa-random-icon{
font-size: clamp( 15rem, 80vw, 80vh)
}
Here 80vw is the preferred font-size.
15 rem is the minimum font size (lower bound).
80vh is the max font size (upper bound).
i.e.
if in a particular mobile screen size if 80vw < 15rem then font-size is 15rem.
if screen is too wide then if 80vw > 80vh then font-size is 80vh.
Those methods above suggested by people always have a bit uncertain result... like when we use vw only, the font size might sometimes be too big or too small (unbounded).
#media queries can be used but you have to use minimum 3 media-queries to make the font size responsive
I've been playing around with ways to overcome this issue, and believe I have found a solution:
If you can write your application for Internet Explorer 9 (and later) and all other modern browsers that support CSS calc(), rem units, and vmin units. You can use this to achieve scalable text without media queries:
body {
font-size: calc(0.75em + 1vmin);
}
Here it is in action: http://codepen.io/csuwldcat/pen/qOqVNO
Use CSS media specifiers (that's what they [zurb] use) for responsive styling:
#media only screen and (max-width: 767px) {
h1 {
font-size: 3em;
}
h2 {
font-size: 2em;
}
}
If you don't mind to use a jQuery solution you can try TextFill plugin
jQuery TextFill resizes text to fit into a container and makes font size as big as possible.
https://github.com/jquery-textfill/jquery-textfill
There are several ways to achieve this.
Use a media query, but it requires font sizes for several breakpoints:
body
{
font-size: 22px;
}
h1
{
font-size: 44px;
}
#media (min-width: 768)
{
body
{
font-size: 17px;
}
h1
{
font-size: 24px;
}
}
Use dimensions in % or em. Just change the base font size, and everything will change. Unlike the previous one, you could just change the body font and not h1 every time or let the base font size be the default of the device and the rest all in em:
“Ems” (em): The “em” is a scalable unit. An em is equal to the current font-size, for instance, if the font-size of the document is 12 pt, 1 em is equal to 12 pt. Ems are scalable in nature, so 2 em would equal 24 pt, .5 em would equal 6 pt, etc..
Percent (%): The percent unit is much like the “em” unit, save for a few fundamental differences. First and foremost, the current font-size is equal to 100% (i.e. 12 pt = 100%). While using the percent unit, your text remains fully scalable for mobile devices and for accessibility.
See kyleschaeffer.com/....
CSS 3 supports new dimensions that are relative to the view port. But this doesn't work on Android:
3.2vw = 3.2% of width of viewport
3.2vh = 3.2% of height of viewport
3.2vmin = Smaller of 3.2vw or 3.2vh
3.2vmax = Bigger of 3.2vw or 3.2vh
body
{
font-size: 3.2vw;
}
See CSS-Tricks ... and also look at Can I Use...
There's another approach to responsive font sizes - using rem units.
html {
/* Base font size */
font-size: 16px;
}
h1 {
font-size: 1.5rem;
}
h2 {
font-size: 1.2rem;
}
Later in media queries, you can adjust all fonts sizes by changing the base font size:
#media screen and (max-width: 767px) {
html {
/* Reducing base font size will reduce all rem sizes */
font-size: 13px;
}
/* You can reduce font sizes manually as well */
h1 {
font-size: 1.2rem;
}
h2 {
font-size: 1.0rem;
}
}
To make this work in Internet Explorer 7 and Internet Explorer 8 you will have to add a fallback with px units:
h1 {
font-size: 18px;
font-size: 1.125rem;
}
If you're developing with Less, you can create a mixin that will do the math for you.
Rem units support - http://caniuse.com/#feat=rem
The "vw" solution has a problem when going to very small screens. You can set the base size and go up from there with calc():
font-size: calc(16px + 0.4vw);
This is partly implemented in foundation 5.
In file _type.scss they have two sets of header variables:
// We use these to control header font sizes
// for medium screens and above
$h1-font-size: rem-calc(44) !default;
$h2-font-size: rem-calc(37) !default;
$h3-font-size: rem-calc(27) !default;
$h4-font-size: rem-calc(23) !default;
$h5-font-size: rem-calc(18) !default;
$h6-font-size: 1rem !default;
// We use these to control header size reduction on small screens
$h1-font-reduction: rem-calc(10) !default;
$h2-font-reduction: rem-calc(10) !default;
$h3-font-reduction: rem-calc(5) !default;
$h4-font-reduction: rem-calc(5) !default;
$h5-font-reduction: 0 !default;
$h6-font-reduction: 0 !default;
For medium up, they generate sizes based on the first set of variables:
#media #{$medium-up} {
h1,h2,h3,h4,h5,h6 { line-height: $header-line-height; }
h1 { font-size: $h1-font-size; }
h2 { font-size: $h2-font-size; }
h3 { font-size: $h3-font-size; }
h4 { font-size: $h4-font-size; }
h5 { font-size: $h5-font-size; }
h6 { font-size: $h6-font-size; }
}
And for default-i.e small screens, they use a second set of variables to generates CSS:
h1 { font-size: $h1-font-size - $h1-font-reduction; }
h2 { font-size: $h2-font-size - $h2-font-reduction; }
h3 { font-size: $h3-font-size - $h3-font-reduction; }
h4 { font-size: $h4-font-size - $h4-font-reduction; }
h5 { font-size: $h5-font-size - $h5-font-reduction; }
h6 { font-size: $h6-font-size - $h6-font-reduction; }
You can use these variables and override in your custom scss file to set font sizes for respective screen sizes.
I saw a great article from CSS-Tricks. It works just fine:
body {
font-size: calc([minimum size] + ([maximum size] - [minimum size]) * ((100vw -
[minimum viewport width]) / ([maximum viewport width] - [minimum viewport width])));
}
For example:
body {
font-size: calc(14px + (26 - 14) * ((100vw - 300px) / (1600 - 300)));
}
We can apply the same equation to the line-height property to make it change with the browser as well.
body {
font-size: calc(14px + (26 - 14) * ((100vw - 300px) / (1600 - 300)));
line-height: calc(1.3em + (1.5 - 1.2) * ((100vw - 300px)/(1600 - 300)));
}
A responsive font size can also be done with this JavaScript code called FlowType:
http://simplefocus.com/flowtype/
https://github.com/simplefocus/FlowType.JS
FlowType - Responsive web typography at its finest: font-size based on element width.
Or this JavaScript code called FitText:
http://fittextjs.com/
https://github.com/davatron5000/FitText.js
FitText - Makes font-sizes flexible. Use this plugin on your responsive design for ratio-based resizing of your headlines.
If you are using a build tool then try Rucksack.
Otherwise, you can use CSS variables (custom properties) to easily control the minimum and maximum font sizes like so (demo):
* {
/* Calculation */
--diff: calc(var(--max-size) - var(--min-size));
--responsive: calc((var(--min-size) * 1px) + var(--diff) * ((100vw - 420px) / (1200 - 420))); /* Ranges from 421px to 1199px */
}
h1 {
--max-size: 50;
--min-size: 25;
font-size: var(--responsive);
}
h2 {
--max-size: 40;
--min-size: 20;
font-size: var(--responsive);
}
I had just come up with an idea with which you only have to define the font size once per element, but it is still influenced by media queries.
First, I set the variable "--text-scale-unit" to "1vh" or "1vw", depending on the viewport using the media queries.
Then I use the variable using calc() and my multiplicator number for font-size:
/* Define a variable based on the orientation. */
/* The value can be customized to fit your needs. */
#media (orientation: landscape) {
:root{
--text-scale-unit: 1vh;
}
}
#media (orientation: portrait) {
:root {
--text-scale-unit: 1vw;
}
}
/* Use a variable with calc and multiplication. */
.large {
font-size: calc(var(--text-scale-unit) * 20);
}
.middle {
font-size: calc(var(--text-scale-unit) * 10);
}
.small {
font-size: calc(var(--text-scale-unit) * 5);
}
.extra-small {
font-size: calc(var(--text-scale-unit) * 2);
}
<span class="middle">
Responsive
</span>
<span class="large">
text
</span>
<span class="small">
with one
</span>
<span class="extra-small">
font-size tag.
</span>
In my example I only used the orientation of the viewport, but the principle should be possible with any media queries.
I use these CSS classes, and they make my text fluid on any screen size:
.h1-fluid {
font-size: calc(1rem + 3vw);
line-height: calc(1.4rem + 4.8vw);
}
.h2-fluid {
font-size: calc(1rem + 2vw);
line-height: calc(1.4rem + 2.4vw);
}
.h3-fluid {
font-size: calc(1rem + 1vw);
line-height: calc(1.4rem + 1.2vw);
}
.p-fluid {
font-size: calc(1rem + 0.5vw);
line-height: calc(1.4rem + 0.6vw);
}
Try including this on your style sheet:
html {
font-size: min(max(16px, 4vw), 22px);
}
More info at https://css-tricks.com/simplified-fluid-typography/
There are the following ways by which you can achieve this:
Use rem for e.g. 2.3 rem
Use em for e.g. 2.3em
Use % for e.g. 2.3%
Moreover, you can use :
vh, vw, vmax and vmin.
These units will autoresize depending upon the width and height of the screen.
jQuery's "FitText" is probably the best responsive header solution. Check it out at GitHub:
https://github.com/davatron5000/FitText.js
In actual original Sass (not scss) you could use the below mixins to automatically set the paragraph's and all headings' font-size.
I like it because it is much more compact. And quicker to type. Other than that, it provides the same functionality. Anyway, if you still want to stick to the new syntax - scss, then feel free to convert my Sass content to scss here:
[CONVERT SASS TO SCSS HERE]
Below I give you four Sass mixins. You will have to tweak their settings to your needs.
=font-h1p-style-generator-manual() // You don’t need to use this one. Those are only styles to make it pretty.
=media-query-base-font-size-change-generator-manual() // This mixin sets the base body size that will be used by the h1-h6 tags to recalculate their size in a media query.
=h1p-font-size-generator-auto($h1-fs: 3em, $h1-step-down: 0.3, $body-min-font-size: 1.2em, $p-same-as-hx: 6) // Here you will set the size of h1 and size jumps between h tags
=config-and-run-font-generator() // This one only calls the other ones
After you finish playing with settings just make a call on one mixin - which is: +config-and-run-font-generator(). See code below and comments for more information.
I guess you could do it automatically for a media query like it is done for header tags, but we all use different media queries, so it would not be appropriate for everyone. I use a mobile-first design approach, so this is how I would do that. Feel free to copy and use this code.
COPY AND PASTE THESE MIXINS TO YOUR FILE:
=font-h1p-style-generator-manual()
body
font-family: "Source Sans Pro", "Helvetica Neue", Helvetica, Arial, sans-serif // google fonts
font-size: 100%
line-height: 1.3em
%headers
line-height: 1em
font-weight: 700
p
line-height: 1.3em
font-weight: 300
#for $i from 1 through 6
h#{$i}
#extend %headers
=media-query-base-font-size-change-generator-manual()
body
font-size: 1.2em
#media screen and (min-width: 680px)
body
font-size: 1.4em
#media screen and (min-width: 1224px)
body
font-size: 1.6em
#media screen and (min-width: 1400px)
body
font-size: 1.8em
=h1p-font-size-generator-auto($h1-fs: 3em, $h1-step-down: 0.3, $body-min-font-size: 1.2em, $p-same-as-hx: 6)
$h1-fs: $h1-fs // Set first header element to this size
$h1-step-down: $h1-step-down // Decrement each time by 0.3
$p-same-as-hx: $p-same-as-hx // Set p font-sieze same as h(6)
$h1-fs: $h1-fs + $h1-step-down // Looping correction
#for $i from 1 through 6
h#{$i}
font-size: $h1-fs - ($h1-step-down * $i)
#if $i == $p-same-as-hx
p
font-size: $h1-fs - ($h1-step-down * $i)
// RUN ONLY THIS MIXIN. IT WILL TRIGGER THE REST
=config-and-run-font-generator()
+font-h1p-style-generator-manual() // Just a place holder for our font style
+media-query-base-font-size-change-generator-manual() // Just a placeholder for our media query font size
+h1p-font-size-generator-auto($h1-fs: 2em, $h1-step-down: 0.2, $p-same-as-hx: 5) // Set all parameters here
CONFIGURE ALL MIXINS TO YOUR NEEDS - PLAY WITH IT! :) AND THEN CALL IT ON THE TOP OF YOUR ACTUAL SASS CODE WITH:
+config-and-run-font-generator()
This would generate this output. You can customize parameters to generate different sets of results. However, because we all use different media queries, some mixins you will have to edit manually (style and media).
GENERATED CSS:
body {
font-family: "Source Sans Pro", "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 100%;
line-height: 1.3em;
word-wrap: break-word; }
h1, h2, h3, h4, h5, h6 {
line-height: 1em;
font-weight: 700; }
p {
line-height: 1.3em;
font-weight: 300; }
body {
font-size: 1.2em; }
#media screen and (min-width: 680px) {
body {
font-size: 1.4em; } }
#media screen and (min-width: 1224px) {
body {
font-size: 1.6em; } }
#media screen and (min-width: 1400px) {
body {
font-size: 1.8em; } }
h1 {
font-size: 2em; }
h2 {
font-size: 1.8em; }
h3 {
font-size: 1.6em; }
h4 {
font-size: 1.4em; }
h5 {
font-size: 1.2em; }
p {
font-size: 1.2em; }
h6 {
font-size: 1em;
}
The text size can be set with a vw unit, which means the "viewport width". That way the text size will follow the size of the browser window:
https://www.w3schools.com/howto/tryit.asp?filename=tryhow_css_responsive_text
For my personal project I used vw and #meida. It works perfectly.
.mText {
font-size: 6vw;
}
#media only screen and (max-width: 1024px) {
.mText {
font-size: 10vw;
}
}
.sText {
font-size: 4vw;
}
#media only screen and (max-width: 1024px) {
.sText {
font-size: 7vw;
}
}
We can use calc() from css
p{
font-size: calc(48px + (56 - 48) * ((100vw - 300px) / (1600 - 300))) !important;
}
The mathematical formula is
calc(minsize + (maxsize - minsize) * (100vm - minviewportwidth) / (maxwidthviewoport - minviewportwidth)))
Codepen
A lot of answers but I did not see anyone mentioning the min or max functions combined with media queries
There is a max() function in CSS, so our example above becomes a one-liner:
font-size: max(30vw, 30px);
Or double it up with a min and max:
font-size: min(max(16px, 4vw), 22px);
Which is identical to:
font-size: clamp(16px, 4vw, 22px);
Then don't forget to wrap this in a media query and apply to your h1,h2,h3,h4,h5,h6 how you prefer.
#media (max-width: 600px) {
h1 {
font-size: clamp(16px, 4vw, 22px);
}
}
As with many frameworks, once you "go off the grid" and override the framework's default CSS, things will start to break left and right. Frameworks are inherently rigid. If you were to use Zurb's default H1 style along with their default grid classes, then the web page should display properly on mobile (i.e., responsive).
However, it appears you want very large 6.2em headings, which means the text will have to shrink in order to fit inside a mobile display in portrait mode. Your best bet is to use a responsive text jQuery plugin such as FlowType and FitText. If you want something light-weight, then you can check out my Scalable Text jQuery plugin:
http://thdoan.github.io/scalable-text/
Sample usage:
<script>
$(document).ready(function() {
$('.row .twelve h1').scaleText();
}
</script>
h1 { font-size: 2.25em; }
h2 { font-size: 1.875em; }
h3 { font-size: 1.5em; }
h4 { font-size: 1.125em; }
h5 { font-size: 0.875em; }
h6 { font-size: 0.75em; }
You can make the font size responsive if defining it in vw (viewport width). However, not all browsers support it. The solution is to use JavaScript to change the base font size depending on the browser width and set all font sizes in %.
Here is an article describing how to make responsive fontsizes: http://wpsalt.com/responsive-font-size-in-wordpress-theme/
I have found this solution, and it works very well for me:
/* Fluid font size:
minimum font size at min. device width 300px = 14
maximum font size at max. device width 1600px = 26
*/
body {
font-size: calc(14px + (26 - 14) * ((100vw - 300px) / (1600 - 300)));
}
One way to solve the problem of the text to look good on both desktop and mobile/tablet is in fixing the text size to physical units like physical centimeters or inches, which don't depend on the screen PPI (points per inch).
Based on this answer, below is the code I use at the end of the HTML document for a responsive font size:
<div id='testdiv' style='height: 1in; left: -100%; position: absolute; top: -100%; width: 1in;'></div>
<script type='text/javascript'>
var devicePixelRatio = window.devicePixelRatio || 1;
dpi_x = document.getElementById('testdiv').offsetWidth * devicePixelRatio;
dpi_y = document.getElementById('testdiv').offsetHeight * devicePixelRatio;
function setFontSizeForClass(className, fontSize) {
var elms = document.getElementsByClassName(className);
for(var i=0; i<elms.length; i++) {
elms[i].style.fontSize = String(fontSize * dpi_y / 96) + "px";
}
}
setFontSizeForClass('h1-font-size', 30);
setFontSizeForClass('action-font-size', 20);
setFontSizeForClass('guideline-font-size', 25);
// etc for your different classes
</script>
In the code above the items of a different class are assigned font sizes in physical units, as long as the browser/OS is configured correctly for the PPI of its screen.
A physical-unit font is always not too large and not too small, so long as the distance to the screen is usual (book-reading distance).
Use this equation:
calc(42px + (60 - 42) * (100vw - 768px) / (1440 - 768));
For anything larger or smaller than 1440 and 768, you can either give it a static value, or apply the same approach.
The drawback with vw solution is that you cannot set a scale ratio, say a 5vw at screen resolution 1440 may end up being 60px font-size, your idea font size, but when you shrink the window width down to 768, it may ended up being 12px, not the minimal you want.
With this approach, you can set your upper boundary and lower boundary, and the font will scale itself in between.
After many conclusions I ended up with this combination:
#media only screen and (max-width: 730px) {
h2 {
font-size: 4.3vw;
}
}
The font size changes depending on the screen size by using CSS You can see that this H1 tag is responsive. (correct me if I'm wrong)
#media only screen and (max-width: 1000px) {
h1 {
font-size:5em;
}
}
#media only screen and (max-width: 500px) {
h1 {
font-size: 3em;
}
}
#media only screen and (max-width: 300px) {
h1 {
font-size: 2em;
}
}
#media only screen and (max-width: 100px) {
h1 {
font-size: 1em;
}
}
<h1>Resize the browser!</h1>

Resources