Inconsistent vh unit behaviour - css

I have a pseudo element that appears on hover with:
height: 0.4vh;
The height doesn't change, only the width does. For some reason, however, under certain conditions the heights of different pseudo elements differ (both of the darker lines here have height: 0.4vh):
I put up this fiddle to demonstrate, but realise that it depends on the viewport height whether this weirdness happens:
https://jsfiddle.net/vuw693La/
I am having this issue on Chromium and Firefox. Am I doing something wrong or is there no way to be "pixel perfect" with vh units?

There's some imprecision in browser renderings, especially when percentages or viewport units come into play. In this case, I'd consider whether it's actually worth it to make the height of those lines tied to the viewport. It seems limited to within a few pixels of variance for most screen sizes; maybe either set one size for it, or set static sizes at several breakpoints to gradually scale it up.
.icon_piece::after { height: 1px; }
// tweak breakpoints to whatever works best for your design
#media (min-height: 600px) {
icon_piece::after { height: 2px; }
}
#media (min-height: 900px) {
icon_piece::after { height: 3px; }
}

Some browsers have inconsistencies when using viewport units, specially smaller than 1vw or 1vh.
The way I solved this problem is by assigning larger units (multiplying them by 4 for example) and then using transform: scale(0.25); to get the element back to the desired size.
This is not a straightforward solution as you probably will have to rearrange your code to make it work but I couldn't find any other workaround.

Related

Is it possible to get the difference between width & max-width?

Is it possible to get the difference between width and max-width for a CSS class? For example, let consider the following class:
.className {
width: 100mm;
max-width: 100vw;
}
If the container is smaller than 100mm, let's say it is 90mm, then the difference would be 10mm. Then based on that difference apply different styling, similar to as one would with a media query for different screen sizes.
The use case being, className is 10% (10mm of 100mm) smaller than expected and there for all sub-components in it need to be scaled down by 10% to maintain their relative size.
If not possible with straight CSS can this be done with SASS/SCSS or maybe stylus or LESS?

How to work with percentage rates instead of px rates in responsive design?

So I've applied for a front end job few months ago and got interviewed and they've given me a test task. One of the requirements of this task is that they want the website to be infinitely variable scalable like this one.
To quote the task description it says:
If you scale down the browser window, everything fits perfectly because everything scales in the same ratio. For that you have to work with percentage rates instead of px rates.
Now, my problem is I am a PX guy, I mean I build all of my projects using px and not that confident on using different unit such as em, vw, rem etc. Well I've use other unit like vh but I don't use it often.
So what's the best way to learn or any roadmap that'll help me to migrate from px to percentage. Should I just use tools like px to em?
Practice does make perfect
The short answer is... Start practicing using percentage-based units as that's how you'll learn the little catches. This is a good career move anyway as the idea of matching pixels to a design was crushed long ago with HiDPI screens, mobile devices, etc all rendering pixels differently.
Getting Started
Practically, you need a place to start and that means learning a few new CSS tools.
First
Use rem as a substitute for pixels.
Unlike an em that's relative to its parent font-size, a Rem is relative to the font-size of the root element (usually body) which means its GLOBAL. You can use rems everwhere (font-size, margin, padding, position, etc) and they're ALL based on the root size.
So let's say the root font size is 16px (typical browser default). That means 1rem = 16px. Now a 16px base isn't overly useful when you're doing math in your head. Jonathan Snook wrote about why this works years ago but the basic formula is set the base font size to 62.5% (of 16px) this means that 1rem = 10px and it's much easier to do the math.
Here's what that looks like in code:
body {
font-size: 62.5%;
}
h1 {
font-size: 2.4rem;
/* 2.4rem = 24px */
}
p {
font-size: 1.2rem;
/* 1.2rem = 12px */
}
.padding-left {
padding-left: 2rem;
/* 2rem = 20px */
}
You get the idea...
Fun tip: once you like the layout you can change the body font-size and make everything bigger or smaller. This is useful for things like a small screen where you want the fonts to be a bit larger
Next
CSS Calc() Is your friend. It's designed to help you do math operations on mixed unit values. For example, the browser can then do this type of math: 33.33% - 200px.
.element {
width: calc(33.33% - 20px);
/* maybe you need responsive columns with 10 px of padding on either side */
}
Finally
Start doing all your layout in percents. For example instead of a 3 column layout set to 300px wide (not responsive). You should make them 100/3 or 33.3333333% wide. Percents like this are always based on the parent so 100% = parent's width (regardless of the parent's units).
As a side note, I rarely need to use vh/vw, not because they aren't useful but in general, elements overflow their window in very predictable ways and percents are easier to wrap your head around.
vw and vh are going to be your best bet if it needs to be a percentage of the screen. rem and em are still relative to a starting point (i.e. body { font-size: 16px; } and scaled from there. vw and vh do have some issues on smaller device screens though, but it looks like your demo website has this issue. You can fix this with media queries, but it doesn't look like your example did, it "infinitely" scales as you mentioned.

Wrong screen width on chrome

When I resize the screen of the browser on Google Chrome (I haven't tried on another browser) the value shown is wrong. It makes my work harder when I have to use a media query. I can't find any answers about it. Even if the issue is restricted to Chrome, I would like to know why this happens.
Doesn't match with
#media screen and (max-width: 1067px) {
//do something
}
for example.
EDIT: When I resize the screen to see if my layout broke at a certain width and pick the width shown to use in my media query the query doesnt run at that browser width, but if i put something like 200px more it works but i lose precision.
Using the previous example:
Suppose that is not google site, is my site, and on this width (1067px)I need to center a div.
If I try:
#media screen and (max-width: 1067px) {
margin: 0 auto;
}
It wont work at the specified value (1067px), but if I put something like max-width: 1267px will work but losing precision.
I dont know exactly how much in px is the variation but is around 200px.
The example of center a div is only an example, the fact is: Nothing specified on the query at 1067px work, if I decrease further will work, but too late, forcing me to increase the 1067px to 1267px to run when I want.
IMPORTANT: I have not tried other browsers besides Chrome.
#media screen and (max-width: 1067px) {
//do something
}
I didn't understand your problem well I guess, but I will explain how #media works.
If your screen has from 0 to 1067 width it will work with the css inside this #media screen. It doesn't mean it will limit your screen to some value, you must setup your page to work with max-width of 1067px.
Like this(using max-width on div's and other elements):
<div id="home>
//content
</div>
And your css would be like this:
#home
{
max-width: 1067px;
}
Hope that Helps!

Media Query to Target ONLY Mobile

I want to make a media query to target just my phone. What breakpoint(s) would I use?
For instance, my body max-width is 800px wide with 2px margins. When the window is less than 800px (mobile?) i want the margins on it to be 0px (this works on my browser). Turns out that my phones screen is hi-res and therefore the width of the display never goes below 800px!
Is this because of pixel ratios?
What do I do?
The meta-view-port tag changes how websites are displayed on your phone, or other small screens that may want to 'adjust' a website for you.
Some screens, for instance - an iphone 5 - with no meta-view-port tag, will size the website to fit your screen / but like a little version of your website zoomed out. https://developer.mozilla.org/en-US/docs/Mozilla/Mobile/Viewport_meta_tag
A combination of a view-port tag, and a media-query in your styles would allow you to change your style rules depending on the screen-size. It's kinda best just to make the breaks where things get ugly and not based on the screen sizes of "Today" that will change next month.
I would suggest building from the smallest screen first and moving up as you go with styles like this:
html {
height: 100%;
background: blue;
}
#media (min-width: 400px) {
html {
background: red;
}
}
#media (min-width: 850px) {
html {
background: green;
}
}
etc.
https://jsfiddle.net/5qhmrym5/
If you already have your site built.. and you really want to target the smaller screens, you can use max-width instead of min-width - but I've found that it takes more time and energy to override styles on the way down - then it does on the way up because styles get more complex for larger screens.
#media (max-width: 850px) {
/* styles */
}
If what you want to change is margin value when viewed on mobile you should design your display for use on any screen above the mobile size, 800px wide for you, then create a media query, similar to the ones in the link commented by #Hynes, which changes just margins to 0px.
You are correct in assuming your device is 800px wide due to ratios, but it also has to do with resolution, which are similar topics here. If you imagine a sports jumbo screen, a pixel is nearly an led in size, vs a 1080px display laptop, where the pixels are nearly unobservable. Ratios and resolutions are the reasons displays are tricky to make, and why values such as em's and percentages have come to be, to bypass the differences in display. This is also a large reason of why media queries are so useful
html {
box-sizing: border-box;}
*,*:before,*:after {box-sizing: inherit;}
Try using box-sizing: border-box on your css and also percentages, this is the way I like it, but surely you will find plenty of information about it, just google it.
Found the solution: https://stackoverflow.com/a/18500871/5906166
You need to include this in your header:
<meta name="viewport" content="width=device-width, initial-scale=1">
Explanation:
Fortunately, you can specify a viewport meta tag in the <head> section
of your document in order to control the width and scaling of the
browser's viewport. If this tag has a content value of
width=device-width, the screen's width will match the device
independent pixels and will ensure that all the different devices
should scale and behave consistently.

How to properly use css-values viewport-relative-lengths?

As per Is there a way to up-size the font with CSS to fit the screen?, it's possible to use css3-values/#viewport-relative-lengths (dev3, dev), vw, vh, vmin, vmax, to make the document more fluid.
However, coming from the conservative side, I'd like to ensure that my desire to fit the screen on larger displays doesn't do harm on smaller ones.
I know that with <meta name = 'viewport' content = 'width = device-width' /> and the implicit font-size: 1em;, I'm supposed to be guaranteed that the font size in my page will basically be the same as the font size of the interface elements, and no unnecessary scrolling should appear, either.
As per above, is there a way to ensure vw / vh / vmin / vmax to never ever go below the absolute value of the above relative 1em? Perhaps something do with with CSS4 / CSS3 media queries (dpi, width, length etc)?
By definition, a vw unit is supposed to represent 1% (i.e. 1/100th) of the width of the viewport. (Can anyone confirm if it's roughly the same for the paged media?)
As such, if the viewport width is 50em, then 1vw will equal 0.5em, or, in other words, 1em will equal 2vw.
As such, it would indeed be a good idea to only ever use the vw unit within a media query; it seems like the easiest and most practical visual design and the math would be to target a minimum of 50em width (and also height) as above, and then 2vw (or, if we target minimum height with our media query, too, 2vmin) would guarantee to mean at least 1em, or, in other words, it would guarantee that the magnification will always be at least 100%.
For example, as for OpenBSD ports category listing, the following could be used to magnify the list of the categories (if the window itself is oversized and has sufficient height, too) without affecting the rest of the page nor diminishing the experience on the smaller-sized windows. Here, we use vmin to combat against too much magnification in landscape view (which would result in up/down scrolling), but you have to be careful to also specify a min-height of at least 50em, too (otherwise, we'll be getting below 100% magnification with 2vmin, if the height were to fall below 50em).
#media (min-width: 50em) and (min-height: 50em) {
/* guarantees at least 1em in all viewports */
ul {font-size: 2vmin; -webkit-columns: 4;}
}
(Note that the above appears to detach the ul elements from being zoomable by the user when the rules apply (at least when tested in my Google Chrome), so, overall, the question for best practice still stands.)
Or, for a small business-card-style front page, which only lists your name/address/contact details:
/* automatically magnify business-card-style page in large viewports */
/* please don't use this unless you yourself posses a large monitor! */
#media (min-width: 50em) and (min-height: 64em) {
/* start with 100% at 50em, we'll have 150% magnification at 75em */
html {font-size: 2vmin;}
}
#media (min-width: 75em) and (min-height: 96em) {
/* start with 225% magnification at 75em (75 / 100 * 3 = 2.25) */
html {font-size: 3vmin;}
}
As I was writing this, I also realised that in order to avoid so much magnification as to cause the introduction of the scrolling, it seems like we must absolutely specify both the min-width and min-height of something like 50em, and then also use only the vmin as our unit. Otherwise, a really widescreen window will be magnified way too much with mere 2vw, such that excessive and unnecessary scrolling is very likely to get introduced.

Resources