I need a little help: here is the piece of code incriminated:
html:
<div class="contain">
<div class="background-image background-cover"></div>
<div class="circle">
<div class="inside blur-big background-cover"></div>
<div class="inside blur-small background-cover"></div>
<div class="inside clear background-cover"></div>
</div>
</div>
CSS:
.contain {
position: relative;
height: 200px;
margin-left: -98px;
width: 150%;
}
.background-cover {
width: 100%;
height: 100%;
background: no-repeat center center fixed;
background-size: cover;
-webkit-background-size: cover;
}
.background-image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgb(36, 36, 36);
background-attachment: scroll;
background-image: url(https://dummyimage.com/600x400/000/fff);
}
.circle {
position: absolute;
border-radius: 100%;
width: 115px;
height: 115px;
box-sizing: border-box;
}
.circle .inside {
position: absolute;
top: 0;
left: 0;
border-radius: 100%;
background-image: url(https://dummyimage.com/600x400/000/fff);
}
.blur-big {
height: 100%;
width: 100%;
-webkit-filter: blur(3px);
filter: blur(3px);
}
/* positioned slightly 'inside' the big blur */
.blur-small {
margin: 5px;
height: 105px;
width: 105px;
-webkit-filter: blur(1px);
filter: blur(1px);
}
.clear {
margin: 10px;
height: 95px;
width: 95px;
}
JavaScript:
if ('ontouchstart' in window) {
} else
addContainMouseMoveFunctionality(); //just add this functionality when it'll be used
function addContainMouseMoveFunctionality() {
//do as little as possible in the mousemove-event, so initiate variables here
let circle = document.getElementsByClassName('circle')[0];
let contain = document.getElementsByClassName('contain')[0];
//add event listener for the mouse enters the image, show circle
contain.addEventListener("mousemove", moveCircle);
//add event listener for when the mouse leaves the image, hide circle
contain.addEventListener("mouseout", function(e) {
//give the circle a position outside the viewport
circle.style.top = '-999px';
circle.style.left = '-999px';
});
function moveCircle(e) {
//get the offset from the top to avoid the circle going all over the place when scrolling down or horizontally
let doc = document.documentElement;
let left = window.pageXOffset - doc.scrollLeft + doc.clientLeft;
let top = window.pageYOffset - doc.scrollTop + doc.clientTop;
//give the circle a position near the mouse, position minus half of its width/height to center it
circle.style.top = top + e.pageY - circle.offsetHeight / 2 + 'px';
circle.style.left = left + e.pageX - circle.offsetWidth / 2 + 98 + 'px'; // 98 is for the margin of contain
}
}
I think the problem is with these formulas but maybe not:
circle.style.top = top + e.clientY - circle.offsetHeight / 2 + 'px';
circle.style.left = left + e.clientX - circle.offsetWidth / 2 + 98 + 'px';
Here is a fiddle which shows how it works: https://jsfiddle.net/hw615quf/7/https://jsfiddle.net/hw615quf/7/
When you scroll a little to the right, you will see what the problem is: the circle which was centred around the cursor is now no more centred...
It is not that problematic in this fiddle but when I incorporate my code on the Wordpress site with Salient, the circle is pretty much down and left from the cursor's position. When I scroll down, the circle is a little bit closer to the image but still not centred... And anyway, I don't want my circle to be centred only when the image is barely visible.
Maybe it is my formula which is problematic? Can anyone help me with this scroll?
Thanks for your help and for reading, have a nice day/evening/night :)
Benjamin
clientX and clientY does not change as page scroll changes they remain fixed. You should use pageX and pageY in this scenario. Like this
circle.style.top = top + e.pageY - circle.offsetHeight / 2 + 'px';
circle.style.left = left + e.pageX - circle.offsetWidth / 2 + 98 + 'px';
Here is a working example https://jsfiddle.net/681Lakn0/
I am building a cordova app. When I click on div, its conponents are shown and the popup has to be in the center of screen. This is my code.
var new_height = $('#' + id).height() + 20;
var new_width = $('#' + id).width() * 0.97;
$('#' + id + '_popup').width(new_width);
var move_up = $('#' + id + '_popup').height() / 2;
$('#' + id + '_popup').css({
"overflow-y": 'auto',
'transform': 'translateY(-' + $('#' + id + '_popup').height() / 2 + 'px)'
});
$('#' + id + '_popup').css("z-index", '3000');
But when I scroll the page, the new div is not displaying in the center of div but above. What should I do?
You can achieve perfect center only with CSS, so remove that useless calculations and use transform like this:
.red {
position: absolute;
height: 100%;
width: 100%;
background: red;
}
.green {
position: absolute;
height: 40%;
width: 40%;
background: green;
top: 50%;
left:50%;
-webkit-transform: translate(-50%, -50%); /*safari iOS*/
transform: translate(-50%, -50%);
}
<div class="red">
<div class="green">
</div>
</div>
With this code doesn't matter the sizes of the boxes, it will be always at the center of the screen.
You can change position to fixed or relative and still will work.
How can I resize and reposition the image inside a box, in such way that it covers the entire box, similar to how background-size: cover works.
<div class="box" style="width: 100px; height: 100px;">
<img src="pic.jpg" width="413" height="325">
</div>
I know I have to add overflow:hidden to the box and the image needs position: absolute. But what's the formula that gets me the right new size for the image, and left + top positions?
For what it's worth: this can now be done with CSS alone with...
The new CSS property object-fit (Current browser support)
Just set object-fit: cover; on the img
You don't even need to wrap the img in a div!
FIDDLE
img {
width: 100px;
height: 100px;
}
.object-fit {
display: block;
object-fit: cover;
}
.original {
width: auto;
height: auto;
display: block;
}
<img src="http://lorempixel.com/413/325/food" width="413" height="325">
<p>Img 'squashed' - not good</p>
<img class="object-fit" src="http://lorempixel.com/413/325/food" width="413" height="325">
<p>object-fit: cover -
The whole image is scaled down or expanded till it fills the box completely, the aspect ratio is maintained. This normally results in only part of the image being visible. </p>
<img class="original" src="http://lorempixel.com/413/325/food" width="413" height="325">
<p>Original ing</p>
You can read more about this new property in this webplatform article.
Also, here is a fiddle from the above article which demonstrates all the values of the object-fit property.
Close enough, pure CSS solution for background size cover simulation using img tag with very good browser support (IE8+):
.container {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
overflow: hidden;
}
.container img {
position: absolute;
top: 50%;
left: 50%;
width: auto;
height: auto;
max-height: none;
max-width: none;
min-height: 100%;
min-width: 100%;
transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
-webkit-transform: translate(-50%, -50%);
}
<div class="container">
<img src="//lorempixel.com/400/200/sports/1/" />
</div>
this may be easier
jQuery
$('.box').each(function() {
//set size
var th = $(this).height(),//box height
tw = $(this).width(),//box width
im = $(this).children('img'),//image
ih = im.height(),//inital image height
iw = im.width();//initial image width
if (ih>iw) {//if portrait
im.addClass('ww').removeClass('wh');//set width 100%
} else {//if landscape
im.addClass('wh').removeClass('ww');//set height 100%
}
//set offset
var nh = im.height(),//new image height
nw = im.width(),//new image width
hd = (nh-th)/2,//half dif img/box height
wd = (nw-tw)/2;//half dif img/box width
if (nh<nw) {//if portrait
im.css({marginLeft: '-'+wd+'px', marginTop: 0});//offset left
} else {//if landscape
im.css({marginTop: '-'+hd+'px', marginLeft: 0});//offset top
}
});
css
.box{height:100px;width:100px;overflow:hidden}
.wh{height:100%!important}
.ww{width:100%!important}
This should handle any size/orientation, and will not only resize, but offset the images. All without relative or absolute positioning.
made a fiddle: http://jsfiddle.net/filever10/W8aLN/
Also for what it's worth, the same effect can be produced by instead of setting "width" and "height" (setting them could break this approach btw):
min-width: 100%;
min-height: 100%;
or
min-width: (your desired percent of viewport width)vw;
min-height: (your desired percent of viewport height)vh;
with
overflow: hidden;
on the parent
:)
The idea is to make additional wrapper for image:
<div class="wrap">
<div class="inner">
<img src="http://placehold.it/350x150">
</div>
</div>
And use such CSS:
.wrap {
position: relative;
width: 100%;
height: 200px;
background: rgba(255, 0, 0, 0.3);
overflow: hidden;
}
.inner {
position: absolute;
min-width: 100%;
height: 100%;
left: 50%;
-moz-transform: translateX(-50%);
-o-transform: translateX(-50%);
-ms-transform: translateX(-50%);
-webkit-transform: translateX(-50%);
transform: translateX(-50%);
}
.inner img {
position: absolute;
min-height: 100%;
min-width: 100%;
top: 50%;
left: 50%;
-moz-transform: translate(-50%, -50%);
-o-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
This is working example: https://jsfiddle.net/kr60jroe/
From https://developer.mozilla.org/en-US/docs/Web/CSS/background-size:
cover
This keyword specifies that the background image should be scaled to be as small as possible while ensuring both its dimensions are greater than or equal to the corresponding dimensions of the background positioning area.
So, you're either looking at making the width: 100% or the height: 100%, whichever will create an overlap within the parent div. So we can use the following logic:
var makeBackgroundCover = function (div) {
$(div + " img").css("height", "100%");
if ($(div + " img").width() < $(div).width()) {
$(div + " img").css({
"height": "auto",
"width": "100%"
});
}
}
The following fiddle shows this function working on both a horizontal and vertical image.
http://jsfiddle.net/2r5Cb/
Here is my approach:
//collect the nodes
var parent = $('.box');
var img = $('image', box);
//remove width and height attributes
img.removeAttr('width');
img.removeAttr('height');
//set initial width
img.attr('width', parent.width());
//if it's not enough, increase the width according to the height difference
if (img.height() < parent.height()) {
img.css('width', img.width() * parent.height() / img.height());
}
//position the image in the center
img.css({
left: parseInt((img.width() - parent.width())/-2) + 'px',
top: parseInt((img.height() - parent.height())/-2) + 'px'
});
FIDDLE
Here's a clean JavaScript function to do this and an example of implementation:
function backgroundCover(elementSizes, containerSizes) {
var elementRatio = elementSizes.width / elementSizes.height,
containerRatio = containerSizes.width / containerSizes.height;
width = null,
height = null;
if (containerRatio > elementRatio) {
width = Math.ceil( containerSizes.width );
height = Math.ceil( containerSizes.width / elementRatio );
} else {
width = Math.ceil( containerSizes.height * elementRatio );
height = Math.ceil( containerSizes.height );
}
return { width, height };
}
Here's an example of implementation:
HTML
<!-- Make sure the img has width and height attributes. The original image's width and height need to be set in order to calculate the scale ratio. -->
<div class="photo"><img src="photo.jpg" width="400" height="300"></div>
CSS
.photo {
position: relative;
overflow: hidden;
width: 200px;
padding-bottom: 75%; /* CSS technique to give this element a 4:3 ratio. */
}
.photo img {
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
-moz-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
JavaScript
$( window ).on( 'resize', function() {
$( '.cover-photo' ).each( function() {
var img = $( 'img', this ),
imgWidth = img.attr( 'width' ),
imgHeight = img.attr( 'height' ),
containerWidth = $( this ).width(),
containerHeight = $( this ).height(),
newSizes = backgroundCover( { width: imgWidth, height: imgHeight }, { width: containerWidth, height: containerHeight } );
img.css( {
width: newSizes.width,
height: newSizes.height
} );
} );
} );
While reading the accepted answer, it strikes me that we simply test on whether the image is 'portrait' or 'landscape':
if (ih>iw) {//if portrait
In the case of the OP, that's right. But others might be dealing with rectangles and should take the aspect ratio of the container and the 'child'-image into consideration:
var int_container_width = parseInt( $_container.width() );
var int_container_height = parseInt( $_container.height() );
var num_container_aspect = int_container_width/int_container_height;
var int_image_width = parseInt( $_image.width() );
var int_image_height = parseInt( $_image.height());
var num_image_aspect = int_image_width/int_image_height;
if ( num_image_aspect > num_container_aspect){
num_scale = int_container_width/int_image_width * 100;
} else {
num_scale = int_container_height/int_image_height * 100;
}
This is a pure css solution. You can define a wrapper with:
div.cover {
position: fixed;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
}
and the img:
img.cover {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
min-width: 50%;
min-height: 50%;
overflow-x: hidden;
}
Here the live example:
http://codepen.io/ErwanHesry/pen/JcvCw
You can use this style to the image tag :"object-fit:cover;"
This link will support you also https://css-tricks.com/almanac/properties/o/object-fit/
If you want the image centered in the box without resizing the image, just use this code:
.box {
width: 100px;
height: 100px;
overflow: hidden;
position: relative;
}
.box img {
width: 413px;
height: 325px;
position: absolute;
left: 50%;
top: 50%;
}
If you are looking to resize the image to fit, use the following code:
.box {
width: 100px;
height: 100px;
}
.box img {
width: 100%;
height: auto;
}
This code will leave some white space if the image is wider than it is tall. If neither of these work, you could just set the image as a background and use background-size: cover;.
For anyone who happens across this answer as I did today looking for a solution that will work with landscape, portrait, rectangle, square, etc images and arbitrary container sizes, I have included my own code below.
This will also work responsively, you'll just need to run it again whenever the window resizes.
JSFiddle:
http://jsfiddle.net/66c43ao1/
HTML
<div class="test">
<div class="cover">
<img src="http://d2ws0xxnnorfdo.cloudfront.net/character/meme/cool-dog.jpg" width="590" height="590"/>
</div>
</div>
CSS
/* modify the width and height below to demonstrate coverage */
.test {
height: 300px;
position: relative;
width: 500px;
}
/* you will need the below styles */
.cover {
height: 100%;
left: 0;
overflow: hidden;
position: absolute;
top: 0;
width: 100%;
z-index: 1;
}
JS
$('.cover').each(function() {
var containerHeight = $(this).height(),
containerWidth = $(this).width(),
image = $(this).children('img'),
imageHeight = image.attr('height'),
imageWidth = image.attr('width'),
newHeight = imageHeight,
newWidth = imageWidth;
if (imageWidth < containerWidth) {
// if the image isn't wide enough to cover the space, scale the width
newWidth = containerWidth;
newHeight = imageHeight * newWidth/imageWidth;
}
if (imageHeight < containerHeight) {
// if the image isn't tall enough to cover the space, scale the height
newHeight = containerHeight;
newWidth = imageWidth * newHeight/imageHeight;
}
var marginLeft = (newWidth - containerWidth)/2;
var marginTop = (newHeight - containerHeight)/2;
image.css({
marginLeft : '-' + marginLeft + 'px',
marginTop : '-' + marginTop + 'px',
height : newHeight,
width : newWidth
});
});
You can of course use libraries such as Backstretch which do this same thing, but I found this solution to be better for my purposes (no increase in dependencies, lighter weight, etc).
I created a function below that should do it. I borrowed some of the logic from the accepted answer and adjusted it to work with any container by creating a ratio for image dimension : container dimension and then compared which is greater to figure which dimension to adjust. Also added a 'center' argument ('true' centers, false sets it to top/left).
I'm using CSS3 with the translateX/Y, but could get it working without it easily enough.
Here's the code:
var coverImage = function(wrap, center) {
if (typeof center === 'undefined') {
center = true;
}
var wr = $(wrap),
wrw = wr.width(),
wrh = wr.height();
var im = wr.children('img'),
imw = im.width(),
imh = im.height();
var wratio = wrw / imw;
var hratio = wrh / imh;
//Set required CSS
wr.css({'overflow' : 'hidden'});
im.css({'position' : 'relative'});
if (wratio > hratio) {
im.width(wrw);
im.css({'height' : 'auto'});
if (center) {
im.css({
'top' : '50%',
'transform' : 'translateY(-50%)'
});
}
} else {
im.height(wrh);
im.css({'width' : 'auto'});
if (center) {
im.css({
'left' : '50%',
'transform' : 'translateX(-50%)'
});
}
}
}
and checkout the jsfiddle to see it in action: https://jsfiddle.net/cameronolivier/57nLjoyq/2/
I made something could work to emulate a background-size:cover and background-position:center.
If you want to change the position just change the styles "top" an "left" of the img
CSS
.box{
overflow:hidden;
position:relative;
}
.box img{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
-webkit-transform: translate(-50%, -50%);
}
JS
$('.box').each(function() {
//aspect ratio of container
var boxRatio = $(this).height() / $(this).width();
//aspect ration of image
var imageRatio = $(this).children('img').height() / $(this).children('img').width();
//set width or height 100% depend of difference
if (imageRatio > boxRatio) {
$(this).children('img').css({"width":"100%","height":"auto"});
} else {
$(this).children('img').css({"height":"100%","width":"auto" });
}
});
This function should be activated on "load" and "resize" event.
I am using this script to create a parallax scroll effect on my page:
$(window).scroll(function (e) {
parallax();
});
function parallax() {
var scrolled = $(window).scrollTop();
$('.cloud1').css('top', - (scrolled * 0.1) + '%');
$('.cloud2').css('top', - (scrolled * 0.3) + '%');
$('.cloud3').css('top', - (scrolled * 0.2) + '%');
}
HTML:
<div class="cloud1"></div>
<div class="cloud2"></div>
<div class="cloud3"></div>
CSS (same for .cloud2 and .cloud3 but with different background image, opacity and 'top' 'left'):
.cloud1 {
background: url(../images/cloud1.png) no-repeat;
opacity: 0.9;
position: fixed;
width: 100%;
height: 100%;
top: 50%;
left: 20%;
z-index: 1;
}
When the script begins (on scroll) the HTML changes to this:
<div class="cloud1" style="top: 0%; "></div>
which makes the 'cloud' jump to the top of the page, and then the parallax starts (which you can see for a very short period of time as it's already jumped to the top of the page)
Is there a way to set the style="top: 0%;" to start at say 20% when the parallax begins, and then begin to multiply by 0.1?
Here is a codepen of the problem : http://codepen.io/anon/pen/tkfDH
Hopefully this is clear,
Any help is appreciated
Jon
Okay so I think i've fixed the problem.
$(window).scroll(function(e){
parallax();
});
function parallax(){
var scrolled = $(window).scrollTop();
$('.cloud1').css('top', -(scrolled*0.1)+70+'%');
// the 70 corresponds to the 'cloud1' value for 'top'.
$('.cloud2').css('top', -(scrolled*0.3)+50+'%');
// the 50 corresponds to the 'cloud2' value for 'top'.
}
http://cdpn.io/naIjf
#hero {
background:black;
color: white;
}
.cloud1, .cloud2 {
opacity: 0.8;
position: fixed;
width: 100%;
height: 100%;
z-index: 1;
}
.cloud1 {
background: url('http://www.jrk-design.co.uk/v2/images/big-cloud.png') no-repeat;
top: 70%;
left: 0;
}
.cloud2 {
background: url('http://www.jrk-design.co.uk/v2/images/big-cloud.png') no-repeat;
top: 50%;
left: 65%;
}
Fixed the jump.
Hope this helps.