Is there any way I can have font-sizes relative to the body font-size setting?
I know I could use percentages like this:
body{
font-size: 14px;
}
p{
font-size: 150%;
}
But this produces unwanted results on nested elements, where the font-size becomes relative to the parent element:
li{
font-size: 150%;
}
li li{
/* ... */
}
CSS3 introduced rem(root em), which is html. Unlike em, which sets the unit relative to the parent font-size, rem will set the unit relative to the root. Here is a great article on rem: >>>CLICK HERE<<<
CSS:
html {
font-size: 14px;
}
p {
font-size: 21px; /*cross browser fall-back hack*/
font-size: 1.5rem; /*same as 150%*/
}
li {
font-size: 21px; /*cross browser fall-back*/
font-size: 1.5rem;
}
li li {
font-size:18px; /*cross browser fall-back*/
font-size: 1.25rem;
}
For cross browser compatibility concerns, you can use a fall-back by also including px for desired results.
I am adding my response to Jukka K. Korpela's comment, as I think it is relevant to the original post.
The functionality of rem is an attempt to remove the compounding effect of em/% throughout your document (especially in lists) and also gain elasticity that you do not get with px. em/% requires a great deal of maintenance and with the ever evolving internet environment, this means a-lot of time. Additionally early IE would still require a hack to set the base percentage (most commonly the root [HTML] to 100%) then set the parent element to the necessary size. However, this hack would cause issues with newer browsers that follow the cascade properly. Again, my recommendation is to use rem for the a flexibility and ease of maintenance and a fall-back (for unsupported browsers) of px.
When using relative values, such as font-size: 150%; this is relative to the parent element. You can't change that.
For example if you had:
<div>
<p id=p1>
<p id=p2>
<p id=p3>
...
With this CSS:
div { font-size: 10pt }
p { font-size: 200% }
The result would be p1 would have a font size of 20pt, p2 would be 40pt, p3 would be 8-pt and so on.
You could get around this by overriding the font-size of everything, and then doing a relative font-size on only the relevant elements such as:
* { font-size: 100% }
body { font-size: 10pt }
#p3 { font-size: 150% }
div { font-size: 120% }
But again, any nesting of elements, like <div>s in the above example would again cause the relative font-size to grow or shrink with each nesting.
The best solution in your case is to switch to the use of variables and compile your css in SASS or LESS.
Although, if you don't want to go over the trouble, you can rely on %, em, or javascript...
The absolute unit, the pixel, is used if you want absolute control or in case you need a "pixel perfect" result. On the other hand, the relative units, like em or rem are usually used if the font size needs to change according to the screen size. It provides easier manipulation and requires fewer media query usages.
The em unit is relative to the parent font-size, while the rem unit is relative to the root element.
Here is an example of the usage of the rem unit:
html { font-size: 100% } //usually this is 16px
p,
div {
font-size: 1rem; //this will equal to 16px
}
section,
article {
font-size: 1.5rem; //this will equal to 24px
}
There is a great article here https://kolosek.com/css-relative-font-size/ that explains the absolute and relative font sizes in detail.
Related
I have this code:
<p style="line-height: 1;overflow: hidden;">blah_blah</p>
<p>blah_blah</p>
<p style="line-height: 1;overflow: hidden;">qypj;,</p>
<p>qypj;,</p>
which results in (notice no underscore, and cut characters):
That is, it behaves that way in Firefox (66.0.3 on Windows 10). Other browsers seem to render the underscore. The above snippet runner also seems to work (even in Firefox), unless you run it in "Full page".
This Q is similar to Text changes height after adding unicode character except there are no tricks here. "_" is just a simple ASCII character.
My question is which behavior is the correct one.
Is specific character allowed to change line height (I thought it was only supposed to be font dependent)? Shouldn't line-height: 1 imply it can fit exactly any text?
I suppose some characters are special, such as "p", "g", "j" (and possibly "_") that draw below its line. Still which behavior is the correct one. Is it considered overflow or not?
PS: Furthermore I find it funny either overflow-x: hidden;overflow-y: visible; and overflow-x: visible;overflow-y: hidden; still causes this. Which seems more like an actual bug to me.
My question is which behavior is the correct one.
All of them are correct because we don't have the same default font in all browsers and it's also different depending on the OS.
Is specific character allowed to change line height (I thought it was only supposed to be font dependent)?
Character doesn't change line-height. To be more accurate, line-height is a property that can only be changed by setting line-height but you are probably confusing with the line box that is defined by the line-height and a character alone cannot change it.
Shouldn't line-height: 1 imply it can fit exactly any text?
Not necessarely, line-height:1 means that the line box will be equal to the 1xfont-size 1 but is the font designed to include all the character inside this space? Probably most of them will do but we don't know.
Basically, you have two things to consider. The content area that is defined by the font properties and the line box that is defined by the line-height. We have no control over the first one and we can only control the second one.
Here is a basic example to illustrate:
span {
background:red;
color:#fff;
font-size:20px;
font-family:monospace;
}
body {
margin:10px 0;
border-top:1px solid;
border-bottom:1px solid;
animation:change 2s linear infinite alternate;
}
#keyframes change {
from {
line-height:0.2
}
to {
line-height:2
}
}
<span >
blah_blah
</span>
The red is our content area and its height is defined by the font properties and if you inspect the element you will see it has a height equal to 23px (not 20px like the font-size) and the borders define our line box that we control using the line-height.
So if the line-height is equal to 1 we will have a line box equal to 20px which is not enough to contain the 23px of the content area thus it will get truncated and we may probably hide some characters (or a part of them) which is logical:
span {
background: red;
color: #fff;
font-size: 20px;
font-family: monospace;
}
body {
margin: 5px;
line-height: 1;
overflow:hidden;
}
html {
overflow:auto;
}
<span>
blah_blah ÂÄ j p
</span>
a different font-size will remove the underscore in Firefox:
span {
background: red;
color: #fff;
font-size: 26px;
font-family: monospace;
}
body {
margin: 5px;
line-height: 1;
overflow:hidden;
}
html {
overflow:auto;
}
<span>
blah_blah ÂÄ j p
</span>
Another example with a Google Font where the result should be the same cross browser. The underscore is visible but not the ^/¨
span {
background: red;
color: #fff;
font-size: 26px;
font-family: 'Gugi', cursive;
}
body {
margin: 5px;
line-height: 1;
overflow:hidden;
}
html {
overflow:auto;
}
<link href="https://fonts.googleapis.com/css?family=Gugi" rel="stylesheet">
<span>
blah_blah ÂÄ j p
</span>
Another example where the underscore is not visible:
span {
background: red;
color: #fff;
font-size: 27px;
font-family: 'PT Sans', sans-serif;
}
body {
margin: 5px;
line-height: 1;
overflow:hidden;
}
html {
overflow:auto;
}
<link href="https://fonts.googleapis.com/css?family=PT+Sans" rel="stylesheet">
<span>
blah_blah ÂÄ j p
</span>
You can clearly see that we have a different overflow everytime we use a different font which confirms that this is font related. We have no control over it unless we know how the font is designed.
Related questions:
Understanding CSS2.1 specification regarding height on inline-level boxes
Why is there space between line boxes, not due to half leading?
Line height issue with inline-block elements
Here is a good article to get more accurate details and calculation: https://iamvdo.me/en/blog/css-font-metrics-line-height-and-vertical-align
A quote from this article:
It becomes obvious that setting line-height: 1 is a bad practice. I remind you that unitless values are font-size relative, not content-area relative, and dealing with a virtual-area smaller than the content-area is the origin of many of our problems.
1 : I considered a simplified explanation but in reality the calculation of the line box is not only relate to the line-height property.
The default line-height (depending on the font-family) when not otherwise specified is about 1.2 in most browsers. This includes Firefox.
This would explain why the underscore did not show in FireFox when the line-height was set to 1 - the bottom was of the line was cut off. So I don't think it's entirely to do with the font (although this does contribute), but also browser defaults.
Some font-sizes are bigger than other even at seemingly the "same" font size (as I'm sure you've seen when typing documents in e.g. Georgia vs Times new Roman/Baskerville ; so you wouldn't be guaranteed that text would always show on a specified line height of 1 (or 1.2). There are ways of measuring a font in pixels however
Hope this helps
If I use the browser tools in Firefox to inspect my snippet below, there is no height difference between the lines with and without underscore. The only difference is caused by the line-height setting: 16px with line-height: 1, 19.2 px with the browser's default line-height. So the underscore doesn't make a difference here (Firefox 66.0.3 on Mac), and it is visible in both cases.
Note that I set margins to 0 to see the "pure" line-height without distances between the lines. Also, I didn't specify a font-familiy setting, so the default font of the browser for p tags is used.
The only reason for what you describe which I can think of is a font with very particular dimensions/settings, where the descenders (i.e. the parts of letters like p q j which extend below the baseline) are not inside the line-height as defined by the font.
After a bunch of comments back and forth: I suppose it could be caused by the different default (system) fonts on Windows and Mac. Still a bug, I would say (if you are using the default font).
html,
body {
margin: 0;
padding: 0;
}
p {
background: #fb6;
margin: 0px;
}
<p style="line-height: 1;overflow: hidden;">blah_plah</p>
<p style="line-height: 1;overflow: hidden;">blah plah</p>
<p>blah_plah</p>
<p>blah plah</p>
When I change my font-size from 1em to 1.1em, the font changes to a huge size. It looks like about size 48px or something. It should only increase by 10%.
* {
font-size: 1.1em;
}
Because with that selector every nested element increases the size by 10%. You might want 1.1rem instead, or better yet, just set :root { font-size: 18px; }
#ray hatfield's answer is correct.
As an alternative, you might want to change the * selector of this rule to html.
html {
font-size: 1.1em;
}
This way only the "basic font-size" (defined for the html tag, which is defined by the browser's default settings) will be increased by 10%, and all other font sizes (but only those with a relative unit like em or rem will change accordingly.
I have a base size in my html of 62.5% and I multiply my headers' font-sizes accordingly. When I inspect it in my Chrome: different h2 headings have the same font-size, but they appear in diff. sizes on my screen. From my understanding the font sizes (with %) depend on the font-size of html. But anyways the parent containers are also the same width.
html {
font-size: 62.5%; }
h1, h2, h3, h4 {
text-align: center; }
h1 {
font-size: 250%; }
h2 {
font-size: 187.5%; }
h3 {
font-size: 125%; }
h4 {
font-size: 100%;
font-weight: bold;
margin-bottom: 0.5em; }
I figured out, that there are two font-sizes in the parent elements, which are crossed out. If I deactivate them in my developer window it still affects the size of the headers. Interesting to see.
But I think I had a misunderstanding, I thought if I have a parent defined in the css like
div h1, the font-size of the parent affects the size. But it seems that every parent font-size has an effect on its child elements. That makes working with %, like in the article below, in my humble opinion useless, because you are not able to set a hierarchy for the fonts. Or am I wrong? So the best way would be to use rems everywhere to get consistent font-sizes?
In html tag set font size in percentages, in body tag set to 1em, and other tags use em units
My site is almost totally designed in "em" (as opposed to px). It is supposed to be much better for modern browsers.
Most of the text is font-size:1em. 1em = 16px by default, I didn't specify it.
But I have some content where font-size is 1.2em and other which is 0.8em (for example for H1 or for small buttons).
The issue with "em" is that it re-scale all the sizes of an element (margin, padding, height...) according to the font-size.
I have the specific code in my CSS:
/* Reset */
html [and many other elements] {
font-size: 100%;
font: inherit;
}
/* Design */
body {
font-size: 1em;
line-height: 1; /* Line height will equal the em of each element */
}
.small-button {
font-size: 0.8em;
margin-left: 1em;
}
.normal-button {
font-size: 1em;
margin-left: 1em;
}
The normal-button has a margin of 1x1x16 = 16px. But the small-button has a margin of 1x0.8x16 = 12.8px.
Apparently this is a specific "em" property (it would not be the case in "px") which scales everything according to the font-size of the element.
This example is simple; but on my website it makes things really hard for me to keep things consistent.
How can I de-activate this property so that in the example above the 2 buttons have the same margin? (without re-calculating the sizes; which is what I am doing right now!)
It is the purpose of the em unit that it is relative to the currently set font size. If you want to use an consistent form of em, use the unit 'rem'. It is relative to the root element of your page (most likely your html tag) and stands for root em.
Check out this article by Jonathan Snook if you want to learn more about it.
http://snook.ca/archives/html_and_css/font-size-with-rem
Personally, I set my "master unit" in the body and proceed in multiples of 10s. I hate 16pt as stock, because I don't want to use a chart to set my font sizes the sizes I want them.
body { font-size:10pt; }
As far as particular elements, keep in mind that if you have an element (say a ul) with a size of 1.2em, and the li set to 1.0, and your body is 10pt, then the li is actually based off it's parent container, so it would be 1.2em instead of 1.0(aka 10pt as set in the body), because it's parent is 1.2em.
If you have something that you want a specific size throughout (such as a main menu), I suggest you forgo the em method on that particular parent object (or the li themselves) and use a set px or pt method.
This may be a bit stupid, but I'm having a problem with the font size of text inside a div.
In my CSS I have used
*{
font-size: 16px;
}
#newsletter{
font-size: 14px;
}
When I do this Chromes Element Inspector shows that it is using the 16px from the * selector.
When I use
#newsletter p{
font-size: 14px;
}
That works, I know that It uses that because it is a more specific selector, but why doesn't it pick up the 14px set to the #newsletter selector, it is further down in the CSS so it should take priority, does it not work because the * selector takes priority for some reason, or does setting font-size on a div not work, does it have to be on the #newsletter p selector instead.
Try
#newsletter *{
font-size: 14px;
}
You probably want to apply the font-size to all children of newsletter
When you have any element (p in this case) inside another element (the element with id=newsletter in this case), then the styling of the inner element is always based on its own CSS properties. In this case, the only rule that assigns font-size to the inner element is *{ font-size: 16px; } so it takes effect. Anything that you set on outer elements cannot possibly affect this.
This is part of the CSS cascade.
If you want to set a fixed font size for the element with id=newsletter and all of its descendants (inner elements), you can set
#newsletter, #newsletter * { font-size: 14px }
A more structured approach is
body { font-size: 16px }
#newsletter { font-size: 14px }
When you don’t otherwise set font size, then elements will inherit from body or from the element with id=newsletter, depending on their placement.
An even better approach, with the same basic logic but with font size automatically adjusting to browser settings (user preferences) is
body { font-size: 100%; } /* logically not needed, helps against some bugs though */
#newsletter { font-size: 0.875em; } /* 14/16, giving 14px for body font size 16px */
Alternatively, use body instead of *. That will achieve the same thing without having specificity issues.
body {
font-size: 16px;
}
#newsletter {
font-size: 14px;
}