I am working on an image slider that scales an image. Of course this works fine in all browsers included IE9+ but for IE7/8 it seems to scale the image to fit the containers height and not the width...
I am using the following CSS code to scale the images.
-ms-filter: "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../files/slideshow/3.jpg', sizingMethod='scale')"
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../files/slideshow/3.jpg', sizingMethod='scale');
I was curious if anyone knew of a way to make this scale by the width of the container instead of the height using either CSS or JavaScript?
You can view it here http://kearsargefire.org/
Check it...
http://css-tricks.com/perfect-full-page-background-image/
HTML
<img src="images/bg.jpg" id="bg" alt="">
CSS
#bg { position: fixed; top: 0; left: 0; }
.bgwidth { width: 100%; }
.bgheight { height: 100%; }
SCRIPT
$(window).load(function() {
var theWindow = $(window),
$bg = $("#bg"),
aspectRatio = $bg.width() / $bg.height();
function resizeBg() {
if ( (theWindow.width() / theWindow.height()) < aspectRatio ) {
$bg
.removeClass()
.addClass('bgheight');
} else {
$bg
.removeClass()
.addClass('bgwidth');
}
}
theWindow.resize(resizeBg).trigger("resize");
});
Adjust the code for instead of "$(window)" to be your container.
Related
I am trying to create letterboxes for video thumbnails in css. Thumbnails can be any size but I want them to fit within a box with a fixed aspect ratio of 16:9. This is easy to accomplish if I use the background-image properties. See the example below:
.container {
background-color: gray;
position: relative;
width: 100%;
padding-top: 56.25%;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
}
.container1 {
background-image: url("https://bulma.io/images/placeholders/640x480.png");
}
.container2 {
background-image: url("https://bulma.io/images/placeholders/720x240.png");
}
<div class="container container1">
</div>
<br/>
<div class="container container2">
</div>
However, using background-image introduces a few problems. I only want the background of .container to be gray while the thumbnail is loading, once it has loaded I want it to be black. I also want to replace the thumbnail url with a default thumbnail url if for some reason the thumbnail fails to load. I cannot think of a way to do this without being able to use the onload and onerror events of an actual image element.
Fortunately, since in my actual code I am fetching the thumbnail urls dynamically I can also return the width and height of a thumbnail so I know it before I try to load it. However, I cannot figure out how to convert the width and height of the thumbnail into the correct percent it needs to be to cover the center of the box the same way the first example does using background-image. See the example below:
let c1ThumbnailWidth = 640;
let c1ThumbnailHeight = 480;
let c2ThumbnailWidth = 720;
let c2ThumbnailHeight = 240;
$( document ).ready(function() {
$('.container1 img').css('left', 100 * (1 - (9 / 16) * (c1ThumbnailWidth / c1ThumbnailHeight)) / 2 + '%');
$('.container2 img').css('left', 100 * (1 - (9 / 16) * (c2ThumbnailWidth / c2ThumbnailHeight)) / 2 + '%');
$('.container img').one('load', function() {
$(this).parent().css('background-color', '#000');
});
$('.container img').on('error', function () {
$(this).attr('src', 'default.jpg');
});
});
.container {
background-color: gray;
position: relative;
width: 100%;
padding-top: 56.25%;
}
.container img {
position: absolute;
top: 0;
height: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container container1">
<img src="https://bulma.io/images/placeholders/640x480.png">
</div>
<br/>
<div class="container container2">
<img src="https://bulma.io/images/placeholders/720x240.png">
</div>
How can I make the image element mimic the behavior of a background-image set to cover or alternatively how can I tell when a background-image has loaded or failed to load and adjust it accordingly?
Have you tried using CSS object-fit on the image element?
https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit
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
What I'm trying to do is to center and resize an image that's inside of a viewport (or a parent element), without stretching it.
To make a very long story short, I want the images to keep their aspect ratio and be resized so that they cover up the viewport completely.
This is my HTML layout:
<div class="media-area" data-size="b" data-type="2">
<ul class="content-slider">
<li class="cs-item">
<img class="cs-background" src="assets/img/backgrounds/top-slider-1.jpg" alt="slider-element">
</li>
<li class="cs-item">
<img class="cs-background" src="assets/img/backgrounds/top-slider-2.jpg" alt="slider-element">
</li>
<li class="cs-item">
<img class="cs-background" src="assets/img/backgrounds/top-slider-3.jpg" alt="slider-element">
</li>
</ul>
</div>
This is my CSS:
.media-area {
width: 100%;
height: 100%; /* Standard height */
position: relative;
overflow: hidden;
}
.media-area .content-slider {
position: relative;
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
.media-area .content-slider .cs-item {
position: relative;
display: block;
float: left;
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
.media-area .content-slider .cs-item img {
display: block;
}
.media-area .content-slider .cs-background {
-webkit-transition: all .1s ease-in-out;
-moz-transition: all .1s ease-in-out;
-o-transition: all .1s ease-in-out;
transition: all .1s ease-in-out;
}
And this is my JS:
function mediazone() {
var defaults = {
elem: ".media-area",
elemWrap: ".media-area .content-slider",
elemSlide: ".media-area .content-slider .cs-item",
vh: $(window).height(),
vw: $(window).width()
};
$(defaults.elemSlide).find(".cs-background").each(function () {
var bkndImgW = $(this).width(); // Current image width
var bkndImgH = $(this).height(); // Current image height
var mediaViewPortW = $(this).parents(defaults.elem).width(); // Current media viewport width
var mediaViewPortH = $(this).parents(defaults.elem).height(); // Current media viewport height
// Used for viewport aspect ratio
var viewportratio = Math.round((mediaViewPortW / mediaViewPortH) * 100000 ) / 100000;
// Used for image aspect ratio
var imageratio = Math.round((bkndImgW / bkndImgH) * 100000 ) / 100000;
// Negative margins for when the height is larger than the width
var bkndImgPosW = ((bkndImgW - mediaViewPortW) / 2)*-1;
// Negative margins for when the width is larger than the height
var bkndImgPosH = ((bkndImgH - mediaViewPortH) / 2)*-1;
bkndImgPosW = Math.min(0, Math.max(bkndImgPosW, bkndImgPosW));
bkndImgPosH = Math.min(0, Math.max(bkndImgPosH, bkndImgPosH));
if (viewportratio > imageratio) {
$(this).removeAttr("style");
$(this).css("min-height", "100%");
$(this).css("width", "100%");
$(this).css("margin", bkndImgPosH+"px 0px");
} else if (viewportratio < imageratio){
$(this).removeAttr("style");
$(this).css("height", "100%");
$(this).css("min-width", "100%");
$(this).css("margin", "0px "+bkndImgPosW+"px");
} else if (viewportratio == imageratio) {
$(this).removeAttr("style");
}
});
}
The function is initialized here:
$(document).ready(function () {
mediazone();
});
$(window).resize(function () {
mediazone();
console.log('window resize event');
});
The problem I'm faced with right now is that when the page loads, the image is half-way out of the viewport, but when I resize the browser window, it fits perfectly.
Another problem I can't really find a way around right now is the one with the two aspect ratio's being equal ( i couldn't find a way to make the image cover the screen without having to deal with some white spaces). This makes the image flicker when the aforementioned scenario is under way.
It is important that I use the IMG tag in the DOM, otherwise maybe there would have been a way to make use of the "background-image" property in CSS.
Can anyone point out what I'm missing/ doing wrong/ I should delete?
Kind regards,
Alex
* Later Edit *
This is what I have right now:
http://jsfiddle.net/LexEckhart/Z5cjx/
After resizing, it seems to work fine and maintain the image balanced in the middle but when the page loads, the items are not positioned properly.
Since the OP specifically said he didn't want to use background-image as the image must be present in the DOM as an image, here's a jsfiddle showing a solution. I've dimmed the images using opacity to show the borders of the li's beneath it. I think the OP was overthinking the problem a bit. Anyway, hope this helps.
jsfiddle
if (viewportratio > imageratio) {
$(this).removeAttr("style");
$(this).css("width", "100%");
$(this).css("margin", bkndImgPosH+"px 0px");
} else if (viewportratio < imageratio){
$(this).removeAttr("style");
$(this).css("height", "100%");
$(this).css("margin", "0px "+bkndImgPosW+"px");
} else if (viewportratio == imageratio) {
$(this).removeAttr("style");
}
Keep in mind that images retain their aspect ratio if you only provide one attribute / property (width OR height). That's the key to the solution.
EDIT: Updated fiddle. I played around with the math logic until it worked for the images I had, replacing your images which I used before. The math logic below the first section is possibly wrong, so it'll need further testing, but this works for what I had.
You can give try for
"background-size" and "align-items" properties from css3.
set "background-size:100% 100%;";
it will cover (parent window);
For aligning contents in center you could use "align-items:center".
You can take advantage of the fact that percentage padding is always figured from the element's width. You can therefore use vertical padding with a percentage width to enforce an aspect ratio.
<div id=img></div>
// ... then in CSS:
#img {
background: url("http://placekitten.com/1280/720") no-repeat center center;
background-size: cover;
height: 0;
padding-bottom: 56.25%; /* 9:16, or 720/1280 */
}
Here is a jsfiddle to demonstrate. If you don't know the aspect ratio in advance, you can of course compute it and set the "padding-bottom" dynamically via JavaScript.
Thanks are due to the inimitable Dave Rupert for this technique.
edit ah, the <img> tag in that ending paragraph was hidden. You can employ a variation of this trick if you really need an <img> tag:
<div class=image-centerer>
<img src='http://whatever.com/your/image.png'>
</div>
// ... then in CSS:
.image-centerer {
position: relative;
height: 0;
padding-bottom: 56.25%;
}
.image-centerer img {
position: absolute;
display: block;
height: 100%;
}
Fiddle demo, and here is one demonstrating the handling of arbitrarily-proportioned images.
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>
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.