Ensure an element retains a specified aspect ratio - javascript

Is there anyway to specify an aspect ratio in CSS such as 4:3 or 16:9 and then have the div (container) block fit the current window width and height?
Quite a simple question hopefully it has a relatively simple answer.
Edit: those still interested a great example of achieving this using only styles would be Bootstrap's responsive helpers classes.

For this I fear you'll need some JS. I used jQuery here:
function preserveAspect() {
var scaled = $("#scaled");
scaled.height("100%");
scaled.width("100%");
scaled.css("box-sizing", "border-box");
var ratio = 16/9;
var w = scaled.outerWidth();
var h = scaled.outerHeight();
if (w > ratio*h) {
scaled.width(ratio*h);
// horizontal centering is done using margin:auto in CSS
} else if (h > w/ratio) {
var newHeight = w/ratio;
scaled.height(newHeight);
// for vertical centering:
scaled.css({marginTop: ($("body").height()-newHeight)/2});
}
}
$(document).ready(function() {
preserveAspect();
$(window).resize(preserveAspect);
});
Explanation:
First we scale up our div to 100% in width and height so that we know how much space it has.
Then we look up if it is too wide which means that the width is more
than height times ratio.
If so, change width. Height is at 100% already.
Otherwise it might be too high, in which case we want the scale to be width divided through ratio. To center vertically we use a margin-top set to (window_height - element_height) / 2.
If neither of both rules apply, the div is scaled properly already.
In the end we add event listeners for when document is fully loaded and whenever the window size changes.
Full code and working example here:
http://jsbin.com/efaRuXE/5/

This question's a few weeks old now, but there is a pure CSS way to accomplish this. Thanks to Danield for using it to answer this question. It uses the vw and vh units, like so:
#wrapper {
height:75vw;
max-height:100vh; /* max-height / height = aspect ratio */
width:100vw;
max-width:133.3333vh; /* max-width / width = aspect ratio */
position:absolute;
}
The bad news is that support is iffy in current mobile browsers and in IE before version 11.

Found a way. This may be rough but it should get you going. Set the element's height to zero and then use a percentage for the padding.
jsFiddle example
For example, 4:3:
div {
height: 0;
padding-bottom: 75%;
background: #999;
}
For example, 16:9
div {
height: 0;
padding-bottom: 56%;
background: #999;
}

Unfortunately no.
I've proposed once on www-styles WG # W3C construction like this:
div {
width: 50%;
height: width(56.25%); /* 16:9 ratio */
}
but no one from browser vendors expressed any interest at that moment.
And anyway that solution above allows to define ratio of boxes only. But layout model used by CSS does not allow to define inscribing declaratively.

Related

Is transform: scale(x) a costly operation?

I have a UI element that is designed to work best at exactly '200px' width. But if the size of the UI needs to change based on window / media size, it would be a pain to have to adjust this Component bit by bit and change the width away from 200px.
Is changing the size of a component by using transform: scale(x) to adjust to window / media size an acceptable practice? Is it costly in performance? In practical reality, window / media size will be set from the beginning, so the scale function would only have to be run once anways.
if (screen width < 600px) {
element.style.transform = "scale(.7)"
} else {
element.style.transform = "scale(1)"
}
Is transform: scale(x) a costly operation?
No, the transform operation doesn't require a DOM update. A browser makes a rendering update. Its pros are its performance costs are low, it works fast. Its cons are scaling could greatly downgrade its visual quality (for example, blur images), the downscaled component with its content could be hard to use or read.
A JS usage to set CSS is definitely a costly way to make changes. The most efficient way is to use CSS only (media query).
It looks weird to 'scale' a component for a small screen. A common way to solve it now is to make a responsive layout. But think, you don't need to let its content be dynamic inside. Such a task could be solved with CSS. Just make another step forward. Tie the inner content with outer sizes at CSS - use em/rem units instead of px for all its measures. And the media query will change its base font-size only. Different size, no potential scaling visualization issues, same content position. :)
The CSS could be like this below. Sorry, a minimal working HTML, CSS, JS to demonstrate the concept. To check JS in different screen sizes in this snippet - change your screen size, refresh the snippet. The CSS option works without a refresh.
function setSizeJs() {
const element = document.getElementById('target-element-px');
element.style.transform = window.innerWidth < 600 ? 'scale(.7)' : 'scale(1)';
}
.parent {
font-size: 14px;
}
#target-element-px {
/* original width */
width: 200px;
/* colorize element to show its size */
background-color: green;
}
#target-element-em {
/* main style, will be applied always */
/* an equivalent of 'width 200px' in EMs, where EM is taken as '14px' from the 'parent' class */
width: 14.28571428571429em;
background-color: grey;
}
#media screen and (max-width: 600px) {
/* additional style, will be applied only when the screen size will be less than 600px */
/* it will overwrite the main style */
#target-element-em {
font-size: 0.7em;
}
}
<div class="parent">
<div id="target-element-px" class="target-element" onload="setSizeJs">
Some content for original 200px width
</div>
<div id="target-element-em" class="target-element">
Some content for original 200px width
</div>
</div>

Increment negative value of property based on window size

I don't know if this question has an easy or hard answer.
The situation is that I have an element on the page with negative margin:
.element {
margin-left: -195px;
}
It works well with a screen size 1440x532 (check with Chrome's inspector element).
What I want is kind of simple to explain.
I want an increase of 1 pixel (for instance) in the margin-left of the element anytime the window is larger by one pixel:
So, if window size is 1441, the margin-left of the element be -194px. If the window size is 1451, the margin-left of the element be -184px.
In the same way, I want this to work from 1440px upwards.
IMPORTANT NOTE: What I want is a dynamic value for the margin-left that increases based on screen size and not a kind of media query which would make the value always remain the same between an interval of screen sizes. What I want would force me to add a massive number of media queries.
Is this possible with javaScript or jQuery? (or even CSS?)
The Jquery solutions that other users gave you works perfectly for this use, but if you prefere you can also use a CSS-only alternative (it works even if the user has disabled scripts!).
It has got also a good support among browsers
You can implement your CSS in this way:
#element{
margin-left: -195px;
}
#media screen and (min-width: 1440px){
#element{
margin-left: calc(-195px + 100vw - 1440px); //100vw is the width of the screen
}
}
It adds a pixel for each pixel above 1440
Tell me if this is what you mean
This is not possible with CSS since there is no property or method to capture the window size. If there would be, this could be done using calc().
However, this is possible with JavaScript.
function resizeScreen() {
var windowWidth = $(window).width();
var $element = $('.element');
if (windowWidth > 1440) {
// Calculate the new (negative) margin by subtracting the windows width by 1440 (e.g. 1500-1440 = 60). The new margin would be: -195 + 60 = -135.
var newMargin = $element.css('margin-left') + (windowWidth - 1440);
$('.element').css('margin-left', newMargin)
}
}
$(window).resize('resizeScreen');
Yes is it possible with Jquery with resize()
$(window).resize(function() {
if (($(window).width() <= 1441)) {
$('.element').css('margin-left', "-194px")
}else if($(window).width() <= 1451){
$('.element').css('margin-left', "-184px")
}
});
But i suggest to you to use media queries with css:
#media screen and (max-width: 1441px) {
.element {
margin-left: -194px;
}
}
#media screen and (max-width: 1451px) {
.element {
margin-left: -184px;
}
}

container should automatically adjust to the height of the background image for responsive design css only

I working on a responsive design.
If i load the image with the image tag i have no problem with the size, but then it will load on screen too even if i set display:none. This cause loading problems on smartphone devices...
This way i trying to scale it with background-size:contain, but the problem is i have to add an height for the container.
That means if i have a device with different width the image doesn´t fit more.The same problem with background-size:cover. The image flow over if i change width.
Would do it just with css, because there are many pictures and this cause loading problems with javascript.
#header {
width: 100%;
background-image:url(../images/backgrounds/Header_phone2.jpg);
background-size:contain;
background-repeat:no-repeat;
min-height: 200px;
}
Edit
My solution with JS in the answer, improvement tipps are welcome
I made now something, what is working nice for me.
I´m not really good with jquery, this way i´m looking forward for improvement tipps.
Html:
container in container ...
Css stay almost same:
#header {
height:auto;
}
#header-image{
width: 100%;
min-height: 155px;
background-image:url(../bilder/backgrounds/Header_phone2.jpg);
background-size:cover;
background-repeat:no-repeat;
}
Jquery:
if ($( window ).width() <= 966) {
var screenwidth = $(window).width();
var heightimage = (screenwidth /940) * 198;
$("#header-image").css("height", heightimage);
}
$(window).resize(function() {
if ($( window ).width() <= 966) {
var screenwidth = $(window).width();
var heightimage = (screenwidth /940) * 198;
$("#header-image").css("height", heightimage);
}
});
This is working fantastic !! Same like you add the image with img tag and the image doesn´t load with screen design. (look there)
If javascript disabled set min-heigth, like this the image is displayed too.
With jquery i calculate the height of the image. For this i take the width from the display, divide it trough image width and multiply it with height from image. => the correct height for the container.
With the windows-resize function you can change the size of the window and it still works.
This is very simple and works nice for me.
Click for Jsfiddle.
If you use the js script where you delete the src path from img tag, then it will send a request too. With this variant you don´t have problems, look out first link.
Some skilled guys could improve this: select the image width and height with jquery and make a function.

How do I resize/crop images simualar to how background-size:cover does?

I am building a responsive site using bootstrap 3 & I need a photo gallery on it. The client want to update the gallery themselves..
My issue is the images that they upload can be of any size & any proportion.. How can I make the image fit a certain size div?
Requirements (must work similar to background-size:cover):
-images must keep their original proportions (can be cropped to fit the div)
-images must be stretched/shrunk to fit the FULL div (no white space)
-image must be centered vertically & horizontally in the div
I know I can do something like this but I need it to work more like "background-size:cover":
.myImages {
height:300px;
width:300px;
overflow:hidden;
}
http://jsfiddle.net/w4xTN/1/
EXAMPLE:
You can see at the link below that I have used "background-image:cover" for the "featured properties" photos.. I need to do something similar for normal images (unless someone knows of an image gallery that will support "background-image:cover" for the images?):
http://new.amberlee.com.au/for-sale/browse-for-sales
NOTE: JQuery/Javasript is OK to use & resizing them on upload is not an option ;)
You've got your tag within the .myImages so you need to add properties for your tag hence:
.myImages > img {
height: 100%;
width: 100%;
}
If you want to center the img, just change the height or width attribute to "auto";
you could also hack the img tag to center vertically whereby the image is cropped with playing with the vertical margin:
e.g.
margin-top: -33%;
http://jsfiddle.net/denistsoi/rLmxL/1/
No, you can't get it quite like background-size:cover but..
This approach is pretty damn close: it uses javascript to determine if the image is long or tall and applies styles acordingly.
JS
$('.myImages img').load(function () {
var height = $(this).height();
var width = $(this).width();
console.log('widthandheight:', width, height);
if (width > height) {
$(this).addClass('wide-img');
}
else {
$(this).addClass('tall-img');
}
});
CSS
.tall-img{
margin-top:-50%;
width:100%;
}
.wide-img{
margin-left:-50%;
height:100%;
}
http://jsfiddle.net/b3PbT/
Edit: this is a shameless repost from your last question ;)

Font-size that expands when you resize the window

How do I make my font in HTML such that when I expand the window, the size of the text expands also. Sort of like setting a percentage for the text that will take on a percentage of the size of the box it is in.
Here is an illustration of what I would like to happen:
#box #text {
font-size: 50%;
}
Now lets say #box is 200px, #text should be 100px.
Obviously I can't just put a fix width for #text because in the site #box will be a dynamic width.
Do it in jquery.
$(window).resize(function(){
$('#box #text').css('font-size',($(window).width()*0.5)+'px');
});
Use the vh (viewport height), vw (viewport width), and/or vm (viewport minimum (smallest of the dimensions)) units in browsers that fully support CSS3, and for other browsers listen for resize and JavaScript such as in Razor Storm's answer.
In browsers that support it, you can use CSS media queries to change your layout depending on the width of the window.

Categories