How to give image a max-height but retain aspect ratio? - javascript

The image is 100% of the document width. I want the max-height of the image to be 2/3 of the screen height but to retain aspect ratio, and for the image to be centered.
Here is a Fiddle for a starting point.
EDIT: I've updated the fiddle to demonstrate one CSS solution I found (shown below in answers) but it would be preferable to have a solution that has more browser support.
Html:
<header>
<div class="header-content"></div>
</header>
<div class="image-wrapper">
<img class="image" src="http://designyoutrust.com/wp-content/uploads/2013/06/376.jpg" alt="pic" />
</div>
<div class="other-content">
</div>
CSS:
header {
width: 100%;
border: 1px solid black;
box-sizing: border-box;
}
.header-content {
height: 5em;
}
.image {
width: 100%;
}
.other-content {
height: 20em;
width: 100%;
background-color: black;
}
I've just started learning web development so I'm very new to all this. I've tried creating a function that says if image height >= 67vh then html width = image width but I couldn't get it to work.

This solution works although I would rather have a solution with better browser support.
.image-wrapper, .image {
max-height: 67vh;
}
body {
max-width: 119.0525vh;
margin: auto;
}
The max-width was calculated with the aspect ratio of the original image in relation to viewport height.
Calculation is (image width / image height) * percentage of viewport height = max-width
In this case (1354px / 762px) * 67vh = 119.0525vh

image {
display: block;
max-width: 119.0525vh;
max-height: 67vh;
width: auto;
height: auto;
}
source: CSS force image resize and keep aspect ratio

most common way I make is using div's background instead of img, set background-size 100% and leave height empty, it will keep aspect.
html:
<div class="image"></div>
css:
.image {
width: 100%;
height: 100vh;
background-image: url(http://designyoutrust.com/wp-content/uploads/2013/06/376.jpg);
background-repeat: no-repeat;
background-position: center center;
background-size: 100%;
}

If you application is intent to use any king of image in terms of aspect ratio and resolution. Then you can use below concept:
HTML:
<img src="#Model.ThumbnailUrl" id="imageThumbnail">
Javascript:
<script>
$(document).ready(function () {
$('#imageThumbnail').each(function () {
var maxWidth = 601; // Max width for the image
var maxHeight = 257.14; // Max height for the image
var ratio = 0; // Used for aspect ratio
var width = $(this).width(); // Current image width
var height = $(this).height(); // Current image height
// If Height width are same
if (height === width) {
$(this).css("height", maxHeight);
$(this).css("width", maxHeight);
}
// Check if the current width is larger than the max
if (width > maxWidth) {
ratio = maxWidth / width; // get ratio for scaling image
$(this).css("width", maxWidth); // Set new width
$(this).css("height", height * ratio); // Scale height based on ratio
height = height * ratio; // Reset height to match scaled image
width = width * ratio; // Reset width to match scaled image
}
// Check if current height is larger than max
if (height > maxHeight) {
ratio = maxHeight / height; // get ratio for scaling image
$(this).css("height", maxHeight); // Set new height
$(this).css("width", width * ratio); // Scale width based on ratio
width = width * ratio; // Reset width to match scaled image
}
});
});
</script>

for setting div width according to image width try this:
var image = new Image()
image.onload = function(){
$('.image-wrapper').width = image.width
}
image.src = 'http://designyoutrust.com/wp-content/uploads/2013/06/376.jpg';

Related

Why am I getting overflow when i mentioned width to be window.innerwidth and height to be window.innerheight

screenshot for reference
So I have been wondering what is causing the overflow to happen when I mention height and width to be window.innerheight and window.innerwidth respectively.
Here's a snippet:
var canvas = document.querySelector('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
* {
box-sizing: border-box;
}
html,
body {
margin: 0;
padding: 0;
}
canvas {
border: 1px solid;
}
<body>
<canvas id="canvas" width=""></canvas>
<script src="./canvas.js"></script>
</body>
Set the width and height in css by using:
canvas {
width: 100%;
height: 100%;
}
The short answer seems to be that width and height are HTML attributes - nothing to do with CSS - whereas box-sizing is to do with CSS. i.e. the box-sizing is not affecting the width/height + border settings so you get overflow.
For the longer answer I tried to understand what was happening on my Windows10 system (Edge/Chrome) when setting the canvas dimensions by CSS, leaving the attributes untouched. I only partially understand, the x direction seemed fine, the border was there but the vertical border on the right was hidden bizy a vertical scroll bar - it seemed as though the calculation was one pixel out until I went full screen at which point there was no scrolling.
Hopefully someone else can explain in more depth what is happening here as the box-sizing on the canvas seemed to work but not to the full extent.
This snippet sets everything to have margin and padding 0 just to be on the safe side.
canvas = document.querySelector('canvas');
function resize() {
//canvas.width = window.innerWidth;
//canvas.height = window.innerHeight;
canvas.style.width = window.innerWidth + 'px';
canvas.style.height = window.innerHeight + 'px';
}
window.onresize = resize;
resize();
* {
box-sizing: border-box;
}
* {
margin: 0;
padding: 0;
}
canvas {
border: 10px solid;
}
<canvas id="canvas" width=""></canvas>

How to create canvas that scales well with browser window resize

I can't seem to get my canvas to be perfectly responsive.
Using 100% or 100vmax for height and width makes it responsive but it looses clarity.
The center of the canvas seems to be at the bottom of the page as if the canvas stretches beyond the screen
canvas when width is set to 100% or 100vmax
Canvas when width is set through javaScript NOT RESPONSIVE
You'll need to know the aspect ratio of the canvas to do this. You can't simply apply 100% width and height as that will stretch to 100% width and 100% height of the body.
Example:
Lets say I have a Canvas with the dimensions of 864 x 576 and I want it to be responsive to the full body.
Find the percentage/ratio of the canvas. To do this you can do it manually or through JavaScript. In this example lets do it manually for a non-changing image.
ratio = width / height * 100
So here our ratio will be ratio = 864 / 576 * 100 that would be 150% (as in 1.5:1 or 3:2)
We now add the styles using the viewport height vh.
canvas
{
display: block;
margin: auto;
width: 150vh;
height: 100vh;
}
Now one problem remains. What if the window width is smaller than the canvas? Okay, we create a CSS media query and do the opposite of what we've done.
ratio = (height / width) * 100
So here our ratio will now be ratio = 576 / 864 * 100 that would be 66.66% (as in 0.66:1 or 7:10)
We need to use the viewport width now for the canvas width and height. width is always 100vh.
#media (max-width: 150vh)
{
canvas
{
width: 100vw;
height: 66.66vw;
}
}
The max-width media query needs to be equal to the canvas width, which is 150vh in this example.
Take a look at the code: https://codepen.io/StudioKonKon/pen/oQobaa
var image = "https://res.cloudinary.com/studiokonkon/image/upload/v1541450918/sample.jpg";
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
canvas.width = 864;
canvas.height = 576;
var background = new Image();
background.src = image;
// Make sure the image is loaded first otherwise nothing will draw.
background.onload = function()
{
ctx.drawImage(background,0,0);
}
body { margin: 0; padding: 0; background: #000; }
.mycanvas
{
display: block;
margin: auto;
width: 150vh;
height: 100vh;
}
#media (max-width: 150vh)
{
.mycanvas
{
width: 100vw;
height: 66.66vw;
}
}
<canvas id="canvas" class="mycanvas"></canvas>
Please be aware support of the vh and vw units are only supported in the latest browsers and assuming you don't care about Internet Explorer.
https://caniuse.com/#feat=viewport-units

Maintain aspect ratio of background-image

I need to present images in a container using the CSS property background-image
The problem here is that I need to present every image keeping the aspect ratio of it, and maximize the presentation of the image to the height or width of the image centered inside the container.
HTML:
<div class="fotowind shadow"></div>
EDIT:
Initial CSS properties of the .fotowind container:
.fotowind {
overflow:hidden;
margin-left:10px;
background:#333;
margin-bottom:5px;
z-index:30;
background-position: center center !important;
background-repeat: no-repeat;
}
Code to build the properties dynamically based in the size of the window - I need to resize the image keeping the ratio, even of some empty space as to remain on the sides:
jQuery:
windowWidth = $(window).width();
windowHeight = $(window).height();
if (windowWidth <= 1200 && windowWidth > 768 || windowHeight < 900)
{
$('.fotowind').css('width', '650px').css('height', '425px');
}
else if (windowWidth > 1200 || windowHeight > 900)
{
$('.fotowind').css('width', '950px').css('height', '650px');
}
if (windowWidth <= 768)
{
$('.fotowind').css('width', '450px').css('height', '425px');
}
Resulting HTML:
<div class="fotowind shadow" style="background-image: url(http://localhost/AdPictures/25/2c/c2/4c/-9/77/1-/4b/77/-b/ff/a-/57/e5/10/2b/31/b1/7516_1_xl.jpg); background-size: 100%; width: 950px; height: 650px; background-position: 50% 50%; background-repeat: no-repeat no-repeat;"></div>
In some situations where an image has size 800x600, for example, I can't present it with this size, or when the image has 200x650, for example, it deforms to the container size.
As I saw that you are already using jQuery, so I assume that you are open to jQuery solution, because, as I read your comment which says
I want to center the background-image if the viewport size exceeds
the original image size, and if it's equal to or less than the real
size, than you want a responsive background
So here, I am using jQuery to detect the windows height and width and accordingly am resizing your background-image
Demo
$(window).on('resize', function() {
if($(window).width() < 300) { //original idth of your background image
$('div.fotowind').css('background-size', '100% auto');
} else if($(window).height() < 300) { //original height of your background image
$('div.fotowind').css('background-size', 'auto 100%');
} else {
$('div.fotowind').css('background-size', 'auto');
}
});
There is no CSS solution as such because we don't have max-width and max-height for background-size so if you are looking for a pure CSS solution, than you will need an absolute positioned img tag, with max-height and max-width defined with a z-index set to negative, but still you will face some issues regarding the element center positioning...
After you commented, you said that the images will be dynamic in dimensions, and the container will be fixed so..
Here, now the code is completely compatible with your fixed width container elements.. you need to do nothing now and it's completely dynamic, also thanks to this answer which helped me to fetch the height and width of the image
$(document).on('ready', function() {
var image_url = $('div.fotowind').css('background-image'), image;
// Remove url() or in case of Chrome url("")
image_url = image_url.match(/^url\("?(.+?)"?\)$/);
if (image_url[1]) {
image_url = image_url[1];
image = new Image();
image.src = image_url;
}
// just in case it is not already loaded
$(image).load(function () {
imgwidth = image.width;
imgheight = image.height;
if($('div.fotowind').width() < imgwidth) {
$('div.fotowind').css('background-size', '100% auto');
} else if($('div.fotowind').height() < imgheight) {
$('div.fotowind').css('background-size', 'auto 100%');
} else {
$('div.fotowind').css('background-size', 'auto');
}
});
});
Few demos to illustrate the above code in action...
Demo 1 (Where image size > than the elements size)
Demo 2 (Where container size > image size)
Demo 3 (Where image height > container height)
Demo 4 (Where image height > container height [2])
Demo 5 (Where image width > container width)
You can use background-size: cover
body {
margin: 0
}
.fotowind {
background: url(//placehold.it/400) fixed no-repeat center / cover;
min-height: 100vh /*demo purposes*/
}
<div class="fotowind shadow"> </div>
See more info on this article
I tried to propose two different solution, one with a background-image and the other one with an image tag.
Here is the code:
HTML
<div class="container">
<img src="https://upload.wikimedia.org/wikipedia/commons/e/e2/Mei_Foo_Station_2.JPG" alt="foo" />
<div class="bg"></div>
<div class="bg bg_h_s"></div>
<div class="bg bg_h_m"></div>
<div class="bg bg_h_l"></div>
<div class="bg bg_w_s"></div>
<div class="bg bg_w_m"></div>
<div class="bg bg_w_l"></div>
</div>
CSS
.container {
text-align: center;
background-color: grey;
}
.bg {
background: url(https://upload.wikimedia.org/wikipedia/commons/e/e2/Mei_Foo_Station_2.JPG) no-repeat center center blue;
-webkit-background-size: contain;
background-size: contain;
height: 480px
}
img, .bg {
width:100%;
max-width:640px;
margin: 30px auto;
}
.bg_h_s {
height:100px;
}
.bg_h_m {
height:200px;
}
.bg_h_l {
height:300px;
}
.bg_w_s {
width:200px;
}
.bg_w_m {
width:400px;
}
.bg_w_m {
width:600px;
}
Here is the working codepen

resize image to browser proportionally checking width and height

I'm building a fluid website in which an image must scale to a maximum size depending on the viewport of the browser (minus some margins). I don't want the image to crop or lose its original proportions, so depending on the width or height it should resize to the maximum size possible without cropping.
I wrote some javascript code, but since I'm not a hardcore coder I was wondering how to fix this in the right way. The script works, but has a bug when resizing. It seems that it only processes one if statement when resizing the browser window.
function setSizes() {
var margin_top = 100;
var margin_right = 85;
var margin_bottom = 10;
var margin_left = 85;
// get image width and height
var img_w = $('.gallery_img').width();
var img_h = $('.gallery_img').height();
// calculate viewport width and height
var vp_w = $(window).width() - margin_right - margin_left;
var vp_h = $(window).height() - margin_top - margin_bottom;
//
if (vp_w <= img_w || vp_w > img_w) {
// new width
var img_w_new=vp_w;
// calculate new height
var img_h_new=Math.round((img_h*img_w_new) / img_w);
}
//
if (vp_h <= img_h || vp_h > img_h) {
// new height
var img_h_new=vp_h;
// calculate new width
var img_w_new=Math.round((img_w*img_h_new) / img_h);
}
// change image width and height to new width and new height
$('.gallery_img').width(img_w_new);
$('.gallery_img').height(img_h_new);
}
// onload
$(window).load(function(){ setSizes(); });
// on resize
$(window).bind("resize", function() { setSizes(); });
I searched for a solution for quite some time, but most scripts I found only check and change the width.
Does somebody know how to fix this?
Thanx!
this might be a lame answer but why don't you just use css width setting?
see http://jsfiddle.net/dXm4r/
I think this is a wrong approach? It would be more natural to define width of enclosing container in percents and than define width 100% on image. Something like this:
div.img-container {
width: 30%;
}
div.img-container img {
display: block;
width: 100%;
}
<div class="img-conatiner">
<img src="...
</div>
Please pay attention to the fact that in img CSS rule there is no height specified, this will allow browsers to properly scale image without loosing quality.
You have a line to change the width; simply add a line to change the height, based on your height variable. You can figure out what the height should be by dividing the new width by the old width. Basically, that is the multiple of widths in the new width, which is equal to the multiple of heights in the new height. Therefore, if you multiply that number to the old height, you would get the new height.
Here is the equation you could use:
img_h_new = (img_w_new / img_w) * img_h;
And this is the function you could use with your width function:
$('.gallery_img').height(img_w_new);
http://blog.francois-becker.net/post/2012/08/16/HTMLCSS-container-of-a-maximized-image
you can done it by css ,just apply this css to your image element
.img { /* image*/
position: absolute;
top: 10px;
right: 85px;
bottom: 10px;
left: 85px;
width: calc( 100% - 170px); /* 170 = marging left + right*/
height: calc(100% - 20px); /* 20px = marging top + bottomt*/
background-size: cover;
box-sizing: border-box;
padding: 0px;
}
body { /* container*/
margin: 0px;
padding: 0px;
height: 100%
width:100%;
overflow:hidden;
}
<html>
<body>
<img class="img" src="http://kingofwallpapers.com/picture/picture-004.jpg" > </img>
</body>
</html>

Scale a div to fit in window but preserve aspect ratio

How can I scale a div to fit inside the browser view port but preserve the aspect ratio of the div. How can I do this using CSS and/or JQuery?
Thanks!
You don't need javascript for this. You can use pure CSS.
A padding-top percentage is interpreted relative to the containing block width. Combine it with position: absolute on a child element, and you can put pretty much anything in a box that retains its aspect ratio.
HTML:
<div class="aspectwrapper">
<div class="content">
</div>
</div>
CSS:
.aspectwrapper {
display: inline-block; /* shrink to fit */
width: 100%; /* whatever width you like */
position: relative; /* so .content can use position: absolute */
}
.aspectwrapper::after {
padding-top: 56.25%; /* percentage of containing block _width_ */
display: block;
content: '';
}
.content {
position: absolute;
top: 0; bottom: 0; right: 0; left: 0; /* follow the parent's edges */
outline: thin dashed green; /* just so you can see the box */
}
The display: inline-block leaves a little extra space below the bottom edge of the .aspectwrapper box, so another element below it won't run flush against it. Using display: block will get rid of it.
Thanks to this post for the tip!
Another approach relies on the fact that browsers respect an image's aspect ratio when you resize only its width or height. (I'll let google generate a 16x9 transparent image for demonstration purposes, but in practice you would use your own static image.)
HTML:
<div class="aspectwrapper">
<img class="aspectspacer" src="http://chart.googleapis.com/chart?cht=p3&chs=160x90" />
<div class="content">
</div>
</div>
CSS:
.aspectwrapper {
width: 100%;
position: relative;
}
.aspectspacer {
width: 100%; /* let the enlarged image height push .aspectwrapper's bottom edge */
}
.content {
position: absolute;
top: 0; bottom: 0; right: 0; left: 0;
outline: thin dashed green;
}
Thanks to Geoff for the tip on how to structure the math and logic. Here's my jQuery implementation, which I'm using to size a lightbox so it fills the window:
var height = originalHeight;
var width = originalWidth;
aspect = width / height;
if($(window).height() < $(window).width()) {
var resizedHeight = $(window).height();
var resizedWidth = resizedHeight * aspect;
}
else { // screen width is smaller than height (mobile, etc)
var resizedWidth = $(window).width();
var resizedHeight = resizedWidth / aspect;
}
This is working well for me right now across laptop and mobile screen sizes.
I have a different pure HTML/CSS approach which does not rely on padding or absolute positioning. Instead it uses em units and relies on the CSS min() function plus a little bit of math.
Imagine that we want a viewport div with 16:9 aspect ratio which always fits the browser window and is centered in the axis with excess space. Here's how we can accomplish that:
HTML
<body>
<div class="viewport">
<p>
This should be a 16:9 viewport that fits the window.
</p>
</div>
</body>
CSS
body {
width: 100vw;
height: 100vh;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
background-color: white;
font-size: min(1vw, 1.778vh);
}
div.viewport {
width: 100em;
height: 56.25em;
background-color: lightblue;
}
div.viewport > p {
font-size: 3em;
text-align: center;
}
You can experiment with this in a sample JSFiddle here.
The secret sauce is in the body font-size. It should be set to min(1vw, Avh), where A is the aspect ratio you want the div to have, i.e. width / height. In the example above we're using 1.778, which is approximately 16 / 9.
In CSS, em units are based on the font-size of the element, which is inherited from parent element if not explicitly set. For your viewport div, set the width to 100em (NOT rem) and the height to Iem, where I is the inverse of the aspect ratio expressed as a percentage, i.e. 100 / A or 100 * height / width. In the example above we're using 56.25, which is 100 * 9 / 16.
One bonus of this approach is that all of your nested elements may also use em units so that they always scale precisely with the size of the viewport. You can see this used on the p element in the example.
Note that as an alternative to the above, you may set the font-size on your html element and use rem units everywhere. CSS rem units are similar to em units but always relative to the root element's font-size.
Javascipt:
//Responsive Scaling
let outer = document.getElementById('outer'),
wrapper = document.getElementById('wrap'),
maxWidth = outer.clientWidth,
maxHeight = outer.clientHeight;
window.addEventListener("resize", resize);
resize();
function resize(){
let scale,
width = window.innerWidth,
height = window.innerHeight,
isMax = width >= maxWidth && height >= maxHeight;
scale = Math.min(width/maxWidth, height/maxHeight);
outer.style.transform = isMax?'':'scale(' + scale + ')';
wrapper.style.width = isMax?'':maxWidth * scale;
wrapper.style.height = isMax?'':maxHeight * scale;
}
HTML:
<div id="wrap">
<div id="outer">
{{ fixed content here }}
</div>
</div>
Styling:
/* Responsive Scaling */
#wrap {
position: relative;
width: 1024px;
height: 590px;
margin: 0 auto;
}
#outer {
position: relative;
width: 1024px;
height: 590px;
transform-origin: 0% 0%;
overflow: hidden;
}
This is possible with JQuery and a bit of maths.
Use JQuery to get the view ports width and height as well as the divs current dimensions.
$(document).width();
Calculate the divs current aspect ratio. eg width/height
You need a bit of logic to determine whether to set the width or height first, then use the initial ratio to calculate the other side.
jQuery has a plugin that grows an object until one of it's sides reaches a certain px-value. Coupling this will the viewport's height, you could expand any element to that size: jQuery MaxSide.

Categories

Resources