I am working on an experimental art site that involves a grid of images each scaled to the size of the viewport. The background for the page body should be one stretched image and it was working at one point but has stopped functioning. The background color shows and the image simply doesn't. However if the background-size CSS is turned off in Chrome inspector it shows up at it's own size positioned top and left...
I am guessing that having body contain a box which amounts to 5 viewports wide and 5 viewports tall is messing with what the body element's size is? Though allowing bg image to repeat didn't make it show up...
I resolved this by grabbing the screen width and height in the JavaScript and then setting background-size to those values like so:
$('body,html').css('background-size',the_width + 'px ' + the_height+'px');
But my question remains- why did the background-size:100% 100% stop working?
The page HTML looks like this only with 25 total divs and images.
<body>
<div id="box">
<div class="full" id="full_10">
<img src="home_tiles/10.jpg" width="800" height="600" title="10">
</div>
<div class="full" id="full_11">
<img src="home_tiles/11.jpg" width="800" height="600" title="11">
</div>
</div>
</body>
The CSS looks like this
* { padding: 0; margin: 0; }
html, body {
overflow:hidden;
background-color: #FF0000;
background-size: 100% 100%;
background-image:url(home_tiles/edge.jpg);
background-repeat:no-repeat;
}
img { display: block; }
#box {
position:absolute;
}
.full {
float:left;
}
The JavaScript sizing the images is
$(function() {
$('.full').hide();
var win = $(window),
fullscreen = $('.full'),
image = fullscreen.find('img'),
imageWidth = image.width(),
imageHeight = image.height(),
imageRatio = imageWidth / imageHeight;
var the_width;
var the_height;
var left_limit;
var right_limit;
function resizeImage() {
var winWidth = win.width(),
winHeight = win.height(),
winRatio = winWidth / winHeight;
if(winRatio > imageRatio) {
the_width = winWidth;
the_height = Math.round(winWidth / imageRatio);
} else {
the_width = Math.round(winHeight * imageRatio);
the_height = winHeight;
}
left_limit = the_width * -2;
right_limit = the_width * 2;
image.css({
width: the_width,
height: the_height
});
$('#box').css({
width: the_width * 5,
height: the_height * 5,
top: the_height * -2,
left: the_width * -2
});
}
win.bind({
load: function() {
resizeImage();
$('.full').show('slow');
},
resize: function() {
resizeImage();
}
});
Related
Background
The below code creates a square box <div class="box"> and adds an animation of different sized circles.
At the moment, the script creates an animation across the whole page, but I’m trying to apply the animation script specifically to the square box <div class="box">.
I’ve tried changing the script document.body.append(circle) to document.getElementsByClassName("box")[0].appendChild(circle) with no success, the animation continues to apply across the whole page.
Question
What code changes are needed to apply the Script animation specifically to <div class="box"> ?
Code
<html>
<h1>Heading 1</h1>
<div class="box">
<h2>Heading 2</h2>
<p>This is some text inside a div element.</p>
</div>
<p>This is some text outside the div element.</p>
</html>
<style>
.circle {
position: absolute;
border-radius: 100%;
}
.box {
height: 500px;
width: 500px;
border: 5px outset red;
text-align: center;
}
</style>
<script>
const colors = ["#000000"];
const numCircles = 50;
const circles = [];
for (let i = 0; i < numCircles; i++) {
let circle = document.createElement("div");
circle.classList.add("circle");
circle.style.background = colors[Math.floor(Math.random() * colors.length)];
circle.style.left = `${Math.floor(Math.random() * 100)}vw`;
circle.style.top = `${Math.floor(Math.random() * 100)}vh`;
circle.style.transform = `scale(${Math.random()})`;
circle.style.width = `${Math.random()}em`;
circle.style.height = circle.style.width;
circles.push(circle);
document.body.append(circle);
}
circles.forEach((el, i, ra) => {
let to = {
x: Math.random() * (i % 10 === 0 ? -10 : 10),
y: Math.random() * 10
};
let anim = el.animate(
[
{ transform: "translate(0, 0)" },
{ transform: `translate(${to.x}rem, ${to.y}rem)` }
],
{
duration: (Math.random() + 1) * 2000,
direction: "alternate",
fill: "both",
iterations: Infinity,
easing: "ease-in-out"
}
);
});
</script>
Image
The problem is in
circle.style.left = `${Math.floor(Math.random() * 100)}vw`;
circle.style.top = `${Math.floor(Math.random() * 100)}vh`;
vw and vh use the full page width and full page height.
Change them to % AND replace document.body.append(circle); with document.querySelector('.box').append(circle). Also make sure the .box has position:relative to make sure the absolute positioning stays inside the box.
Result
step1: changing the script document.body.append(circle) to document.getElementsByClassName("box")[0].appendChild(circle)
step2: add below css to .box;
{
transform: scale(1);
overflow: hidden;
}
Result
I set my images centred in CSS:
background-position: center center;
But I want to know its top-position now after it is set to centre, how can I calculate that with jQuery or just plain javaScript?
.parallax3 {
position: relative;
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
background-image: url('https://picsum.photos/g/200/600');
height: 100%;
}
.tagline {
font-size: 2.5vw;
letter-spacing:0.05em;
padding: 25% 25%;
}
.grid-x {
border:1px solid red;
}
.cell {
border: 1px solid blue;
}
<div class="row widescreen">
<div class="grid-container full">
<div class="grid-x grid-padding-x align-stretch small-padding-collapse">
<div class="medium-6 cell">
<div class="tagline text-center">
<p>Lorem ipsum dolor sit amet</p>
</div>
</div>
<div class="medium-6 cell parallax-viewport">
<div class="parallax3">
</div>
</div>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/foundicons/3.0.0/foundation-icons.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.4.1/css/foundation.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.4.1/js/foundation.min.js"></script>
Any ideas?
As I commented above we need to find the formula, so the idea is to rely on the logic of background-position:center and background-size:cover. So since the image will always be stretched, we have two possibilities :
The top of the image will be the same as the top of div and thus top=0
The height of the image will be longer than the div and the top will be hidden and thus top<0
As you may notice I considered the top position relatively to the top of the div which is the origin for me
Now we need to consider all the different cases on how the image will cover the div and calculate the new height of the image depending on each situation.
Here is a code example:
//am using fixed values because they are known in this case, so this need to also be calculated
var him = 600;
var wim = 200;
var ratio = him / wim;
/*--*/
function get_top() {
var h = $('.parallax3').height();
var w = $('.parallax3').width();
var diffh = h - him;
var diffw = w - wim;
if (diffw > 0 && diffh > 0) {
//the image is smaller than the div so it should get bigger by at least the max difference
if (diffh > diffw*ratio) {
//both height will be equal here so top position = 0
console.log(0);
} else {
//height of image will be bigger so top position < 0
var newH = (wim + diffw) * ratio;
console.log((h - newH) / 2)
}
} else if (diffw > 0) {
//only the width if div is bigger so the image width will stretch and the height will be bigger and top < 0;
var newH = (wim + diffw) * ratio;
console.log((h - newH) / 2)
} else if (diffh > 0) {
//only the height is bigger so the image height will stretch and both heights will be equal to div and top = 0
console.log(0);
} else {
// the image is bigger in this case so we do same logic as the start with abs value but we will reduce size so we consider the lowest value
if (Math.abs(diffh) < Math.abs(diffw)*ratio) {
//both height will be equal here so top position = 0
console.log(0);
} else {
//height of image will remain bigger so top position < 0
var newH = (wim + diffw) * ratio;
console.log((h - newH) / 2)
}
}
}
get_top();
$(window).resize(function() {
get_top()
})
body {
height: 100vh;
}
.parallax3 {
position: relative;
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
background-image:url('https://picsum.photos/g/200/600');
height: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parallax3">
</div>
If we consider contain as value in background-size the image will always be contained inside the div so the two possibilities are:
The top of the image will be the same as the top of the div and thus top=0
The image will be smaller in height and the top of image will be visible and thus top>0
Same thing as the above, we need to consider the different situations and calculate the new height of the image.
Here is a code example:
//am using fixed values because they are known in this case, so this need to also be calculated
var him = 600;
var wim = 200;
var ratio = him / wim;
/*--*/
function get_top() {
var h = $('.parallax3').height();
var w = $('.parallax3').width();
var diffh = h - him;
var diffw = w - wim;
if (diffw > 0 && diffh > 0) {
//the image is smaller than the div so it should get bigger by at least the min difference
if (diffh < diffw*ratio) {
//both height will be equal here so top position = 0
console.log(0);
} else {
//height of image will be bigger so top position < 0
var newH = (wim + diffw) * ratio;
console.log((h - newH) / 2)
}
} else if (diffw > 0) {
//only the width if div is bigger so the image height need to be reduced and both height will be equal
console.log(0);
} else if (diffh > 0) {
//only the height is bigger so the image width will be reduced
var newH = (wim + diffw) * ratio;
console.log((h - newH) / 2);
} else {
// the image is bigger in this case so we do same logic as the start with abs value but we will reduce size so we consider the biggest value
if (Math.abs(diffh) > Math.abs(diffw)*ratio) {
//both height will be equal here so top position = 0
console.log(0);
} else {
//height of image will be bigger so top position < 0
var newH = (wim + diffw) * ratio;
console.log((h - newH) / 2)
}
}
}
get_top();
$(window).resize(function() {
get_top()
})
body {
height: 100vh;
}
.parallax3 {
position: relative;
background-position: center center;
background-repeat: no-repeat;
background-size: contain;
background-image: url('https://picsum.photos/g/200/600');
height: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parallax3">
</div>
Both snippet can be optimized to reduce redundancy but I kept them like this to better explain different situations.
I want to build a page to show a blown-up version of an image.
I have the smaller image and the bigger image built out. I am not sure how to build the in between portion that looks like rays coming out of the smaller image.
HTML
<div class="flex">
<div class="exp" tabindex="0">
<img class="image" src="http://via.placeholder.com/50x50">
</div>
<div class="big-image">
<img class="image" src="http://via.placeholder.com/350x550">
</div>
</div>
CSS
.exp {
margin: 5px;
width: 100px;
height: 100px;
background-color: #ded3c0;
border-radius: 100%;
line-height: 80px;
align-items: center;
display: flex;
justify-content: center;
}
.exp .image {
width: 50px;
height: 50px;
}
.big-image {
border: 1px solid #000;
padding: 20px;
border-radius: 19px;
}
.flex {
display: flex;
align-items: center;
justify-content: space-around;
}
Any pointers on how to do this is helpful.
Here is jsfiddle https://jsfiddle.net/npkeq7ut/
If you need only lines you can achieve this with JS and skew transform:
let topLine = document.getElementById('top-line');
let bottomLine = document.getElementById('bottom-line');
function updateLines()
{
let b = document.getElementById('b').getBoundingClientRect();
let a = document.getElementById('a').getBoundingClientRect();
let left = a.right;
let width = b.left - a.right;
let tHeight = a.top - b.top;
let tTop = tHeight / 2 + b.top;
let tAngle = Math.atan(tHeight / width) * 180 / Math.PI;
let bHeight = b.bottom - a.bottom;
let bTop = bHeight / 2 + a.bottom - bottomLine.offsetHeight;
let bAngle = Math.atan(bHeight / width) * 180 / Math.PI;
topLine.style.top = tTop + "px";
topLine.style.left = left + "px";
topLine.style.width = width + "px";
topLine.style.transform = "skewY("+(-tAngle)+"deg)";
bottomLine.style.top = bTop + "px";
bottomLine.style.left = left + "px";
bottomLine.style.width = width + "px";
bottomLine.style.transform = "skewY("+(bAngle)+"deg)";
}
updateLines();
Fiddle: https://jsfiddle.net/JacobDesight/f40yeuqe/2/
#EDIT
If you want trapeze with background then here is example using canvas: https://jsfiddle.net/JacobDesight/f40yeuqe/3/
This could be a starting point for you.
Code by thecodeplayer.
http://thecodeplayer.com/walkthrough/magnifying-glass-for-images-using-jquery-and-css3
$(document).ready(function() {
var native_width = 0;
var native_height = 0;
//Now the mousemove function
$(".magnify").mousemove(function(e) {
//When the user hovers on the image, the script will first calculate
//the native dimensions if they don't exist. Only after the native dimensions
//are available, the script will show the zoomed version.
if (!native_width && !native_height) {
//This will create a new image object with the same image as that in .small
//We cannot directly get the dimensions from .small because of the
//width specified to 200px in the html. To get the actual dimensions we have
//created this image object.
var image_object = new Image();
image_object.src = $(".small").attr("src");
//This code is wrapped in the .load function which is important.
//width and height of the object would return 0 if accessed before
//the image gets loaded.
native_width = image_object.width;
native_height = image_object.height;
} else {
//x/y coordinates of the mouse
//This is the position of .magnify with respect to the document.
var magnify_offset = $(this).offset();
//We will deduct the positions of .magnify from the mouse positions with
//respect to the document to get the mouse positions with respect to the
//container(.magnify)
var mx = e.pageX - magnify_offset.left;
var my = e.pageY - magnify_offset.top;
//Finally the code to fade out the glass if the mouse is outside the container
if (mx < $(this).width() && my < $(this).height() && mx > 0 && my > 0) {
$(".large").fadeIn(100);
} else {
$(".large").fadeOut(100);
}
if ($(".large").is(":visible")) {
//The background position of .large will be changed according to the position
//of the mouse over the .small image. So we will get the ratio of the pixel
//under the mouse pointer with respect to the image and use that to position the
//large image inside the magnifying glass
var rx = Math.round(mx / $(".small").width() * native_width - $(".large").width() / 2) * -1;
var ry = Math.round(my / $(".small").height() * native_height - $(".large").height() / 2) * -1;
var bgp = rx + "px " + ry + "px";
//Time to move the magnifying glass with the mouse
var px = mx - $(".large").width() / 2;
var py = my - $(".large").height() / 2;
//Now the glass moves with the mouse
//The logic is to deduct half of the glass's width and height from the
//mouse coordinates to place it with its center at the mouse coordinates
//If you hover on the image now, you should see the magnifying glass in action
$(".large").css({
left: px,
top: py,
backgroundPosition: bgp
});
}
}
})
})
/*Some CSS*/
* {
margin: 0;
padding: 0;
}
.magnify {
width: 200px;
margin: 50px auto;
position: relative;
}
/*Lets create the magnifying glass*/
.large {
width: 175px;
height: 175px;
position: absolute;
border-radius: 100%;
/*Multiple box shadows to achieve the glass effect*/
box-shadow: 0 0 0 7px rgba(255, 255, 255, 0.85), 0 0 7px 7px rgba(0, 0, 0, 0.25), inset 0 0 40px 2px rgba(0, 0, 0, 0.25);
/*Lets load up the large image first*/
background: url('http://thecodeplayer.com/uploads/media/iphone.jpg') no-repeat;
/*hide the glass by default*/
display: none;
}
/*To solve overlap bug at the edges during magnification*/
.small {
display: block;
}
<!-- Lets make a simple image magnifier -->
<div class="magnify">
<!-- This is the magnifying glass which will contain the original/large version -->
<div class="large"></div>
<!-- This is the small image -->
<img class="small" src="http://thecodeplayer.com/uploads/media/iphone.jpg" width="200"/>
</div>
<!-- Lets load up prefixfree to handle CSS3 vendor prefixes -->
<script src="http://thecodeplayer.com/uploads/js/prefixfree.js" type="text/javascript"></script>
<!-- You can download it from http://leaverou.github.com/prefixfree/ -->
<!-- Time for jquery action -->
<script src="http://thecodeplayer.com/uploads/js/jquery-1.7.1.min.js" type="text/javascript"></script>
I'm trying to write a layout where I have a toolbar and a main div. When the window Y axis is smaller than window X axis, the toolbar is on the left side. And when the window X axis is smaller than the window Y axis the toolbar is on the top.
I've positioned the toolbar absolute at the top:0 and left: 0 and tried changing width and height properties on resize. But my code is not working.
Javascript:
window.onresize = function(event) {
winW = window.innerWidth;
winH = window.innerHeight;
console.debug("x axis:" + winW + "y axis:" + winH);
if(winW < winH){
var elem = document.getElementById('div1');
console.debug("test" + elem.style.width);
var a = elem.style.height;
elem.style.height = elem.style.width;
elem.style.width = a;
}
else{
var elem = document.getElementById('div1');
elem.style.height = elem.style.height;
elem.style.width = elem.style.width;
}
}
CSS:
#div1{
background: red;
position:absolute;
height:100%;
width:20px;
top:0;
left:0;
}
#div2{
width:100%;
height:500px;
background-color:green;
margin-left: 20px;
}
jsFiddle Example Here
You can do this using #media screen and (min-aspect-ratio: 1/1) { ... }. Any styles inside this query will only activate when the window is as wide, or wider than it is high.
DEMO
I added this code, and removed all the JavaScript:
#media screen and (min-aspect-ratio: 1/1) {
#div1 {
width: 100%;
height: 20px;
}
#div2 {
width: 100%;
margin: 0;
}
}
Information can be found here on the MDN
Support for Media Queries can be found here, but as you can use JavaScript I would recommend using Respond.js to make them work for all users.
Upvote for the media ratio ;)
More browser-compatible:
window.onresize = function(event) {
winW = window.innerWidth;
winH = window.innerHeight;
console.debug("x axis:" + winW + "y axis:" + winH);
document.getElementById("div1").className = ( winW < winH ? "verticalMenu" : "horizontalMenu" );
}
// optionally invoke window.resize() once manually for setting it default. Or set a defaultClass on the div itself in HTML
and
.horizontalMenu {
height:20px;
width:100%;
}
.verticalMenu {
height:100%;
width:20px;
}
See this CodePen.
I'm working on a site based on this: http://inner.geek.nz/javascript/parallax/
All's well except I'm getting a jump down (by whatever px is set in calcParallax(xx, x, posY))
on scroll. This number should be where the image ends not where it begins — it should begin scrollTop or 0. Not sure what I'm doing wrong, I've pretty much taken the structure verbatim from the above link without the #cloud object or relevant script.
Here's what I have:
<script type="text/javascript">
function calcParallax(tileheight, speedratio, scrollposition) {
return ((tileheight) - (Math.floor(scrollposition / speedratio) % (tileheight+1)));
}
window.onload = function() {
window.onscroll = function() {
var posX = (document.documentElement.scrollLeft) ? document.documentElement.scrollLeft : window.pageXOffset;
var posY = (document.documentElement.scrollTop) ? document.documentElement.scrollTop : window.pageYOffset;
var ground = document.getElementById('ground');
var groundparallax = calcParallax(53, 8, posY);
ground.style.backgroundPosition = "0 " + groundparallax + "px ";
document.getElementById('javascriptcode').onscroll = function() {
var posX = (this.scrollLeft) ? this.scrollLeft : this.pageXOffset;
var j = calcParallax(53, 16, posX);
console.log('scroll js: '+ j);
document.getElementById('javascriptcode').style.backgroundPosition = j + "px 0";
}
}
</script>
Any help would be much appreciated
Use this example instead. It uses a different jQuery that seems more stable and does not jump around like the script from inner geek.
http://www.stevefenton.co.uk/cmsfiles/assets/File/backgroundparallax.html
I put together a demo on something similar while trying to minimize scripting in the scroll event... I've found that it's jumpy in Firefox and Chrome, and oddly smooth as silk in IE.
Even this game website that uses a combination of Mootools and CSS transitions is a bit jumpy.
CSS
/* Tiled background image */
body {
margin: 0;
padding: 0;
/* Use height of header image for top position */
background: #000 url(http://i201.photobucket.com/albums/aa236/Mottie1/testsite/forums/bgtile.jpg) left 1080px repeat-y;
}
/* Top background image (1920x1080) */
#wrapper {
position: relative;
top: 0;
left: 0;
height: 100%;
width: 100%;
background: url(http://i201.photobucket.com/albums/aa236/Mottie1/testsite/forums/bg1.jpg) center top repeat-x;
z-index: 100;
}
/* Page Title image */
#header {
height: 350px;
background: url(http://i201.photobucket.com/albums/aa236/Mottie1/testsite/forums/title.png) center 40px no-repeat;
}
/* Content Block with 55% opacity background image */
.block {
width: 600px;
height: 500px;
margin: 20px auto;
border: #333 1px solid;
padding: 20px;
background: url(http://i201.photobucket.com/albums/aa236/Mottie1/testsite/forums/bg-black-55.png);
}
.block h3 {
font-family: 'Arial Black', Gadget, sans-serif;
font-size: 130%;
}
HTML
<body> <!-- contains repeated background image -->
<div id="wrapper"> <!-- contains top image -->
<div id="header"></div> <!-- contains the page title image -->
<div class="block"> <!-- contains 55% opacity background image -->
<h3>Block 1</h3>
<div class="content">Content 1.</div>
</div>
<div class="block">
<h3>Block 2</h3>
<div class="content">Content 2.</div>
</div>
<div class="block">
<h3>Block 3</h3>
<div class="content">Content 3.</div>
</div>
<div class="block">
<h3>Block 4</h3>
<div class="content">Content 4.</div>
</div>
<div class="block">
<h3>Block 5</h3>
<div class="content">Content 5.</div>
</div>
</div>
</body>
Script
$(document).ready(function(){
// defaults
var st, win = $(window)[0],
body = $('body')[0],
doc = (jQuery.support.boxModel) ? document.documentElement : document.body,
wrap = $('#wrapper')[0],
// Set top background image height here
imgH = 1080; // top image height
// vertical parallax scroll
$(win).scroll(function(){
st = (win.pageYOffset || doc.scrollTop );
if (st < imgH) { wrap.style.backgroundPosition = 'center ' + (st/4) + 'px'; } // limit moving top image only when in view
body.style.backgroundPosition = 'left ' + ( imgH + st/4) + 'px';
});
});
Change your 53 to the exact height of each element.
The only thing I can't figure out about this script is it jumps slightly vertically when I change it to a scroll left function.
var element = document.getElementById('element');
var elementparallax = calcParallax(7000, .5, posX);
element.style.backgroundPosition = " 0" + elementparallax + "px";
};
P.S. You can change the vertical scroll to horizontal by changing posY to posX and in = "0_" + elementparalax to = "_0"