How to fetch aspect ratio within HTML and CSS? - html

Responsive website depends on #media queries which takes value in terms of pixels or screen type.
Is there a way to set media query using aspect ratio of the screen that is being used? How?
Also how to fetch or calculate the aspect ratio of the current screen on which the web page is being displayed from HTML and CSS?

Sadly there's no such thing in CSS like sw or sh to get the screen width / height.
JS to the rescue!
Use JS's screen.width and screen.height
Use CSS aspect-ratio property
Calculate the aspect-ratio: sw/sh : 1
const set_AR = (el) => el.style.aspectRatio = screen.width / screen.height;
set_AR(document.querySelector("#emulator"));
#emulator {
--scale: 0.6;
max-width: calc(100vw * var(--scale));
max-height: calc(100vh * var(--scale));
background: #000;
}
<div id="emulator"></div>

Related

How can i work with negative and percentage values in css calc? (Fluid Design)

I found this awesome css calc function from css-tricks
calc([minimum size] + ([maximum size] - [minimum size]) * ((100vw - [minimum viewport width]) / ([maximum viewport width] - [minimum viewport width])));
I try to use this calc function like this for margin-right
margin-right: calc(-20% + (0 - -20) * ((100vw - 320px) / (1600 - 320)));
I wanted to achieve the following:
-20% at 320px viewport width
0% at 1600px viewport width
The css calc function works perfectly with positive values, but apparently not with negative values. How do I change the calc function to work with percentages and negative values?
I tried this
margin-right: calc(-20% + (0% - -20%) * ((100vw - 320px) / (1600 - 320)));
but this is invalid.
Background
I am using this js function to calculate ranges
function _translateRange(
input,
inputMin,
inputMax,
outputMin,
outputMax
) {
let inputMinA = Math.min(inputMin, input);
let inputMaxA = Math.max(inputMax, input);
return (
outputMin +
((outputMax - outputMin) * (input - inputMinA)) /
(inputMaxA - inputMinA)
);
};
like this
translateRange(window.innerWidth, 320, 1400, -45%, 0%)
I want to convert this function to a css calc function. Why? Why do I not use the js function to calculate margin-right? Because I want to do without as much js as possible in my application.
Note: This flexibility is especially important for me because I also want to work with as few media queries as possible.
Edit
I restructured my css code. I configure my absolute element, so i can use positive px values at begin and end with 0. So in this way, the css calc function works as i aspected.

css responsive fluid html font size based on rem

I want to implement the example from css-tricks based on rems. This is what I got so far. However, the scaling does not work as intended, and the font size increases only tiny amounts. What is the mistake?
html {
font-size: 1rem;
}
#media screen and (min-width: 320px) {
html {
font-size: calc(1rem + 2 * ((100vw - 20rem) / 680));
}
}
#media screen and (min-width: 1000px) {
html {
font-size: 3rem;
}
}
I assume that 2 * ((100vw - 20rem) / 680) returns a px value. If that's true. How can I change it to return rem instead?
Edited to add some clarifications:
I want to use rem instead of px because this allows the user to overwrite the default font size in the browser.
The term 2 * ((100vw - 20rem) / 680) is between 0 and 2 (1 rem equals 16px on normal font size). This is what I want to achieve. I want to have font-size: 1rem + [0, 2]rem between 320 and 1000px viewport width. A linearly increasing rem function based on the viewport width.
Here is a link to a sandbox example.
Edit 2:
I think what I want to achieve is not possible. If the user increases the default font size by 50%, I want the scaling factor also increase by 50%: font-size: 1rem + [0, 2 * 1.5]rem.
The current problem is that the part 2 * ((100vw - 20rem) / 680)) needs to be rem based. This is not possible because there is no way in CSS to strip the unit. If I could strip the unit, I could do this: 2rem * strip-unit((100vw - 20rem) / 680))
If you want a responsive font size then you can use View Width too, no need to use calc or rem for that.
Just change this so you can try it out:
HTML {
font-size: 5vw;
}
View width goes from 0 to 100 so you know how much room you have to work with.
edit: I personally haven't found out how to scale on both axis yet but just the X-axis works good enough in most cases.
Here is a solution for fluid fonts I got from Creating a Fluid Type Scale with CSS Clamp
After some tweaking I ended up with the following Sass code to generate the clamp function.
/*
From https://www.aleksandrhovhannisyan.com/blog/fluid-type-scale-with-css-clamp/
Generates the css clamp function.
Focused on font-size, but may be used for margins and padding
Usage:
clamped(min-size-px, max-size-px, min-browser-width-px, max-browser-width-px)
font-size: clamped(26px, 36px, 600px, 1200px);
font-size: clamped(26px, 36px); //using width default values
Output:
font-size: clamp(1.63rem, 1.11vw + 1.28rem, 2.25rem);
*/
#use "sass:math";
#use "sass:map";
// Default min-mix browser width values for clamped function
$default-min-bp: 500px;
$default-max-bp: 1400px;
// Convert pixels to rems.
#function to-rems($px) {
$rems: math.div($px, 16px) * 1rem;
#return $rems;
}
//round a to number of decimal places.
#function rnd($number, $places: 0) {
$n: 1;
#if $places > 0 {
#for $i from 1 through $places {
$n: $n * 10;
}
}
#return math.div(math.round($number * $n), $n);
}
// Generate css for clamp
#function clamped($min-px, $max-px, $min-bp: $default-min-bp, $max-bp: $default-max-bp) {
$slope: math.div($max-px - $min-px, $max-bp - $min-bp);
$slope-vw: rnd($slope * 100, 2);
$intercept-rems: rnd(to-rems($min-px - $slope * $min-bp), 2);
$min-rems: rnd(to-rems($min-px), 2);
$max-rems: rnd(to-rems($max-px), 2);
#return clamp(#{$min-rems}, #{$slope-vw}vw + #{$intercept-rems}, #{$max-rems});
}

How to maintain position and size for all window sizes in CSS?

I want the image to be at the center of the window, and of the same size irrespective of the window size. Im not sure on how to do this, any kind of help will be appreciated.
Or you can use JavaScript to do it
In case the piscture is 600px x 400px:
var w = ((window.innerWidth)-600)/2;
var h = ((window.innerHeight)-400)/2;
var img = document.getELementByTagName('IMG')[0];
img.style.marginLeft = w+'px';
img.style.marginTop = h+'px';
You must just add the concrete size of the picture in CSS, like this:
img {
width: 600px;
height: 400px;
}
The image will be 600px x 400px in all screen resolutions.

Calculate aspect ratio of an image to get equal heights with flexbox

I was taking a look at:
this code pen about equal responsive height images
I want images to have the same height, despite their width/height differences.
As can be seen in the CSS below, there is usage of flexbox with flex to get the images as this:
/* Important stuff for this demo. */
img {
width: 100%;
height: auto;
vertical-align: middle;
}
.pics_in_a_row {
display: flex;
}
.img1 { flex: 1.3344; } /* <-- how can I calculate this part? */
.img2 { flex: 1.3345; }
.img3 { flex: 0.7505; }
.img4 { flex: 1.5023; }
.img5 { flex: 0.75; }
How can I calculate the part of the flex : number. I guess this is the aspect ratio?
The aspect ratio is X/Y of the image size.
So if the image is 600 pixels wide and 800 pixels high, the aspect ratio would be 600/800=0.75
When knowing this, you can choose one of the methods proposed in the article you referenced:
With the CSS methods, you do have a few options for specifying the
aspect ratio:
Work out the aspect ratio yourself and hard-code it into the CSS (as done in this demo)
Use CSS's calc() to calculate the aspect ratio (e.g. flex: calc(600/800);)
Use a preprocessor to calculate the aspect ratio at build time
I was struggling with this myself. You get the image ratio by dividing its width and height. If you don't use JavaScript just open your calculator and divide image width with the height. If you use JavaScript then to get the flex value you need to divide image width/height. Like this:
const imageRatio = img.naturalWidth / img.naturalHeight;
When getting the value you can use naturalWidth and naturalHeight values that return the original size of the image. I used only height and width in the beginning but it is from the browser and might return incorrect values in some cases (loading image etc).
https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/naturalWidth
What I ended up doing is that I calculate the column widths with JavaScript instead of the flex because it doesn't work if there is text inside the column. Then the math becomes more complex. You have to get the ratio of all images, sum them and you get the total ratio. Then you divide the image ratio with this full ratio to get the percentage.
Here is some pseudocode:
const getFullRatio = (images) => images.reduce((acc, curr) => (curr.naturalWidth / curr.naturalHeight) + acc, 0);
const containerWidth = 740;
const columnAmount = images.length;
const columnMargin = 15;
const marginPercentageToAdd = ((columnAmount * columnMargin) / containerWidth) + 1;
const fullRatio = getFullRatio(images);
const fullRatioWithMargins = fullRatio * marginPercentageToAdd;
images.forEach((img) => {
const imageRatio = img.naturalWidth / img.naturalHeight;
const columnRatio = (imageRatio / fullRatioWithMargins) * 100;
const imageParentDiv = img.closest('.COLUMNCLASS');
imageParentDiv.style.width = `${columnRatio}%`;
const image = img;
image.style.width = '100%';
});

How to set min-font-size in CSS

I want to set a minimum font size to every element in my HTML page.
For example if there are elements with font-size less then 12px, then they will change to 12px.
But if there are elements with font-size grater then 12px, they will not change.
Is there any way to do it with CSS?
In CSS3 there is a simple but brilliant hack for that:
font-size:calc(12px + 1.5vw);
This is because the static part of calc() defines the minimum. Even though the dynamic part might shrink to something near 0.
As of mid-December 2019, the CSS4 min/max-function is exactly what you want:
(tread with care, this is very new, older browsers (aka IE & msEdge) don't support it just yet)
(supported as of Chromium 79 & Firefox v75)
https://developer.mozilla.org/en-US/docs/Web/CSS/min
https://developer.mozilla.org/en-US/docs/Web/CSS/max
Example:
blockquote {
font-size: max(1em, 12px);
}
That way the font-size will be 1em (if 1em > 12px), but at least 12px.
Unfortunatly this awesome CSS3 feature isn't supported by any browsers yet, but I hope this will change soon!
Edit:
This used to be part of CSS3, but was then re-scheduled for CSS4.
As per December 11th 2019, support arrived in Chrome/Chromium 79 (including on Android, and in Android WebView), and as such also in Microsoft Chredge aka Anaheim including Opera 66 and Safari 11.1 (incl. iOS)
CSS has a clamp() function that holds the value between the upper and lower bound.
The clamp() function enables the selection of the middle value in the range of values between the defined minimum and maximum values.
It simply takes three dimensions:
Minimum value.
List item
Preferred value Maximum allowed value.
try with the code below, and check the window resize, which will change the font size you see in the console. i set maximum value 150px and minimum value 100px.
$(window).resize(function(){
console.log($('#element').css('font-size'));
});
console.log($('#element').css('font-size'));
h1{
font-size: 10vw; /* Browsers that do not support "MIN () - MAX ()" and "Clamp ()" functions will take this value.*/
font-size: max(100px, min(10vw, 150px)); /* Browsers that do not support the "clamp ()" function will take this value. */
font-size: clamp(100px, 10vw, 150px);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<center>
<h1 id="element">THIS IS TEXT</h1>
</center>
Looks like I'm a bit late but for others with this issue try this code
p { font-size: 3vmax; }
use whatever tag you prefer and size you prefer (replace the 3)
p { font-size: 3vmin; }
is used for a max size.
Use a media query. Example:
This is something im using the original size is 1.0vw but when it hits 1000 the letter gets too small so I scale it up
#media(max-width:600px){
body,input,textarea{
font-size:2.0vw !important;
}
}
This site I m working on is not responsive for >500px but you might need more. The pro,benefit for this solution is you keep font size scaling without having super mini letters and you can keep it js free.
.class {
font-size: clamp(minimum-size, prefered-size, maximum-size)
}
using this you could set it up so prefered and max values are 5vw but the minimum is 15px or something so it won't go over 5vw but if 5vw < 15px it will stick to 15px
CSS Solution:
.h2{
font-size: 2vw
}
#media (min-width: 700px) {
.h2{
/* Minimum font size */
font-size: 14px
}
}
#media (max-width: 1200px) {
.h2{
/* Maximum font size */
font-size: 24px
}
}
Just in case if some need scss mixin:
///
/// Viewport sized typography with minimum and maximum values
///
/// #author Eduardo Boucas (#eduardoboucas)
///
/// #param {Number} $responsive - Viewport-based size
/// #param {Number} $min - Minimum font size (px)
/// #param {Number} $max - Maximum font size (px)
/// (optional)
/// #param {Number} $fallback - Fallback for viewport-
/// based units (optional)
///
/// #example scss - 5vw font size (with 50px fallback),
/// minumum of 35px and maximum of 150px
/// #include responsive-font(5vw, 35px, 150px, 50px);
///
#mixin responsive-font($responsive, $min, $max: false, $fallback: false) {
$responsive-unitless: $responsive / ($responsive - $responsive + 1);
$dimension: if(unit($responsive) == 'vh', 'height', 'width');
$min-breakpoint: $min / $responsive-unitless * 100;
#media (max-#{$dimension}: #{$min-breakpoint}) {
font-size: $min;
}
#if $max {
$max-breakpoint: $max / $responsive-unitless * 100;
#media (min-#{$dimension}: #{$max-breakpoint}) {
font-size: $max;
}
}
#if $fallback {
font-size: $fallback;
}
font-size: $responsive;
}
A recent feature added to CSS is min() which chooses the minimum value of its parameters.
So in the following code, when the viewport is big (>1500px in this case), the font-size is capped to 30px.
However for any viewport smaller than 1500px, the other value is used: e.g. when viewport is 1000px, then the font-size will be 20px. This means it can be quite responsive.
p {
font-size: min(2vw, 30px);
}
Here's a Codepen with min() for container width and p text:
https://codepen.io/code0312/pen/dyWJLmB
But note, if you later manually set a font size greater than what you put here, that will still override this declaration.
No. While you can set a base font size on body using the font-size property, anything after that that specifies a smaller size will override the base rule for that element. In order to do what you are looking to do you will need to use Javascript.
You could iterate through the elements on the page and change the smaller fonts using something like this:
$("*").each( function () {
var $this = $(this);
if (parseInt($this.css("fontSize")) < 12) {
$this.css({ "font-size": "12px" });
}
});
Here is a Fiddle where you can see it done: http://jsfiddle.net/mifi79/LfdL8/2/
AFAIK it's not possible with plain CSS,
but you can do a pretty expensive jQuery operation like:
jsBin demo
$('*').css('fontSize', function(i, fs){
if(parseInt(fs, 10) < 12 ) return this.style.fontSize = "12px";
});
Instead of using the Global Selector * I'd suggest you (if possible) to be more specific with your selectors.
Judging by your above comment, you're OK doing this with jQuery — here goes:
// for every element in the body tag
$("*", "body").each(function() {
// parse out its computed font size, and see if it is less than 12
if ( parseInt($(this).css("font-size"), 10) < 12 )
// if so, then manually give it a CSS property of 12px
$(this).css("font-size", "12px")
});
A cleaner way to do this might be to have a "min-font" class in your CSS that sets font-size: 12px, and just add the class instead:
$("*", "body").each(function() {
if ( parseInt($(this).css("font-size"), 10) < 12 )
$(this).addClass("min-font")
});
The font-min-size and font-max-size CSS properties were removed from the CSS Fonts Module Level 4 specification (and never implemented in browsers AFAIK). And the CSS Working Group replaced the CSS examples with font-size: clamp(...) which doesn't have the greatest browser support yet so we'll have to wait for browsers to support it. See example in https://developer.mozilla.org/en-US/docs/Web/CSS/clamp#Examples.
It will work perfectly with 50px. Which will act as a static and thus as min-width.
font-size: calc(50px + 5vw);