How to size text based on the height of page? - css

I want a single form of my website to follow a simple rule: the page must appear identical at every resolution you watch.
So I need h1 be height, e.g., 10% of page, h2 be 7%, etc..
Is there a way to realize this with CSS?

Well, as a pure CSS solution you could use vh Viewport-percentage lengths for elements to specify their font-size/line-height base on the viewport height:
EXAMPLE HERE
h1 { font-size: 10vh; line-height: 10vh; }
h2 { font-size: 7vh; line-height: 7vh; }
5.1.2 Viewport-percentage lengths: the vw, vh, vmin, vmax units
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. However,
when the value of overflow on the root element is auto, any scroll
bars are assumed not to exist. Note that the initial containing
block’s size is affected by the presence of scrollbars on the
viewport.
vh unit
Equal to 1% of the height of the initial containing block.
It's worth noting that vh unit is supported in the modern web browsers (including IE9+).

Related

Why padding-left and height are not working the same as padding-bottom and width? [duplicate]

If you look at the CSS box model spec, you'll observe the following:
The [margin] percentage is calculated with respect to the width of the generated box's containing block. Note that this is true for 'margin-top' and 'margin-bottom' as well. If the containing block's width depends on this element, then the resulting layout is undefined in CSS 2.1. (emphasis mine)
This is indeed true. But why? What on earth would compel anyone to design it this way? It's easy to think of scenarios where you want, e.g. a certain thing to always be 25% down from the top of the page, but it's hard to come up with any reason why you would want vertical padding to be relative to the horizontal size of the parent.
Here's an example of the phenomenon I'm referring to:
<div style="border: 1px solid red; margin: 0; padding: 0; width: 200px; height: 800px;">
This div is 200x800.
<div style="border: 1px solid blue; margin: 10% 0 0 10%;">
This div has top-margin of 10% and left-margin of 10% with respect to its parent.
</div>
</div>
http://jsfiddle.net/8JDYD/
Transferring my comment to an answer, because it makes logical sense. However, please note that this is unfounded conjecture. The actual reasoning of why the spec is written this way is still, technically, unknown.
Element height is defined by the height of the
children. If an element has padding-top: 10% (relative to parent
height), that is going to affect the height of the parent. Since the
height of the child is dependent on the height of the parent, and the
height of the parent is dependent on the height of the child, we'll
either have inaccurate height, or an infinite loop. Sure, this only
affects the case where offset parent === parent, but still. It's an
odd case that is difficult to resolve.
Update: The last couple sentences may not be entirely accurate. The height of the leaf element (child with no children) has an effect on the height of all elements above it, so this affects many different situations.
For "n%" margin (and padding) to be the same for margin-top/margin-right/margin-bottom/margin-left, all four have to be relative to the same base. If top/bottom used a different base than left/right', then "n%" margin (and padding) wouldn't mean the same thing on all four sides.
(Also note having the top/bottom margin relative to the width enables a weird CSS hack that allows you to specify a box with an unchanging aspect ratio ...even if the box is rescaled.)
I vote for the answer from #ChuckKollars after playing with this JSFiddle (on Chrome 46.0.2490.86) and referring to this post (written in Chinese).
A major reason against the infinite calculation conjecture is that: using width faces the same infinite calculation problem.
Have a look at this JSFiddle, the parent display is inline-block, which is eligible to define margin/padding on it. The child has margin value 20%. If we follow the infinite calculation conjecture:
The width of the child depends on the parent
The width of the parent depends on the child
But as a result, Chrome stops the calculation somewhere, resulting:
If you try to expand the "result" panel horizontally on the JSFiddle, you will find that the width of them will not change. Please note that the content in the child is wrapped into two lines (not, say, one line), why? I guess Chrome just hard-code it somewhere. If you edit the child content to make it more (JSFiddle), you will find that as long as there is extra space horizontally, Chrome keeps the content two lines.
So we can see: there is some way to prevent the infinite calculation.
I agree with the conjecture that: this design is just to keep the four margin/padding values based on the same measure.
this post (written in Chinese) also proposes another reason is that: it is because of the orientation of reading/typeset. We read from top to down, with the width fixed and height infinite (virtually).
I realize the OP is asking why the CSS specification defines top/bottom margin percentages as a % of width (and not, as would be assumed, height), but I thought it might also be useful to post a potential solution.
Most modern browsers support vw and vh now which lets you specify margin numbers against the viewport width and viewport height.
100vw/100vh equals 100% width/100% height (respectively) if there's no scrollbar; if there is a scrollbar the viewport numbers don't account for this (while the % numbers do). Thankfully, nearly all browsers use scrollbar sizes of 17px (see here), so you can use css calc function to account for this. If you don't know whether a scrollbar will appear or not, then this solution will not work.
For example: Assuming no horizontal scrollbar, a top margin of 50% of height, could be defined as "margin-top: 50vh;". With a horizontal scrollbar, this could be defined as "margin-top: calc(0.5 * (100vh - 17px));" (remember that the minus and plus operators in calc require spaces on both sides!).
I know this question is a bit old, but I'd like to refresh it for CSS3. While it's true that the CSS2.1 specification says that percentage padding and margin are defined relative to the width of the containing block, this is not always the case. It depends on the writing mode. This comes straight from the CSS3 specs:
As a corollary, percentages on the margin and padding properties, which are always calculated with respect to the containing block width in CSS2.1, are calculated with respect to the inline size of the containing block in CSS3.
I cover this in my tutorial on aspect ratios with CSS.
Specifically, there's a section on Percentage Padding in Horizontal vs. Vertical Writing Modes. By default, an element has a horizontal writing mode, where text flows horizontally (in the "inline" direction) from left to right. However, using the writing-mode CSS property, you can actually set the mode to be vertical (with text either flowing from right to left or left to right). Here are some diagrams of horizontal vs vertical writing modes:
These are taken from the MDN docs on writing modes.
In vertical writing modes, percentage padding will be relative to the height of the containing block, not to the width.
Here's proof:
.document {
writing-mode: vertical-rl;
width: 100%;
height: 100vh;
}
.parent {
width: 100%;
height: 200px;
background-color: black;
color: white;
}
.child {
padding: 10%;
background-color: white;
color: black;
border: solid 1px;
}
<div class="document">
<div class="parent">
<div class="child">
Child
</div>
</div>
</div>
The child gets 20px of padding, which is 10% of its containing block's height (200px).
As to the why in the question, this was covered well in the other posts here.

How to set height by screen-height, not by browser-height

How do I set the height of a div container for example that should be 60% of the screen height?
Setting the 60% as the height in css works fine if the browser window is not resized. But if I shrink the browser window, the div shrinks accordingly.
https://zurb.com provides a nice example. The "Mission Accomplished", grey part is always the same height, no matter how the browser window is being resized. How can this be ensured?
I don't want to use px to ensure HiDpi support.
Thanks,
That's a simple fixed-height element; it has nothing to do with screen size.
You should just use px and not worry about anything; px means logical pixels and will work with arbitrary DPIs.
While the page in question simply used a fixed height (px) for the element in question, meaning that it will always have the same height (and won't be 60% of the height regardless of viewport height). In order to have an element be relative to the viewport, you're looking for viewport-sized typography.
To adjust based on height, you're looking for the CSS unit vh, which tells the element in question to scale based on the viewport height. You can also use vw to scale based on the viewport width.
Keep in mind that <body> has a default of margin: 8px, so if you want to avoid scrollbars when using viewport-sized typography, you'll also need to override this back to 0.
body {
margin: 0;
}
div {
height: 60vh;
width: 100vw;
background: red;
}
<div></div>
For more in-depth information on CSS units, I'd recommend checking out this guide.
Hope this helps! :)

Size of font in vmin as percent of container

working on a class project, and something has our whole class, including our teacher, stumped. We're making a calculator out of html, css and javascript. The problem involves CSS. We have set the calculator to height: 50vmin and width: 50vmin.
We then set font-size to 5vmin, expecting it to be 10% of the container height. Instead, the font size is coming out to be around 11-12% or more of the height. For example, on my screen, the container is 323.5 px and the font-size is 37.981px. This does not include the padding or margin: it is the font-size itself. Does anyone know why the font is not coming out 10%? With 5 rows of buttons, plus margins and padding, it makes quite a difference.
Thanks!
font-size: 10vh;
1vh = 1% of viewport height

CSS3 vw for font-size : what does it mean

Definition says 1vw = 1% of viewport width. But I don't get it what does it mean when used with font-size? For instance what does it mean if I set:
h1 {
font-size: 10vw;
}
I thought that if I have h1 with 10 characters it would take 100% of viewport, but it does not.
Font-size refers to the vertical size of the font not character width
See the demo below for how they react differently.
h1 {
font-size: 10vw;
}
h1:nth-of-type(2) {
font-size: 10vh;
}
<h1>MY HEADER</h1>
<h1>MY HEADER</h1>
JSfiddle Demo
As Paulie_D stated:
Font-size refers to the vertical size of the font not character width.
If you're looking for the width of the character, you might want to look at font-weight (for the thickness of a character) or font-kerning (for the spacing between characters).
the vw unit is based on the width of the viewport.
1vw is 1% of the browser viewport width. (vh is the corresponding value for height)
This means if the viewport is 600px wide then 10vw is 60px and that's how high your font will be
It also means that dimensions, including heights, can be set relative to the width of the screen, which is very useful for maintaining aspect ratios. This means your font size will respond to the size of the viewport, something which you can't do with a font any other way
It's not supported in all cases, so it's good to provide a pixel fallback, like this:
height: 100px; /* over-ridden if vw can be interpreted */
height: 10vw; /* ignored if not understood */

CSS width 100% OR max-width in pixels

How one could create a CSS rule for width which
Uses 100% width by default
If 100% width exceeds certain pixel width (let's say 512 px), then the width is clamped down to this pixel width
I am not sure about width and max-width relations, or how calc() is supported or could express this. This would need to work with the latest WebKit browsers and Firefox 4. IE8 etc. support not needed
That's in fact the intended use of max-width. If the computed (actual) width of an element exceeds max-width, it will be constrained to the max value instead of going beyond it. Percentage versus pixels isn't relevant.
Declare both in the same rule like this (no need for the calc() function):
#somediv {
width: 100%;
max-width: 512px;
}
If it's block level element it should be 100% by default so no need to declare the width, then max-width: 512px; would curtail it
calc() is not supported very well at all, but in this case I wouldn't think you would need it
div{ max-width: 512px; }
should suffice.

Resources