Fluid Typography - html

I'm trying to use fluid typography and the goal is to scale the text between screen sizes 300px and 1160px.
So at 1160px I want 56px H1 and mobile 30px.
The problem I'm having is the H1 increases in size past the 1160px and keeps increasing.
h1 {
font-size: calc(30px + (56 - 30) * ((100vw - 300px) / (1160 - 300)));
}
<H1>Fluid Typography</H1>

You need to limit fluid calculation of h1 between media queries. Try this:
h1 { font-size: 30px; }
#media (min-width: 300px) {
h1 {
font-size: calc(30px + (56 - 30) * ((100vw - 300px) / (1160 - 300)));
}
}
#media (min-width: 1160px) {
h1 {
font-size: 56px;
}
}
First, the minimum font-size needs to be provided: that's the first line. Then between two breakpoints you introduce fluid calculation which, at 300px gives exactly 30px of font-size, and again at 1160px calculates to exactly 56px. After 1160px you keep it at 56px again using media query. This way you have a graceful transition between static and fluid typography between the set breakpoints.
You can find more examples of this here:
https://www.madebymike.com.au/writing/fluid-type-calc-examples/
or here:
https://www.smashingmagazine.com/2016/05/fluid-typography/
Let me know if you need more examples, I've done a lot of these.

If you are using SCSS you can use the following Mixin:
https://gist.github.com/MColl92/3229098c32e20c1d5593865a7e3ea3da
$min_screen_width: 360px;
$max_screen_width: 1448px;
$min_font_size: 38px;
$max_font_size: 52px;
#mixin fluid-type($min-vw, $max-vw, $min-font-size, $max-font-size) {
$u1: unit($min-vw);
$u2: unit($max-vw);
$u3: unit($min-font-size);
$u4: unit($max-font-size);
#if $u1 == $u2 and $u1 == $u3 and $u1 == $u4 {
& {
font-size: $min-font-size;
#media screen and (min-width: $min-vw) {
font-size: calc(
#{$min-font-size} + #{strip-unit($max-font-size - $min-font-size)}*
((100vw - #{$min-vw}) / #{strip-unit($max-vw - $min-vw)})
);
}
#media screen and (min-width: $max-vw) {
font-size: $max-font-size;
}
}
}
}
#function strip-unit($value) {
#return $value / ($value * 0 + 1);
}
To apply globally:
Define your minimum and maximum screen widths
Define your min and max font size for H1 element in px
Apply fluid-type mixin to root element (html or body selector).
Generate px to rem table from https://nekocalc.com/px-to-rem-converter.
(NOTE: you will need to set the root font size to you max_font_size when generating)
Assign REM values to font-size as required

Related

CSS responsive for 1080p and above

Recently I am thinking about creating a responsive website that displays really well on high resolution screens, like 2k and 4k screens, I will also make it responsive on desktop and smaller devices.
Problem:
Because different screen sizes will have different font size, padding and margin so there is going to be a lot of similar media query codes and I don't think it's a good idea to repeating similar media query codes so is there any other good approaches?
Example of REPEATING SIMILAR CODES:
#media only screen and (min-width: 900px) {
.title{
font-size: 1rem;
margin-bottom: 0.2rem;
}
}
#media only screen and (min-width: 1200px) {
.title{
font-size: 1.5rem;
}
}
#media only screen and (min-width: 1920px) {
.title{
font-size: 2rem;
margin-bottom: 0.5rem;
}
}
#media only screen and (min-width: 2560px) {
.title{
font-size: 3rem;
margin-bottom: 1rem;
}
}
#media only screen and (min-width: 3840px) {
.title{
font-size: 3.5rem;
margin-bottom: 1.2rem;
}
}
Is above approach the only approach or is there any other ways I can use so I don't need to change font size, padding and margin on every different screen size.
After some trying out, I created a sass mixin to help myself with my responsive design, I am not sure if this works 100% well but I think it might be able to help a little.
code:
#function size-number($base-size, $new-size) {
#if $new-size != 0 {
#return $new-size;
} #else {
#return $base-size;
}
}
#mixin break-points-resize ($properties) {
$PROPERTIES: $properties;
$BREAKPOINTS: ("1920px","2560px","3840px",);
#for $i from 1 through length($BREAKPOINTS) {
#media only screen and (min-width: nth($BREAKPOINTS, $i)) {
#each $PROPERTY-KEY, $PROPERTY-VALUE in $PROPERTIES {
$SIZE-NUMBERS: map-get($PROPERTY-VALUE, "size" );
// [1920px default size => 2], [2560px default size => 3], [3840px default size => 4]
$BASE-SIZES: (size-number(2,nth($SIZE-NUMBERS, 1)),size-number(3,nth($SIZE-NUMBERS, 2)),size-number(4,nth($SIZE-NUMBERS, 3)));
$INDIV-PROPERTY-KEY: $PROPERTY-KEY;
$VALUE-NUMBERS: map-get($PROPERTY-VALUE, "value" );
#{$INDIV-PROPERTY-KEY}: $VALUE-NUMBERS * nth($BASE-SIZES, $i);
}
}
}
}
h1{
// Specify size, it will use the size that is specified (Three breakpoints, three size)
#include break-points-resize(("font-size":("value": 2rem,"size": (2,3,3.5))));
// Specify 0, it will use the default size (Three breakpoints, three size)
#include break-points-resize(("font-size":("value": 2rem,"size": (0,0,0))));
}
Sorry the code is a little messy

Taming the VW-Unit (CSS) [duplicate]

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.

Easy way to implement responsive font sizing

Is there a way of setting all font sizes to scale down x amount in a media query, instead of setting font size for each element ( h1, h2, h3 ).
Currently I have a media query that looks like this:
#media only screen and (min-width : 1200px) {
body {
font-size: 20px;
}
}
This, however, doesn't set sizes for headings. Is there any way to include all text on a site? Thanks
Yes, basically you set font size in pixels for a root element like html and then you can use rem units to set font sizes for other elements. In your #media rule you will have to change just font-size property for html element and it will equally affect other elements since they depend on root's font-size because you use rems.
html {
font-size: 12px;
}
p {
font-size: 1.1rem;
}
.footer {
font-size: .9rem;
}
#media (max-width: 767px) {
/* now the basis for all the font sizes set in
rems is 10px. For example, font-size for p is 10*1.1 = 11px.
Previously it was 1.1*12 = 13.2px. */
html {
font-size: 10px;
}
}
div{font-size:15px;}
#media screen and (max-width:1200px) {
div{font-size:20px;}
}
#media screen and (max-width:600px) {
div{font-size:25px;}
}
#media screen and (max-width:320px) {
div{font-size:50px;}
}
<div>test font size</div>

Changing font-size on root doesn't affect #media queries [duplicate]

This question already has answers here:
Is is possible to overwrite the browser's default font-size in media queries using EMs?
(2 answers)
Closed 5 years ago.
I'm working in a page that has
html {
font-size: 62.5%;
}
That means 1rem = 10px instead of 1rem = 16px So far, so good.
The problem is that it doesn't affect #media queries.
/*
it should change at 600px and not 960px.
the #media ignores the 62.5%;
*/
#media (min-width: 60rem) {
.el {
background: blue;
}
}
Check this codepen to see the issue.
http://codepen.io/sandrina-p/pen/bqGZjE
I tested on a retina monitor, with Chrome and Firefox. On Safari the issue doesn't happen.
Any solution?
I found the issue.
In #media you need to use em and it will always read the default browser size, ignoring your custom font-size. The same doesn't happen with rem.
So in this case, you need to set 37.5em (600/16), and it will change the at 600px in every browser including safari.
https://zellwk.com/blog/media-query-units/
(...) the only unit that performed consistently across all four browsers is em. There aren’t any differences between em and rem with the exception of bugs found on Safari.
(...) Unfortunately, px media queries remained at 400px in the third experiment, which makes it a no-go if you intend to support users who change their browser’s font-size value.
Hence, my conclusion after these experiments is: Use em media queries.
#media screen and (max-width: 37.5em) {
.el {
background: blue;
}
}
No. It doesn't have to do anything with you html font-size or your .el font-size. Because 1rem is 16px. So you have to calculate it as per 16px.
#media (min-width: 37.5rem) {
.el {
background: blue;
}
}
This would be your 600px media queries breaks.
Try this
<div class="el">
hey there
</div>
// =========== basic template =========== //
$safeArea: 1rem;
body {
font-family: sans-serif;
}
// ======== actual codepen code ========= //
html {
font-size: 62.5%;
}
.el {
background: red;
font-size: 1.6rem;
}
/* it should change at 600 px and not 960px.
the #media ignores the 62.5%;
*/
#media screen and (max-width: 60rem) {
.el {
background: blue;
}
}
see this codepen - http://codepen.io/anon/pen/aJbxOQ

Using em and media queries to set relative font size [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I'm looking to create a responsive design that can be used across all devices
My css contains the following:
#media screen and (min-width: 200px) and (max-width: 400px) {
html {
font-size: 8px;
}
}
#media screen and (min-width: 400px) and (max-width: 800px) {
html {
font-size: 12px;
}
}
#media screen and (min-width: 800px) and (max-width: 1600px) {
html {
font-size: 16px;
}
}
#banner h3 {
font-size: 3.125em;
letter-spacing: 0.3125em;
font-weight: 900;
text-shadow: black 0 0.0753125em 0;
}
My understanding was that if I set the font-size at html level for different media sizes, then using em will ensure that it will be adjusted accordingly for each element.
So on my desktop my #banner h3 displays in 50px (16px * 3.125).
However, when I minimize my browser to 700px I was expecting that the h3 would reduce in size, but this is not happening.
This is my website: http://ec2-52-0-228-105.compute-1.amazonaws.com/
What am I missing here?
You have a font-size: 14px; on your body. The body is a child element of html, that is why the font-size of the html is overwritten.
em refers to the font size of the nearest parent element with a font size, and in your case that is the body.
It seems that the body style comes from a wordpress theme or something. If you don't want to change the corresponding css file, you can change your code to overwrite the body:
#media screen and (min-width: 200px) and (max-width: 400px) {
body {
font-size: 8px !important;
}
}
#media screen and (min-width: 400px) and (max-width: 800px) {
body {
font-size: 12px !important;
}
}
#media screen and (min-width: 800px) and (max-width: 1600px) {
body {
font-size: 16px !important;
}
}
Another possibility is to use rem instead of em, which is not 100% browser compatible: http://caniuse.com/#feat=rem
I think you are looking for rem, not em.
A value in em is relative to the font-size of the (closest) parent element (or the element's font-size) and if the parent has a fixed font-size (in px, for instance) then em would be consistent.
But rem (root-em) is relative to the value of font-size of the root element directly. In HTML, the root element is <html>.
#banner h3 {
font-size: 3.125rem;
letter-spacing: 0.3125rem;
font-weight: 900;
text-shadow: black 0 0.0753125rem 0;
}
It's worth mentioning that rem is supported in IE9+.
As other answers say you should use rem unit in order to match the size of the root element (html tag).
But a faster way of achieving what you intend to do is to use the vw CSS3 unit which is equal to 1% of your viewport width. So you won't have to use media queries at all.