I have a 240x240px div which contains a fading slideshow of images differing in sizes. I have each image set to a height: 240px with the width being automatic in proportion to its height. Some images are taller than they are wide (in proportion) so I center them inside the div using position: relative; margin: 0 auto This works well except for images which overflow the 240px div. How could I go about centering images inside the div which overflow? I tried this (jQuery) but it doesn't work for some reason I'm sure I can't figure out:
if( $("div img").width() > 240 ) {
$(this).css("margin-left", rv);
var rv = -1 * ($(this).width() / 4) + "px";
}
The logic being, if the image expands the div in width, then shift it to the left by rvpx, rv being 1/4 of the image's width (as 1/2 would clip the image in half on the left, so 1/2 of 1/2 effectually centering it?) My first guess would be that I can't reference $(this) as I am trying to, though I have no idea.
I know I could go and add individual inline CSS styles but that's messy and mundane. I'd rather have a script which can automatically calculate the center of the image then move it accordingly. Any ideas?
I'd recommend something like this:
div.center-img { background:url('/path/img.jpg') center center no-repeat; }
But your question would be answered with something like this:
$('div img').each(function() {
if( this.width > 240 )
$(this).css("margin-left", ((this.width - 240) / -2) + "px");
});
You can use CSS only:
LIVE DEMO
.imgHolder{
border:1px solid #000;
width:240px;
height:240px;
line-height:240px; /* same as element height */
font-size:0; /* to perfectly vertical align middle the image */
text-align:center; /* to horizontally align middle the image */
}
.imgHolder > img{
max-width:100%;
max-height:100%;
vertical-align:middle;
}
Iterate over the images and when they have loaded get the image width and the parent element width, compare the width, and if the image is wider than the parent get half of the difference and subtract that from the left margin to center the image horizontally.
$("div.centered img").each(function(_,el) {
var img = new Image(),
parent = $(el).parent();
img.onload = function() {
var ma = this.width - $(parent).width();
if ( ma > 0 ) {
$(el).css('margin-left', ((ma/2) * -1));
}
}
img.src = this.src;
if (img.complete) img.onload();
});
FIDDLE
Related
I have some code that allows me to change the img src when I've scrolled from top < 120 px. But I need to change the image to another one when the browser is resized too.
So I should get, 1 image when I scroll down 120 px, 1 image if I already scrolled down 120px but I reduced size of browser to 850 pixels,
1 image if I'm at full top of browser, and another image if I reduce size of browser.
So far I can only change img src if I scroll 120px down, but how can I solve the browser size at the same time?
$(window).on('scroll', function () {
var scrollTop = $(window).scrollTop();
if (scrollTop > 120) {
$('#logo').attr('src', 'http://www.kubographics.com/adiacens/images/logo1-black.svg');
$('#logo').css('margin-top', '10px');
}
else {
('#logo').attr('src', '');
$('#logo').css('margin-top', '0px');
}
});
Thanks for your help!
To change the img use css media query
#logo {
background: url("http://www.kubographics.com/adiacens/images/logo1-black.svg")
}
#media (max-width: 850px) {
background: url("http://www.kubographics.com/adiacens/images/logo2-black.svg")
}
I'm using bxslider to have a carousel of images. The thing is though, the images it receives to display are of somewhat unpredictable sizes. The container size is 243x243. And we know that no image will have a side smaller than 243. So...I'd like to center the image in the container. And either zoom in until the shorter of the two dimensions (L vs W) fills the container at 243, and the longer dimension overflow is hidden.
For the images I'm working with, doing this will be perfect for getting the important details of the picture in the frame.
But I'm having trouble...
I've tried the following to center the picture in the frame:
jQuery(".bx-container").each(function() {
var img_w = jQuery(this).children("img").width();
var img_h = jQuery(this).children("img").height();
var pos_top = (img_h - containerHeight) / 2;
var pos_left = (img_w - containerWidth) / 2;
var pos_top = (243 - img_h) / 2;
var pos_left = (243 - img_w) / 2;
jQuery(this).children("img").css({
'top' : pos_top + 'px',
'left' : pos_left + 'px'
});
});
And I've tried this to position not square images into the frame:
jQuery(".bx-container").each(function(){
var refRatio = 1;
var imgH = jQuery(this).children("img").height();
var imgW = jQuery(this).children("img").width();
if ( (imgW/imgH) < refRatio ) {
jQuery(this).addClass("bx-portrait");
} else {
jQuery(this).addClass("bx-landscape");
}
});
});
I've messed with both scripts and the css but I just can't seem to get it work. It either centers but doesn't resize right. Or resizes but centers wrong. Or does both wrong.
Here's the jsfiddle: http://jsfiddle.net/vgJ9X/298/
Could someone help me out?
Thanks!
EDIT:
New jsfiddle...the portrait ones work right. The landscape images still squish. :(
http://jsfiddle.net/vgJ9X/307/
EDIT:
I THINK it has something to do with relatively positioned elements not being allowed to overlap. Trying to find a fix. If anyone knows, edit the last fiddle I posted.
jQuery(".bx-container img").each(function () {
var w = jQuery(this).width();
var h = jQuery(this).height();
if (w > h) $(this).addClass('bx-landscape');
else $(this).addClass('bx-portrait');
});
Check this Updated JSFiddle
Update
jQuery(".bx-container img").each(function () {
var w = jQuery(this).width();
var h = jQuery(this).height();
if (w > h){
$(this).addClass('bx-landscape');
var trans= -243/2;
$(this).css('-webkit-transform','translateZ('+trans+'px)');
}
else if(h > w){
$(this).addClass('bx-portrait');
var trans= -243/2;
$(this).css('-webkit-transform','translateY('+trans+'px)');
}
});
check this JSFiddle
Update of Update
Found the issue with landscape, the plugin is setting max-width:100%; overriding it with max-width:none; fixes the issue...
Update Of Updated Fiddle
Try this:
img{
position:relative;
height:100%;
width:300px;
}
Simple an clean.
Demo: http://jsfiddle.net/vgJ9X/302/
I did a couple things to your jsfiddle.
First I changed the order of your resize and center functions, so the resize comes first. This way, the smaller images get resized, then centered. I also uncommented the first portion of your code.
You also had a couple of errors in your css. There was an extra closing bracket after img style declaration. Your .bx-portrait img and .bx-landscape img declarations were set to 100%px;.
Update:
Change the css in your two .bx classes to:
.bx-portrait img {
height: 100%;
width: auto;
}
.bx-landscape img {
height: auto;
width: 100%;
}
And add a clearfix to your ul:
.bxslider:after {
content: '';
clear: both;
display: table;
padding: 0;
margin: 0;
}
The height is clipping because .bx-viewport has a set height of 243px but also has a 5px border, which makes the actual internal height 233px. You'll need to make the height 253px to account for the 10px of border. This is why they don't look centered vertically.
DEMO
Why don't you just use background images instead and center them. Here is a demo from your original code
http://jsfiddle.net/8y8df/
If you want to show the full size image, just remove the background-size:contain; from the css.
I have a scrollable div that I zoom/scale the content of using css3 transform. It works fine if I'm zooming in (scaling up the content) but I've noticed that when scaling down, below 100%, the amount that you can scroll vertically of the container div does not reduce.
I've made a jsfiddle to illustrate this
CSS:
.scrollable
{
height: 250px;
width: 250px;
overflow: auto;
background-color: green;
}
.content
{
height :500px;
width : 500px;
background: linear-gradient(red, blue);
...
}
JS/jquery:
function scaleContent(newScale){
var $content = $("#content");
var scaleString = "scale("+newScale+")";
//var height = (newScale<1)? $("#content").height()/scale*newScale : originalHeight;
$content.css({
'-webkit-transform' : scaleString,
'-webkit-transform-origin' : '0 0',
...
//'height' : height +'px'
});
scale=newScale;
}
The actual scaling and the amount that you can scroll horizontally works perfectly, but the amount you can scroll vertically doesn't change below 100%.
Note: the amount you can scroll vertically appears to change on the first scaledown/zoomout, but this is simply because the horizontal scrollbar is removed.
I tried to manually change the height of the content, but this just messed with the content dimensions (duh). That's the commented-out height code.
The ellipses are where I've repeated things for other browsers.
I've managed to come up with one solution, though it's probably not the best. I introduced another div around the content, which I call the view wrapper. I set its overflow to "hidden" and manually set its width and height to match what the scaled content should be.
CSS:
.viewwrapper{
height :500px;
width : 500px;
overflow: hidden
}
JS:
function scaleContent(newScale){
var $content = $("#content");
var scaleString = "scale("+newScale+")";
var $viewwrapper = $("#viewwrapper");
var height = $content.height()/newScale;
var width = $content.width()/newScale;
$viewwrapper.height(height);
$viewwrapper.width(width);
$content.css({
'-webkit-transform' : scaleString,
'-webkit-transform-origin' : '0 0',
...
});
}
JS Fiddle
Update:
This won't work if you're using jQuery 3.0 or 3.1. The read behaviour of the height and width functions has changed, so they return the scaled values. To fix the above code for those versions you can just say.
function scaleContent(newScale){
var $content = $("#content");
var scaleString = "scale("+newScale+")";
var $viewwrapper = $("#viewwrapper");
$viewwrapper.height($content.height());
$viewwrapper.width($content.width());
$content.css({
'-webkit-transform' : scaleString,
'-webkit-transform-origin' : '0 0',
...
});
}
JSFiddle using jQuery 3.0
However this probably won't make it into future versions of jQuery.
Update 2:
You might see unnecessary scrollbars in Chrome when you zoom out of the content. This is down to a Chrome bug.
you're applying transformations to your #content div, but the outside div, #scrollable has also a fixed height and is not reducing. You have to apply transformations to it too.
Because if you're zooming in, the outside div adapts to the inside content, whereas if you're reducing it does not.
I need a <img> to have the smallest possible size without leaving any blank spaces inside a div and it needs to be centralized horizontally and vertically. The size of the image is variable.
So here is an example so you can understand it better:
http://jsfiddle.net/q2c9D/
More info: much like Mikel Ward did, I need the images to fill up the div, so that the background of it is not visible. I made the div background black so it was easier to tell that it is not filling up the div. But I need the images to be centered and to be the smallest size possible without being distorted while filling up the div.
Here is my go
I would set the width to 100%, and remove the height property altogether. This will prevent the image from being distorted
img{
width: 100%;
}
To center the element, I would use this plugin. It makes you do no work, other than to call the function
$("img").center()
Try adding min-width: 100% to the img. Here's an example. It may stretch the picture a little but at the size it is, may not be too noticeable. :)
This will center the image on the page:
img{
margin: 0 auto;
position: relative;
display: block;
}
Just wrap the images in a <div> to position them somewhere on the page.
The way i do it is set the width or height, but only 1 as 100%.
<img width="100%" src=""/>
So I was able to get it working the way I wanted using jQuery. With the following code:
function centerimg(){
$('img').each(function(){
var imgwidth = $(this).width();
var imgheight = $(this).height();
if (imgwidth > imgheight) {
$(this).css({
"height": "100%",
"width": "auto"
});
imgwidth = $(this).width();
$(this).css("margin-left", -.5 * imgwidth + 50 + "px");
} else if (imgheight > imgwidth) {
$(this).css({
"width": "100%",
"height": "auto"
});
imgheight = $(this).height();
$(this).css("margin-top", -.5 * imgheight + 50 + "px");
} else {
$(this).css({
"height": "100%",
"width": "100%"
})
}
})
};
window.onload = centerimg;<code>
The code gets the width and height of the image, so if the image is wider or taller it will properly set the smaller dimension to 100% and the larger one to auto. After that it gets the value of that last one again (since it was re sized with auto) and centers it. Also, if the image is a square it just sets both to 100%.
This way the image will ALWAYS fill up the div and be centered.
Thanks all. Hope this code helps others.
Is there a way to reliably tell a browser's viewport width that includes the scrollbar, but not the rest of browser window)?
None of the properties listed here tell me the width of the screen INCLUDING the scrollbar (if present)
I figured out how to accurately get the viewport width WITH the scrollbar using some code from: http://andylangton.co.uk/blog/development/get-viewport-size-width-and-height-javascript
Put this inside your $(document).ready(function()
$(document).ready(function(){
$(window).on("resize", function(){
function viewport() {
var e = window, a = 'inner';
if (!('innerWidth' in window )) {
a = 'client';
e = document.documentElement || document.body;
}
return { width : e[ a+'Width' ] , height : e[ a+'Height' ] };
}
});
// Get the correct window sizes with these declarations
windowHeight = viewport().height;
windowWidth = viewport().width;
});
What it Does:
When your page is 'ready' or is resized, the function calculates the correct window height and width (including scrollbar).
I assume you want to know the viewport width with scrollbar included, because the screen it self does not have a scrollbar. In fact the Screen width and heigth will be the computer screen resolution itself, so I'm not sure what you mean with screen width with the scroll bar.
The viewport however, the area where only the page (and scroll bars) is presented to the user, meaning, no browser menus, no bookmarks or whatever, only the page rendered, is where such scroll bar may be present.
Assuming you want that, you can measure the client browser viewport size while taking into account the size of the scroll bars this way.
First don't forget to set you body tag to be 100% width and height just to make sure the measurement is accurate.
body {
width: 100%;
// if you wish to also measure the height don't forget to also set it to 100% just like this one.
}
Afterwards you can measure the width at will.
Sample
// First you forcibly request the scroll bars to be shown regardless if you they will be needed or not.
$('body').css('overflow', 'scroll');
// Viewport width with scroll bar.
var widthWithScrollBars = $(window).width();
// Now if you wish to know how many pixels the scroll bar actually has
// Set the overflow css property to forcibly hide the scroll bar.
$('body').css('overflow', 'hidden');
// Viewport width without scroll bar.
var widthNoScrollBars = $(window).width();
// Scroll bar size for this particular client browser
var scrollbarWidth = widthWithScrollBars - widthNoScrollBars;
// Set the overflow css property back to whatever value it had before running this code. (default is auto)
$('body').css('overflow', 'auto');
Hope it helps.
As long as body is 100%, document.body.scrollWidth will work.
Demo: http://jsfiddle.net/ThinkingStiff/5j3bY/
HTML:
<div id="widths"></div>
CSS:
body, html
{
margin: 0;
padding: 0;
width: 100%;
}
div
{
height: 1500px;
}
Script:
var widths = 'viewport width (body.scrollWidth): '
+ document.body.scrollWidth + '<br />'
+ 'window.innerWidth: ' + window.innerWidth + '<br />';
document.getElementById( 'widths' ).innerHTML = widths;
I put a tall div in the demo to force a scroll bar.
Currently the new vw and vh css3 properties will show full size including scrollbar.
body {
width:100vw;
height:100vh;
}
There is some discussion online if this is a bug or not.
there is nothing after scrollbar so "rest of the window" is what?
But yes one way to do it is make another wrapper div in body where everything goes and body has overflow:none; height:100%; width:100%; on it, wrapper div also also has 100% width and height. and overflow to scroll. SO NOW...the width of wrapper would be the width of viewport
See Example: http://jsfiddle.net/techsin/8fvne9fz/
html,body {
height: 100%;
overflow: hidden;
}
.wrapper {
width: 100%;
height: 100%;
overflow: auto;
}
With jQuery you can calculate the browser's scrollbar width by getting the width difference when overflow: hidden is set and overflow: scroll is set.
The difference in width will be the size of the scrollbar.
Here is a simple example that shows how you could do this.
You can get the window width with scrollbar , that way:
function scrollbar_width() {
if (jQuery('body').height() > jQuery(window).height()) {
/* Modified from: http://jdsharp.us/jQuery/minute/calculate-scrollbar-width.php */
var calculation_content = jQuery('<div style="width:50px;height:50px;overflow:hidden;position:absolute;top:-200px;left:-200px;"><div style="height:100px;"></div>');
jQuery('body').append(calculation_content);
var width_one = jQuery('div', calculation_content).innerWidth();
calculation_content.css('overflow-y', 'scroll');
var width_two = jQuery('div', calculation_content).innerWidth();
jQuery(calculation_content).remove();
return (width_one - width_two);
}
return 0;
}
Check out vw: http://dev.w3.org/csswg/css-values/#viewport-relative-lengths
body {
width: 100vw;
}
http://caniuse.com/#search=vw
This is my solution for removing the 'scrollbar shadow', because scrollWidth didn't work for me:
canvas.width = element.offsetWidth;
canvas.height = element.offsetHeight;
canvas.width = element.offsetWidth;
canvas.height = element.offsetHeight;
It's easy, but it works. Make sure to add a comment explaining why you assign the same value twice :)