I've been wracking my brain over this one, google searches don't really have much in the way of help or even documentation of this problem but it's greatly affecting my current conversion to a mobile-friendly design.
Everywhere I go, everyone's touting using rem-based layouts as the new gold standard, and on the surface the virtues of this approach seem ideal (full accesibility support for both reference pixel based scaling and font-size scaling to support many DPIs and many screen sizes / settings).
However I've run into a rather large snag, I'm finding that Chrome (and possibly all webkit browsers but I don't have a mac atm to test) don't seem to scale the same as the rest.
With the initial setup like this:
html { font-size: 62.5%; }
body { font-size: 1.6rem; }
We should be able to set up all our measurements using 1/10th the pixel size in rems:
.my-element { height: 15rem; } /* 150px */
I've created a simple example that illustrates my problem here: https://jsfiddle.net/gLkpz88q/2/embedded/result/
When you use Chrome and you scale this way out, notice how the layout stops scaling but the content continues.
Compare this to Firefox, IE11, Edge and you don't see this behavior at all, they all scale uniformly and continually.
Here's (Top-Left: Chrome, Top-Right: IE11, Bottom-Left: Edge, Bottom-Right: FireFox) side-by-side:
As you can see this has some terrible implications for layouts if the rem unit scales differently than everything else.
I'm not certain how to proceed with this scenario as it seems like WebKit/Chrome have decided to handle scaling completely differently and this calls in to question all the scaling scenarios going forward.
There's a number of articles advocating just using pixels as the CSS Reference Pixel takes care of mobile scaling rather well:
Just Use Pixels
R.I.P. Rem, Viva CSS Reference Pixel!
However these tend to ignore the font-scaling issue, citing it as an unlikely situation.
I did a quick look around at man big mobile friendly/friendlyish sites I could think of from large & successful companies and it seems most of them just use pixels for all their layout needs. (Google, Facebook, Wordpress, Twitter, Bootstrap 3, [and to some extent Bootstrap 4], MDN, and WebPlatform)
Is Chrome the new Standards-Busting IE? Or am I doing something horribly wrong? I'm tempted to just use pixels at this point for consistency.
I'm going to start my answer by addressing your closing statement first, purely because it caught my eye (besides the humongous bounty).
"Is Chrome the new Standards-Busting IE? Or am I doing something horribly wrong? I'm tempted to just use pixels at this point for consistency."
Yes and no. I have more problems with things not working in WebKit browsers than I do in any other mainstream browser engine, but after investigating the individual issues, I generally find that it's because WebKit tends to stick to the rules provided by W3C more rigidly than others.
Most other browser engines seem to be very lenient with developers, and I love them for this, but we can't necessarily crucify WebKit for following the rules.
To extend the above statements into the rest of your question, I skimmed through W3C document regarding relative font lengths. Under the heading for rem units you will notice the first line stating:
Equal to the computed value of ‘font-size’ on the root element.
Unfortunately, font-size in itself is relatively open to interpretation by your browser engine.
Cyrix's answer is correct in that Chrome will adjust your font size based on a minimum font-size that it has built in to the engine. To solve your problem easily, you could use the text-size-adjust or the newer font-size-adjust rule on your container element to prevent this:
* { /* Replacing "*" with ".my-element" would probably be better for the rest of your site*/
-webkit-text-size-adjust: none;
-webkit-font-size-adjust: none;
}
The problem however is that older versions of Chrome don't accept font-size-adjust, and newer version only accept font-size-adjust and only when experimental features are enabled.
In closing, to answer the rest of your questions, rem and em is a wonderful unit of measurement if you are working with actual text content etc. Think in the lines of:
If you want your<h1>'s to always be about 25% bigger than your body text h1 { font-size: 1.25rem; }
If the height of your header bar must always be 3 times the height of the line of text inside it .header { height: 3em; }
If however you are working with a container type block that needs to fit a specified content block on the inside, it's always better to work with something more stable. Keep in mind, stability does not mean unresponsive.
Take this for example:
.my-element {
width: 95%;
margin: auto;
max-width: 600px;
}
This will float your element nicely in the middle of the page, whilst keeping the element at a size that fits the content inside it, and if the screen size decreases to a point smaller than your .my-element height, it will adjust accordingly.
In short.
Yes, Chrome breaks things on a scale that makes IE jealous, but that's ok.
Yes, a lot of people do try to punt using relative font units as the best thing to do, however contrary to what they may say, you don't need to use it for everything.
Your end result should be a responsive web page. Your means to achieving this will differ based on the content you have.
Font scaling is a influencing factor that is most likely going to be around for a while, if you are worried about how it may affect your web page, ensure that only the elements that need to be scaled in relation to your font, will scale with your font.
"I'm tempted to just use pixels at this point for consistency." This is the logical conclusion in most cases, so go for it :)
That's because Chrome's behavior of setting a minimum font-size, so if you zoom-out, chrome will set the minimum font-size to 6px (12px for chinese and japanese version). So your div will have a minimum width as it depends on your base font-size (which can't be smaller then chrome's minimum).
See also:
Chrome will increase the font size when zooming out
[Edit] Additional Information:
Chromium Tickets & Discussions On this topic:
https://bugs.chromium.org/p/chromium/issues/detail?id=16875
https://bugs.chromium.org/p/chromium/issues/detail?id=36429
-webkit-text-size-adjust Support Dropped, so the viable solution for this behavior is not reliable anymore:
https://trac.webkit.org/changeset/145168/webkit
Don't use this CSS { font-size: 62.5%; } body { font-size: 1.6rem; } it causes more problems that it is worth, due to the fact that you will get different results on browsers that use different base font sizes. Just use this site to calculate the correct rem values. http://pxtoem.com/
This should give you consistent results.
https://jsfiddle.net/WizardCoder/gLkpz88q/3/
UPDATE
https://jsfiddle.net/WizardCoder/gLkpz88q/5/
I have faced this issue non-uniform browser zoom in zoom out on my project while setting the base rem . I have used rem in most of the place in the project .so,I had to set base rem based on the screen size dynamically. I will share few ways to set the base rem and issue I faced.The zoom in and zoom out inconsistent is caused because when we zoom out the screen width icreases and when we zoom in the the screen width decreases.So,if we set rem using the media queries or vw it will look inconistent while zooming in and out.
Fixed unit to set base rem like px ,%:
html{
font-size:68%;
or
font-size:16px;
}
pros:
same base rem on all the screen size.
The browser zoom in zoom out will be consistent
cons:
As it would be fixed value doesn't change based screen size.
sometimes the elements can't adjust on small screen size becoz of the specified base rem
Media queries to set base rem:
html {
font-size: 17px;
}
#media (max-width: 1536px) {
html { font-size: 15px; }
}
#media (max-width: 1920px) {
html { font-size: 13px; }
}
pros:
The base rem changes based on screen size.
cons:
The browser zoom in zoom out will be inconsistent
vw to set base rem:
html{
font-size:1vw;
}
pros:
the base rem will change based on the screen size and adjust. If zoom in zoom out is not important for you project.It would give perfect adaptation for the screen.
cons:
The browser zoom in zoom out will be consistent but the zoom in zoom out won't be working on few elements.so,it might look messy sometimes
Dynamic unit combination to set base rem:
html{
font-size:calc(.5em+.5vw);
}
pros:
Just need to adjust em and vw for base rem as we need for one screen.then base rem will change based on the screen size and adjust.
the zoom in and zoom out will be consistent.
Related
I work for a publicity agency, where my boss designs mockups in Photoshop (based on his 1920x1080 screen), and where the website final layout must look 90% like his, very close. We don't use Bootstrap (or any css framework) as he defines margins and columns himself, so Bootstrap gets more in the way than helping.
We use a mockup image for 16:9 aspect ratio, that can be opened in the browser and fits perfectly if you're viewing it on any 16:9 monitor. When we move on to actually creating the html / css page, we're unable to achieve that effect, and rely on many media queries to 'fix' each bigger or lower resolution than the one it was designed in.
Is there a way to make an element - or the whole body, to simply scale from the original design, so that we don't need to do any media queries between screens that share the same aspect ratio?
This way, we would only have three media queries: One for 16:9, one for 9:16 and one for 16:10.
Additional Info: I'm looking for something that does similar to the transform: scale property, but that one in particular doesn't work here (using it causes problems with buttons becoming unclickable in some browsers).
....Technically, yes, but in reality, it's a lot of work, and won't really save you any time. Your best bet is to go back and start using Bootstrap. At least, using the cols and rows of Bootstrap Bootstrap is a fantastic tool for building responsive websites, for people who aren't comfortable building responsive websites on their own.
I... have a lot of things to say.
First of all,
If you're working on building websites, you really, really should have two monitors attached to your computer. Personally, I prefer having one small (1280x800) and one large (1920x1080) screen, because it makes me more aware and comfortable with responsive design. But that's my personal preference, and many people prefer two large monitors. At the very least, you should also have a 1080p screen, so you can work directly on it.
To answer your question directly, this strategy is not going to work for tablets and phones, because the aspect ratio on desktop computers is "landscape", but in mobile devices the aspect ratio is "portrait". If you've ever tried to view a 1920x1080 image in mobile, you'll immediately see why this a problem.
HOWEVER. If you're looking for a way to scale the entire website based upon the body, ...the approach that comes to mind first, REM, is quite popular, and I assume you've already tried it, but... I'll clarify, just in case.
You can define everything using percent, EM or REM (h1, h2, h3, p, borders, padding, margin, height, fontsize, box-shadow etc... Everything. The phrase px should not appear in your stylesheet.) , and then scale the website with a simple series of media queries like this:
#media( min-width:1200px){
html,body{
font-size: 14px;
}
}
#media( min-width:1400px){
html,body{
font-size: 15px;
}
}
#media( min-width:1600px){
html,body{
font-size: 16px;
}
}
#media( min-width:1800px){
html,body{
font-size: 17px;
}
}
Which will cause the entire website to scale. Obviously, if you're working with a theme or framework(Like Bootstrap), you'll need to modify that framework to use REM too.
#3.The last thing that I have to say is that most websites DON'T look exactly the same on 720p screens vs 1080p screens. For example, take StackOverflow itself. This is what the current page we're looking at looks like:
div#left-sidebar {
width: 164px;
}
#sidebar {/*Right sidebar*/
float: right;
width: 300px;
}
div#mainbar {/*Center section*/
width: calc(100% - 300px - 24px);
}
#content {/*And this wrapper around it all*/
max-width: 1100px;
width: calc(100% - 164px);/*left sidebar*/
}
If you look at it, the entire website is more or less max-width:1480px. If it gets smaller than that, the sidebars stay the same size, but the middle section has width:100% and shrinks to fit the screen.
At around 1000px, StackOverflow gives up and hides the right sidebar, because there's not enough space, but it STILL doesn't change the size of any fonts or icons, ever. (On any screen size, from 1920px all the way down to tablet.)
A good designer should keep this kind of "responsive design" in mind, and give his programmers a design that can shrink cleanly, in this way.
You’re looking for vw css unit. (Not sure if you need vh as well).
Checkout this website for an intuitive understanding of how those units work: https://sparanoid.com
vw unit is relative to viewport width. So if you code everything in vw. your website will behave like an image, just what you ask for.
CSS viewport units (vw, vh, vmin, vmax) are great, and I want to start using them for fonts -- but I noticed here that they aren't that widely supported. I tried to google any best practices for graceful degradation in unsupported browsers, but couldn't find anything useful. Are there any better ways beyond doing something like:
h1 {
font-size: 120%; /* for unsupported browsers */
font-size: 5.3vmin; /* for supported browsers */
}
Thanks in advance!
Native usage
You'll at least want to provide a fallback:
h1 {
font-size: 36px; /* Some tweener fallback that doesn't look awful */
font-size: 5.4vw;
}
Also tells about mimicing the functionality with FitText.js.
For more information, read Chris Coyier's "Viewport Sized Typography" http://css-tricks.com/viewport-sized-typography/
You cannot gracefully degrade the viewport units in CSS simply because there is nothing conceptually even remotely similar in older versions of CSS.
For example, setting font size to 120% does not address the issue at all: it simply sets the font size 1.2 times the parent element’s font size, quite independently of viewport dimensions.
It is, however, possible to approximate the effects of viewport units using client-side JavaScript so that you get the viewport properties and then set the font-size property based on them. See e.g. answers to the question Is there any cross-browser javascript for making vh and vw units work.
As per How to properly use css-values viewport-relative-lengths?, I don't think it's correct to use viewport units outside of restricting them with #media queries for minimum height and width of the viewport, and even then, I think it should only be used when you know that the page they'll be applying to is very small (e.g. a business-card style page), and would otherwise leave the whole viewport screen empty handed.
In other words, what exactly are you looking for when you say font-size: 5.3vmin?
What if I cascade multiple windows one by one, only leaving enough room in each viewport as to see three lines of normal text? The text at 5.3vmin will be so small at to be unintelligible!
Likewise, if I have a huge monitor (say, Seiki 39" # 3840x2160, which, I must point out, is quite affordable at below 400 USD), and you use font-size: 5.3vmin for all your headers on a page with a lengthy article, then you're stripping my ability and comfort to fully enjoy all the extra lines of text that my monitor can support, instead having 5 headers occupy more than a quarter of the screen, which instead could have been filled by a hundred of extra lines of text.
I've read many articles, but I'm not quite sure what is correct today. I want to set the font size properly, but I am not sure what to use.
I've seen body { font-size: 100% } and body {font-size: 62.5% }. I have also read that the font-size should be px or not be px.
What would be the correct way to do it today? If IE 6 [is outdated] and 7 are slowly becoming outdated, what would be the best way to set the font to cascade through the web site?
That is very much depending on your personal programming style and preference.
I for myself prefer to set the font-sizes in em. That gives me the advantage that I can adjust all font-sizes in the page, by changing one number in the body.
If you use a font size of 100% or 62.5% is also personal preference and depending on the layout. No one can tell you an optimal value, because no one knows what you personally like and want.
You should use 62.5%, if you want your font-sizes to be relative (Useful for text zoom in FF and IE)
body {
font-size: 62.5%;
}
p {
font-size: 1.2em; /* this is 12pixel */
}
Why 62.5%? It's a value that works in all browsers
This is less a question, but more general guidelines. This can also be applied to the line-height property, which can be pretty buggy in IE. As a UI developer, my workflow is as follows:
Set a Pixel value on body, generally 12px, 14px, 16px, or 18px. (this will be your default). I would very much avoid using a percentage for your default font-size. I also generally set a percentage or EM based line-height on the body element for all text.
Use EMs to define values for text. You may set your general paragraphs to 1.0em, and your first child to 1.25em to be slightly larger. Set your headers to appropriate sizes and so on. It really depends on the site you are working on, and your preference.
Remember, that with CSS once you set a height, it cascades down. If your default font-height is 12 px, and you set all of your divs to 1.33em, then set a sub element of your div to 1.25em, you are going to have a very strange font-size... It's not wrong by any means, but it's not best practice.
With a little practice this will keep you pretty fluid in knowing what your font-size is at any time, and works well across browsers.
Also with this practice, for the visually impaired who increase font-size, everything usually expands well, if you can imagine that all of your font-sizes would be percentage based off a default pixel size.
A good resource to follow for setting EMs after declaring a font-size on the body is pxtoem.com.
Hope this helps!
I was reading now about how it’s a good practice to set the font on <body> to 62.5%, so that later you can use the divide-by-10 conversion from pixel units.
But I was wondering: why not set <body> to 6.25%? Then you can use the same dimensions for em units as for pixel units, assuming the default browser font size is 16 pixels.
E.g.
body {
font-size: 6.25%; /* 1px */
}
p {
font-size: 12em; /* 12px */
}
Two issues.
I seem to remember that if you set your initial font size quite small using a relative unit like ems, if the user resizes the text Internet Explorer, the font size will change quite a lot between the settings.
It’s an odd phenomenon, and I’m not sure if it still occurs in IE, nor if you’re worried about users in IE who change the font size.
You’re potentially condemning yourself to re-setting the font size every time you nest elements.
An answer I wrote to another question tries its best to explain this, but in short, if you’re doing your font sizes in ems, you’re better off using font-size as little as possible, rather than making it ever-so-slightly easier to use font-size when you do.
For example: say you want all <li>s on the site to use a font size of 12 pixels.
li {
font-size: 12em;/* 12px */
}
If you then use the following HTML:
<ul>
<li>
<ul>
<li>
...
Then you need to do this:
li li {
font-size: .083em;/* 12px */
}
Otherwise the inner <li>s will be 12 pixels * 12 pixels = 144 pixels!
Ems aren’t pixels. Ems refer to a percentage of the nearest ancestor’s font size, whereas pixels refer to actual pixels. In my opinion, trying to turn ems into pixels is more confusing than the alternative. You’re better off setting <body> to the most commonly used font size on the site, only changing from that when you need to, and putting the intended size in pixels in a comment after your em-based declaration. (That way, it’s easier to tell later if you’ve got something wrong.)
(Of course, the only reason we avoid pixels is because IE doesn’t change the size of text sized in pixels when the user changes the font size in the browser. If you’re not worried about that, then just use pixels.)
Short answer: Don't do this. Use px to set font sizes. If you need a bigger font, use a larger number of px.
Long answer:
The idea behind setting the base font is make it obvious how big a ems and exs are. If your base font size is 10px, then 1.0em is 10px, 1.2em is 12px, etc. It seems simple enough. The idea breaks down as soon as a container changes the font size from the base. If you're in a div with the font size set to 20px, then all the sudden 1em is twice as big as it used to be.
It gets worse. People started suggesting that 62.5% should be used rather than 10px.
(Note that 16 * 0.625 = 10). This was suggested because specifying a percentage for font size is a workaround for an issue with old versions of Internet Explorer. The end user couldn't "zoom in" unless you used a percentage.
However, % (when applied as the default font) is an absolute unit. It may seem like a relative unit, but here, it's a percentage of the user agent's default font size, and font sizes are specified in points. This introduces a subtle and incorrect assumption about the user agent, namely that the screen resolution is 96 dpi. This assumption often results in text which looks like this:
Hey check me out, I'm too small to read!
To sum up:
Don't use hacks for old versions of IE (4 years is plenty of time to maintain backward compatibility; IE7 is four years old this month).
Don't make assumptions about your user agent's resolution, and don't set the body font size to a percentage.
If you need more precise typographical control, use a CSS framework like Baseline.
If you are doing this, you will have to make sure you resize every font on the page. If you miss anything, it will be tiny by default (1px).
Resizing every font may be more daunting then you imagine, because when you use relative font sizes, you have to be very specific.
Firefox 3 has introduced a new behavior in which line-height, when unset, differs from how other browsers render it. Thus, a critical section maybe render too high in that browser. Setting a global percentage doesn't work, since it's basis is different. Setting a unitless value such as "1" doesn't work either. Is there some way to normalize this dimension?
The computed value of line-height: normal varies between platforms, browsers (and different versions of the same browser, as you state), fonts, and even different sizes of the same font (see Eric Meyer's article).
Setting a unitless value such as...
body {line-height: 1.2;}
...should work to normalize the spacing between browsers. If this is not working, can you provide a more-detailed description of your stylesheet?
It's hard (impossible?) to get "pixel-perfect" results, but in order to get results that are as predictable as possible, I try to use a line height that produces a nice round value when multiplied by the font-size. We can't know the user agent's default font size, but 16 pixels is somewhat common.
body
{
font-size: 100%;
line-height: 1.5;
}
If the user agent's starting font size is indeed 16 pixels then the line height of 1.5 comes out to a nice, even 24 pixels. Users can and do change the default font size or the page zoom, though, and different browsers have different methods of scaling the page. Nevertheless, I think I've had reasonable success for a majority of the users. If I can't make the line height come out exactly, then I shoot for a little above the integer rather than a little below, because some browsers seem to truncate values rather than round them.
Also, note that if you use a percentage for the line height, it behaves differently when the value is inherited.
body
{
font-size: 100%;
line-height: 150%;
}
p
{
font-size: 75%;
}
Starting from a base font size of 16 pixels, the line height will be 24 pixels. Within a <p> element the font size becomes 12 pixels, but the line height does not become 18 pixels, rather it remains 24 pixels. This is the difference between line-height: 1.5 and line-height: 150%. When body {line-height: 1.5;} is used, the line height for <p> is 18 pixels.
There is absolutely nothing you can do. Every browser has there way of rendering CSS and content. You can use a "Master" reset (as cowgod suggests), but even then, that's not ultimately going to fix the alignment issues. They are there because of actual rendering engine. Apple the CSS to your existing website and test it. Tell me if it makes pixel perfect across the board. It won't.
The only way to actually achieve pixel perfection is to implement specific CSS for specific browsers. Mozilla has the #-moz-doc, IE has it's own hacks, but none of these are part of the W3C specs, and we all know standards are important. So not much of an option.
As David said above, it's hard. I'm inclined to think impossible actually. And I've spent hours trying, trust me! Almost went mad more times than I care to count. It's a hard pill to swallow, but there is just no way around it, unless everyone used the same browsing engine (which would actually take the internet a great leap forward in my opinion). I mean, it wouldn't be that hard to slap whatever interface you want on your browser, so long as you plugin [gecko][webkit][presto][trident][whatever] to handle the backend... Since the good ones are all open source, you could merge the projects and really get going. People need to learn to play nice together ;)
You CAN solve this:
Set line height to 1, then zero in your text using padding-top and padding-bottom, and set height to auto.
.zeroed_in_element {
padding: 4px 2px 5px 2px;
height: auto;
line-height: 1;
}
You should always "reset" styles to eliminate all browser inconsistencies with element styles.
I like Eric Meyer's CSS Reset. Yahoo has one also.