jQuery center multiple dynamic images in different sized containers - javascript

So I've found similar questions but none that answer all the questions I have and I know there must be a simple jQuery answer to this. I've got multiple images that are being dynamically placed in their own containing div that have overflow:hidden, they need to fill their containing divs and be centered(horizontally and vertically) also. The containing divs will be different sizes as well.
So in short:
multiple different sized images fill and center in containing div.
containing divs will be different sizes.
will be used multiple times on a page.
images fill box proportionally
Hopefully this image helps explain what I'm after.
Click here to view the image.
HTML I'm using but can be changed
<div class="imageHolder">
<div class="first SlideImage">
<img src="..." alt="..."/>
</div>
<div class="second SlideImage">
<img src="..." alt="..."/>
</div>
<div class="third SlideImage">
<img src="..." alt="..."/>
</div>
</div>
And the CSS
.imageHandler{
float:left;
width:764px;
height:70px;
margin:1px 0px 0px;
}
.imageHolder .SlideImage{
float:left;
position:relative;
overflow:hidden;
}
.imageHolder .SlideImage img{
position:absolute;
}
.imageHolder .first.SlideImage{
width:381px;
height:339px;
margin-right:1px;
}
.imageHolder .second.SlideImage{margin-bottom:1px;}
.imageHolder .second.SlideImage, .imageHolder .third.SlideImage {
width: 382px;
height: 169px;
}
Ask me anything if this doesn't make sense,
thanks in advance

Here's a JQuery alternative to my CSS solution:
JSFiddle: http://jsfiddle.net/yczPs/
$(".SlideImage").each(function () {
var container = $(this),
img = $(this).find("img"),
margin;
if (img.width() / container.width() < img.height() / container.height()) {
img.css("width", container.width());
margin = -(img.height() * img.width() / container.width() - container.height()) / 2;
img.css("margin-top", margin);
} else {
img.css("height", container.height());
margin = -(img.width() * img.height() / container.height() - container.width()) / 2;
img.css("margin-left", margin);
}
});
I just coded that on the fly and haven't done any extensive testing, but it seems to be working fine for the few test cases I threw at it. Let me know if it isn't working properly for you.

Here is a simplest solution I could come up with :)
Full working example on JSFiddle.
http://jsfiddle.net/L3HhX/1/
$(document).ready(function() {
$('.center-trigger').click(function() {
centerImageInTheContainers();
});
function centerImageInTheContainers() {
$('.container').each(function(i, v) {
var container = $(this);
var myImg = $(this).find('img');
myImg.css('top', calculatePosition(container.height(), myImg.height()));
myImg.css('left', calculatePosition(container.width(), myImg.width()));
});
}
function calculatePosition(containerSize, imageSize) {
return 0 - ((imageSize - containerSize) / 2);
}
});

If I understand correctly, this can be done with pure CSS, granted that you 1) are OK using background images instead of <img> elements, and 2) don't need to support IE8 and below.
JSFiddle: http://jsfiddle.net/6nKKX/
HTML:
<div class="imageHolder">
<div class="first SlideImage"></div>
<div class="second SlideImage"></div>
<div class="third SlideImage"></div>
</div>
CSS: (The parts relevant to the solution)
.imageHolder .SlideImage {
background-repeat: no-repeat;
background-position: center center;
background-size: cover;
}
.imageHolder .first.SlideImage {
background-image: url('...');
}
.imageHolder .second.SlideImage {
background-image: url('...');
}
etc.
Alternatively, you can set the background images inline in the HTML with <div class="first SlideImage" style="background-image: url('...');"></div>
Basically, background-size: cover; means scale the image until it covers the entire box (cropping whatever is outside of it), and background-position: center center; centers the image for you.

Related

jQuery/DOM does not update viewport after changing sizes

In a DIV I have inserted images that I always want to display in 60% width of the original size of the image file (so that the images are on the same scale). For this I use the following jQuery-Script:
var cont_slider_ori_width;
var cont_slider_ori_height;
$('.img-drawing').each(function(i) {
var img = $(this);
$("<img>").attr("src", $(img).attr("src")).load(function() {
cont_slider_ori_width = this.width; // to get the original width of the image-file
cont_slider_ori_height = this.height; // to get the original height of the image-file
});
img.width(cont_slider_ori_width * 0.6);
// alert($(this).attr('src')); // If I avtivate this alert command, the size-changes work as it should ...
});
The HTML-Markup:
<div class="cont-slider-item-img-wrapper">
<div class="cont-slider-item-drw">
<img class="img-drawing" src="image1.png" alt="" width="1042" height="412">
</div>
<div class="cont-slider-item-drw">
<img class="img-drawing" src="image2.png" alt="" width="1042" height="411">
</div>
</div>
SCSS:
.cont-slider-item-img-wrapper {
display: flex;
justify-content: center;
.cont-slider-item-drw {
img {
width: auto;
height: auto;
}
}
}
But unfortunately this does not work (the size is not changed). It's strange that when I activate the 'alert' command, the redraw for the respective elements works as expected after each confirmation of the alarm box.
What did I do wrong? Thanks in advance for any help!!
With the friendly help of Chris G (see comments above) I was able to solve the problem. This is the jQuery/Javascript code, which is working now:
var cont_slider_ori_width;
var cont_slider_ori_height;
$('.img-drawing').each(function(i) {
cont_slider_ori_width = $(this).get()[0].naturalWidth;
$(this).width(cont_slider_ori_width * 0.6);
});

Positioning Parallax Hover Layers

I'm teaching myself how to create a parallax hover image using 5 layers, which is working perfectly, and I am able to resize the layers alright, but I'm having trouble with the positioning.
When resized to 150vw/vh the layers spill over the bottom and right side. I've tried a few things but not sure if I'm putting the css properties in the right place. 100vh/vw positions in the center but is too small for my header.
Should I be positioning in #scene or .img? And whats best practice for this kind of thing?
Heres what I have so far anyway:
<div class="section--parallax">
<div id="scene">
<div data-depth="0.2">
<img src="resources/img/layer1.png">
</div>
<div data-depth="0.6">
<img src="resources/img/layer2.png">
</div>
<div data-depth="0.3">
<img src="resources/img/layer3.png">
</div>
<div data-depth="0.6">
<img src="resources/img/layer4.png">
</div>
<div data-depth="0.2">
<img src="resources/img/layer5.png">
</div>
</div>
</div>
CSS
header {
background-size: cover;
background-position: center;
height: 100vh;
background-attachment: fixed;
}
#scene {
}
.section--parallax img {
width: 150vw;
height: 150vh;
}
JS
var scene = document.getElementById('scene');
var parallaxInstance = new Parallax(scene);

Floating divs glitch on resize in Chrome and Edge

Does anyone know how to fix this problem. The only browser that works correctly is Firefox; in Chrome and Edge it doesn't work. When I resize the screen the box changes the position. Is there some solution?
Screenshot
HTML
<div class="box" style="background:#F00; height:200px;"></div>
<div class="box" style="background:#F0F; width:25%"></div>
<div class="box" style="background:#FF0; width:25%"></div>
<div class="box" style="background:#00F; width:25%"></div>
<div class="box" style="background:#55F; width:25%"></div>
CSS
.box {
width: 50%;
height: 100px;
float: left
}
JavaScript
$(window).resize(resize)
function resize() {
$(".box").each(function() {
$(this).height( $(this).width() * 0.5)
});
}
Here's the Codepen link:
http://codepen.io/Tufik/pen/rxyQmV
UPDATE---------
I modified the CodePen to show a more complex structure. The problem is when you resize the screen browser, the divs don't respect the correct position, some divs jump to the next line.
This is an old problem. I think it's because HTML is not pixel perfect. But I want to know if there is some easy solution different to use masonry.js or any plugins. Firefox work great, but Chrome or Edge not.
Problem: Unpredictable browser rounding of integers
Each browser calculates numbers differently. For widths and heights, the browser also rounds to the nearest integer for layout. So, the computed pixel-width of each floated box may have a different initial value after converting from percentage and filling out the container. Calculating on these numbers can lead to unpredictable results.
Here is an example of how the values are being calculated in your setup (resize the browser and watch the values change):
function resize() {
$(".box").each(function() {
var height = $(this).width() * 0.5;
$(this)
.height(height)
.html("<code>height: " + $(this).height() + "px (rounded from " + height + ")</code>");
});
}
$(window).resize(resize);
resize();
.box { float: left; }
.box-large {
width: 50%;
height: 200px;
}
.box-small {
width: 25%;
height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="box box-large" style="background:#F00;"></div>
<div class="box box-small" style="background:#F0F;"></div>
<div class="box box-small" style="background:#FF0;"></div>
<div class="box box-small" style="background:#00F;"></div>
<div class="box box-small" style="background:#55F;"></div>
Solution: uniformly apply your own rounded integer
One way to solve this is to create your own new height value, round it to a whole integer and apply it uniformly to each box instead of applying the decimal value and relying on the browser to do the rounding. The best way to do this is to calculate the new height value from one box and apply it to the others, instead of doing a calculation on each.
Because you have two different sized boxes, we do this calculation twice: once for the large box and once for the small box. The calculated large height value gets applied to all large boxes (only one in this case) and the calculated small height value gets applied to all small boxes.
Example:
function resize() {
var $larges = $('.box-large'), // Get all large boxes
$lgFirst = $($larges.get(0)), // Get first large box
lgHeight = Math.floor( // Round down before the browser screws it up
$lgFirst.width() / 2 // Calculate new height
),
$smalls = $('.box-small'), // Get all small boxes
$smFirst = $($smalls.get(0)), // Get first small box
smHeight = Math.floor( // Round down before the browser screws it up
$smFirst.width() / 2 // Calculate new height
),
// Function returns a function to keep things DRY
setHeight = function(height) {
// This function is returned to the .each() call later
return function () {
$(this)
.height(height)
.html("<code>height: " + height + "px</code>");
}
};
// Set height of all large boxes to new large height
$larges.each(setHeight(lgHeight));
// Set height of all small boxes to new small height
$smalls.each(setHeight(smHeight));
}
$(window).resize(resize);
resize();
.box { float: left; }
.box-large {
width: 50%;
height: 200px;
}
.box-small {
width: 25%;
height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="box box-large" style="background:#F00;"></div>
<div class="box box-small" style="background:#F0F;"></div>
<div class="box box-small" style="background:#FF0;"></div>
<div class="box box-small" style="background:#00F;"></div>
<div class="box box-small" style="background:#55F;"></div>
I'm not sure whether this answers your question, but I think css flex box is what you are looking for. you don't need javascript to do this.
The below code will align your divs all in one line and also provides responsiveness using flex box(Not exact layout you are looking but im sure you will be able to figure it out)
For more info please refer this article
<!DOCTYPE html>
<html>
<head>
<style>
.container {
display: flex;
flex-direction: row;
height: 200px;
flex-grow: 1
}
.column {
display: flex;
flex-direction: column;
flex-grow: 1
}
.big {
flex-grow: 1;
}
</style>
</head>
<body>
<div class="container">
<div class="column">
<div class="big" style="background:#F00;">
1
</div>
</div>
<div class="column">
<div class="big" style="background:#F0F;">
2
</div>
<div class="big" style="background:#00F;">
3
</div>
</div>
<div class="column">
<div class="big " style="background:#FF0; ">
4
</div>
<div class="big" style="background:#55F;">
5
</div>
</div>
</div>
</body>
</html>

JavaScript - Make an image turn white on click

I've got a bunch of images, on click I want the images to turn white emulating some kind of fade effect. So you click it and for 1 second it fades from the original image to just white. I also need it to turn back to the original image when the user clicks something else.
Is this possible with JavaScript? - If so what should I be looking at (I'm really bad with graphics).
I've had a go at trying this with opacity but I don't want the background to be visible behind the image
Psuedo-element Solution
You could use a wrapper with a pseudo-element to overlay what you're looking for -- and the animations are handled by a toggled CSS class (which is ideal for performance).
CodePen Demonstration
HTML
<div class="whiteclicker">
<img src="http://lorempixel.com/400/200" alt=""/>
</div>
SCSS
#import "compass/css3/transition";
body { background: gainsboro; text-align: center; }
.whiteclicker {
display: inline-block;
position: relative;
&::after {
content: "";
display: block;
position: absolute;
top:0; left:0; right:0; bottom:0;
background: white;
opacity: 0;
#include transition(opacity 1s ease);
}
&.active::after {
opacity: 1;
}
}
JS
$('.whiteclicker').click(function(){
$(this).toggleClass('active');
});
To ameliorate the Spencer Wieczorek solution (the way two seems to be the best solution on my opinion) :
What about creating the white div on the fly (and fade it in and out) instead of put it in the html code ?
See the fiddle.
$("#myImage").click(function(){
$(this)
.parent().css({position:'relative'}).end()
.after($('<div>')
.hide()
.css({position:'absolute'
, top: $(this).position().top
, left: $(this).position().left
, width: $(this).width()
, height: $(this).height()
, background: '#FFF'
})
.fadeIn('fast')
.on({
click : function(e){
$(this).fadeOut('fast', function(){ $(this).remove();});
}
})
);
});
Then, you don't have anything to add to the html code or in the css styles, Jquery does everything.
#Spencer Wieczorek : I did my own answer, because I did not agree with your way of designing the css style (the fixed position is really not good, especially if the page is scrolled for example...). Mine is more ... standalone-y ;)
You might want to try having two images stacked on each other.
See this:
<script type="text/javascript">
var image1 = '<img class="images" src="Image 1" onClick="switch();" />';
var image2 = '<img class="images" src="Image 2" onClick="switch();" />';
var currentImage = 1;
function switch(){
if(currentImage==1){
currentImage++;
document.getElementById("image").innerHTML = image2;
}
if(currentImage==2){
currentImage--;
document.getElementById("image").innerHTML = image1;
}
}
</script>
<style>
.images{ position:fixed; top: 0; left: 0; }
</style>
<img class="images" src="Black image" />
<div id="image"><img class="images" src="Image 1" onClick="switch();" /></div>
For the fade I'm just gonna see how you could do it.
EDIT:
<script type="text/javascript">
var fadecount = 100;
function fade() {
document.getElementById("imageToFade").style.opacity = fadecount;
fadecount--;
if(fadecount==0){
clearTimeout(fade);
}
}
function start_fade(){
var fade = setTimeout(fade(), 10);
}
</script>
With Base 64 you can just have the binary version of the picture and then an all white picture and based on the .click you reassign the src to the white base64...
document.getElementById("img").src = "data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAAUA
AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
9TXL0Y4OHwAAAABJRU5ErkJggg=="
just change to the all white version after the click, technically js driven from click event, and doesn't involve two different elements existing just at different layers...

Center image on jQuery Slider in HTML

I have an jQuery Content Slider. But i have an problem, where tall images is stretch. Isn't it possible to center the image. Some says that i need to set the overflow to hidden. But it doesn't make any differences.
Best regard Morten Starck
The html code:
<ul class="bxslider">
<li>
<img id="propImageSliderLarge" src="http://billeder.edc.dk/edcmedia/2012/04-April/04/4fac343a-5d4b-4aab-8205-f57f165bc484_Size687x458.jpg"/></li>
<li>
<img id="propImageSliderLarge" src="http://billeder.edc.dk/edcmedia/2012/04-April/04/7bdfb0cc-47ec-4afa-9fc7-aa2cbb9d43a0_Size687x458.jpg"/></li>
<li>
<img id="propImageSliderLarge" src="http://billeder.edc.dk/edcmedia/2012/04-April/04/aad1d457-285d-42e3-8e68-e243bd2988d4_Size687x458.jpg"/></li>
<li>
<img id="propImageSliderLarge" src="http://billeder.edc.dk/edcmedia/2012/04-April/04/768fda69-af61-4322-a60b-012040d78384_Size687x458.jpg"/></li>
<li>
<img id="propImageSliderLarge" onload="FixImages(true)" src="http://www.blog.designsquish.com/images/uploads/victorian-flatbush-old-hous_thumb.jpg" /></li>
And the Javascript:
<script type="text/javascript">
$('.bxslider').bxSlider({
pagerCustom: '#bx-pager'
});
</script>
and the CSS code:
#propImageSliderLarge {
width: 530px;
height: 400px;
overflow: hidden;
position: relative;
}
There're two things you're doing wrong here. First, you're using the same ID for multiple elements, this isn't valid. I think you intended to use CSS classes. Second, you're setting the width and height attributes of the IMG tag, when in fact you should set these attributes on the container (in this case the LI). Try the following:
Change your markup to this
<li class="propImageSliderLarge">
<img src="http://billeder.edc.dk/edcmedia/2012/04-April/04/4fac343a-5d4b-4aab-8205-f57f165bc484_Size687x458.jpg"/>
</li>
Change your CSS to this
.propImageSliderLarge {
width: 530px;
height: 400px;
overflow: hidden;
position: relative;
text-align: center; /* this will centre your image in the LI */
}
Update the image dimension if larger than LI container
This script assumes variables set for containerWidth and containerHeight so just set these to whatever your LI container size is and it'll resize the images to the max constraints of the container so you can see the entire image.
function resizeImage(img) {
var imgWidth = parseInt($(img).width());
var imgHeight = parseInt($(img).height());
if (imgWidth > containerWidth || imgHeight > containerHeight) {
$(img).width(containerWidth);
$(img).height(containerHeight);
}
}​
First, change the attribute id to attribute class. Id means Identifier, and as the name goes, two things cannot have same identifier. To center the images, give an id to ul tag and add following css:
text-align: center;
Try this...not sure if it'll work.
you can run the slider in onload and check it out.
<script type="text/javascript">
$(document).ready(function(){
$('.bxslider').bxSlider({
mode: 'fade',
captions: true
});
});
</script>
otherwise, you can use anyone suitable slider in http://bxslider.com/examples

Categories

Resources