I wanna keep the section filled with a background image after the position transform.
Using this code I get a white background from the body element.
<section><div class="firstpage"></div></section>
.firstpage{
position: absolute;
background-image:url('https://i.ibb.co/HGSY9Rv/bcb.png');
background-attachment: fixed;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
height:100%;
width:100%;
}
$(".firstpage").mouseenter(function(){
$(".firstpage").animate({
'background-position-x': '-200px',
});});
$(".firstpage").mouseleave(function(){
$(".firstpage").animate({
'background-position-x': '0px',
});});
https://codepen.io/gamegame/pen/NWMpJvy
make the bg image bigger in the width by using a calculation
the calculation is created by using native CSS calc()/var()
basically, we add the length of the animation to the width
so it will always overflow,
and this is correct since we have a calc() (so it is responsive)
so the animation works fine always bigger and smaller display
100% + 200px
(let's say if the width of your device is 550px, now this calcolation will be 550 + 200 = 750)
and there isn't any need for javascript for animation
because with :hover we can do the same / and transition
code example:
body {
margin: 0;
overflow:hidden; /* for not see the scrollbar */
}
.firstpage {
--x: 200px;
position: absolute;
background-image: url("https://i.ibb.co/HGSY9Rv/bcb.png");
/* not use `attachment: fixed` here */
background-position: center;
background-repeat: no-repeat;
background-size: cover;
height: 100%;
width: calc(100% + var(--x));
transition: background-position-x 0.5s ease-in-out;
}
.firstpage:hover {
background-position-x: calc(var(--x) * -1); /* 200px * -1 = -200px */
}
<section>
<div class="firstpage"></div>
</section>
I'm using CSS transform: scale(0.6) to scale down a div. When the element is scaled down, it maintains its aspect ratio. However, in my case, this element needs to always have a height that will reach the bottom of the viewport. This means I need to adjust the height of the element while keeping its width and top position the same.
How do I calculate the height I need to apply so that the element reaches the bottom of the viewport exactly when transform: scale(x) is applied?
below is a codesnippet. Clicking anywhere scales the div down and it's when I should apply the new height to allow the div height to reach the bottom of the viewport while keeping the same width, and position.
document.body.addEventListener('click', () => {
document.querySelectorAll('div')[0].style.transform = 'scale(0.44)';
});
body {
margin: 0;
padding: 0;
height: 100vh;
}
div {
width: 350px;
height: calc(100% - 50px);
position: absolute;
top: 50px;
background-color: red;
position: absolute;
transform-origin: top;
}
<div><h1>TEST</h1></div>
Since you want the div's height to stretch till bottom, you can make use of window.innerHeight here.
The new height can be calculated using the following formula :-
newHeight = (viewportHeight - offsetTop)*(1/scaleValue)
Putting in values it will come down to the following calculation :-
newHeight = (window.innerHeight - div.offsetTop)*(1/0.44)
document.body.addEventListener('click', () => {
const div = document.querySelectorAll('div')[0];
div.style.transform = 'scale(0.44)';
div.style.height = `${(window.innerHeight-div.offsetTop)*(1/0.44)}px`
});
body {
margin: 0;
padding: 0;
height: 100vh;
}
div {
width: 350px;
height: calc(100% - 50px);
position: absolute;
top: 50px;
background-color: red;
position: absolute;
transform-origin: top;
}
<div>
<h1>TEST</h1>
</div>
i see you position it from the top. i think that if you position it from bottom you will get what u want.
change top to bottom: 0px
change tranform-origin to transform-origin:bottom
and for calculating the height u could use 100VH instead of 100%
I have a div that is centered on the page and scales with viewport in a way that its aspect ratio (16:9) is maintained. The problem is, I want the font and content inside to scale with the div as it resizes, as well. Vmin works, for the most part, without issue. It would work perfectly if the aspect ratio of the div is 1:1 because vmin checks for the lesser value between height and width of the viewport directly, and you can't set a custom aspect ratio.
<!DOCTYPE html>
<html>
<head>
<style>
body {
background-color:white;
}
.wrapper {
width: 95vw;
height: calc(95vw * 9/16);
max-height: 95vh;
max-width: calc(95vh * 16/9);
background: center;
background-color: blue;
background-size:contain;
margin: auto;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
#lorem {
color: aqua;
font-size:10vmin;
text-align:center;
position:absolute;
transform: translate(-50%, -50%);
top: 50%;
left: 50%;
margin:auto;
}
</style>
</head>
<body>
<div class="wrapper">
<p id="lorem">
This text should scale with div only.
</p>
</div>
</body>
</html>
https://jsfiddle.net/Addictorator/70fq44sv/2/
Resize the window vertically to see what I'm talking about.
I don't believe there is a way in pure css (but if there is, that would be most preferred), but I think it is possible in javascript using an event listener onresize of the div and scaling each element down separately by a ratio comparing original (or previous - storing it as a var) div height/width to current div height/width. Or it could try and replicate vmin behavior but with height set to a ratio in a way 16:9 is considered instead of 1:1, like what was done on div using css above. I would prefer pure js and no jquery if at all possible. I've tried doing this myself, but I'm rather amateurish when it comes to javascript.
Thanks in advance!
Please see a working codepen here.
The solution is quite simple. On window resize we return the clientHeight of the parent. by dividing the returned value we achieve an integer that is usable as a font-size. We then assign this to the p element.
I hope this solves your problem.
//assigns font-size when document is ready
document.onreadystatechange = () => {
if (document.readyState === 'complete') {
var wrapperHeight = document.getElementById('wrapper').clientHeight;
var relativeFontSize = wrapperHeight / 10 + 'px'; //change 10 to any integer for desired font size
document.getElementById("lorem").style.fontSize = relativeFontSize;
}
};
//then on window resize
window.onresize = function(event) {
var wrapperHeight = document.getElementById('wrapper').clientHeight;
var relativeFontSize = wrapperHeight / 10 + 'px'; //change 10 to any integer for desired font size
document.getElementById("lorem").style.fontSize = relativeFontSize;
};
body {
background-color:white;
}
#wrapper {
width: 95vw;
height: calc(95vw * 9/16);
max-height: 95vh;
max-width: calc(95vh * 16/9);
background: center;
background-color: blue;
background-size:contain;
margin: auto;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
font-size:60px;
}
#lorem {
color: aqua;
text-align:center;
position:absolute;
transform: translate(-50%, -50%);
top: 50%;
left: 50%;
margin:auto;
}
<div id="wrapper">
<p id="lorem">
This text should scale with div only.
</p>
</div>
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.