I am currently creating a horizontal image slider which will be used more than once with different amount of images.
At the moment, the parent div needs to be bigger than 100% to fit all images in, so I calculate the width by adding all widths of the child divs (which include the images) manually in a calculator and then add it to the css, but I want to be able to calculate it automatically with the help of either CSS or JS/jQuery.
window.onload = function(){
let images = [...document.querySelectorAll('.bild')];
let slider = document.querySelector('.slider');
let sliderWidth;
let imageWidth;
let current = 0;
let target = 0;
let ease = .05;
window.addEventListener('resize', init);
function lerp(start, end, t){
return start * (1-t) + end * t;
}
function setTransform (el, transform){
el.style.transform = transform;
}
function init(){
sliderWidth = slider.getBoundingClientRect().width;
imageWidth = sliderWidth / images.length;
document.body.style.height = `${sliderWidth - (window.innerWidth - window.innerHeight)}px`
}
function animate(){
current = parseFloat(lerp(current, target, ease)).toFixed(2);
target = window.scrollY;
setTransform(slider, `translateX(-${current}px)`);
requestAnimationFrame(animate);
}
init();
animate();
console.log(sliderWidth)
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
}
.slider {
position: absolute;
top: 0;
left: 0;
width: 3900px; /* this should be calculated automatically by the amount of divs with the class "item" multiplied by the item width */
height: 100%;
}
.slider-inner {
position: absolute;
top: 5%;
height: 90%;
display: flex;
justify-content: space-around;
}
.item {
position: relative;
width: 455px;
height: 100%;
overflow: hidden;
z-index: 1;
background: #13271b;
}
.image {
position: absolute;
width: 435px;
height: 100%;
background-size: cover;
background-position: top center;
border: none;
}
/* example "images" */
#one, #four {
background-color: #aaaaaa;
}
#two, #five {
background-color: #222222;
}
#three, #six {
background-color: #777777;;
}
#zero {
background-color: #ee2277;;
}
<div class="container">
<div class="slider">
<div class="slider-inner">
<div class="item">
<div class="image" id="zero">
</div>
</div>
<div class="item">
<div class="image" id="one">
</div>
</div>
<div class="item" >
<div class="image" id="two">
</div>
</div>
<div class="item">
<div class="image" id="three">
</div>
</div>
<div class="item">
<div class="image" id="four">
</div>
</div>
<div class="item">
<div class="image" id="five">
</div>
</div>
<div class="item">
<div class="image" id="six">
</div>
</div>
</div>
</div>
</div>
Try something like this:
/** #param {HTMLElement} sliderEl */
function scaleSlider(sliderEl) {
let totalWidth = 0;
sliderEl.querySelectorAll(".item").forEach(item => totalWidth += item.getBoundingClientRect().width);
sliderEl.style.width = `${totalWidth}px`;
}
Related
I have a UI that involves (on wider devices) a 2 column layout that scroll in opposite directions in an infinite loop. On page load the UI seems to work pretty well but I really need some help improving some aspects of it.
The key things I want to work on are:
Order of items (projects) matches HTML structure. Currently they're reversed
Improve how the UI reacts and displays on browser resize
Fix ESLint undefined errors for "Map" and Weakmap"
1. Order of Items (projects)
You can see I've number each .project and on load the one that appears last in the HTML is first when viewing the webpage. It would make more sense the 'top' item is visible in the viewport before revealing the others in cascading order on scroll.
2. UI on Browser Resize
Though the UI seems to work well on page load, I think due to the positional values set on each .project this seems to lead to content overlapping or getting cropped on resize. I've tried matchMedia to see if I can run/recalculate once the viewport has 'stopped' resizing but doesn't seem to work.
It doesn't seem as bad going from desktop to mobile size screens. But vice versa, if you open on a narrow viewport and enlarge no content is visible and the UI appears empty until you scroll ...and then the left column doesn't loop (it stops) until you refresh the page.
On the mid-point #media when each .project has 50vh and not 100vh on scroll the items appear to flicker. Again, until you refresh.
It seems like maybe I need to run the script again after each resize? This is for a 'fun' portfolio style project so I appreciate that's a bit heavy on the resource but maybe acceptable in this instance, as it's not a commercial or D2C site?
3. ESLint Errors
Lastly, I get 2 errors saying Map and Weakmap are undefined when I compile using CodeKit and ESLint. That is in relation to these 2 lines...
const lastScrollPos = new WeakMap();
const linkedLoops = new Map([
I know there's a couple of issues but I wanted to break them down to try and be as clear as possible.
const leftLoop = document.querySelector(".split-loop__left");
const rightLoop = document.querySelector(".split-loop__right");
const scrollHeight = leftLoop.scrollHeight;
const offsetBoundary = 200; //the offset from the borders at which the element reordering event is triggered
const lastScrollPos = new WeakMap();
const linkedLoops = new Map([
[leftLoop, rightLoop],
[rightLoop, leftLoop]
]);
let scrollLockElement = null;
let scrollLockTimeout = null;
// the function sets handlers to scrolling for infinite scrolling
function infiniteScrollHandler(loop) {
const virtualLoop = Array.from(loop.children);
virtualLoop.forEach(
(el) => (el.style.top = scrollHeight / 2 + el.offsetHeight + "px")
);
loop.addEventListener("scroll", () => {
if (virtualLoop.length < 2) return; // not enough items to scroll
const topBound = loop.scrollTop;
const bottomBound = loop.scrollTop + loop.offsetHeight;
const firstEl = virtualLoop[0];
const lastEl = virtualLoop[virtualLoop.length - 1];
if (firstEl.offsetTop >= topBound - offsetBoundary) {
lastEl.style.top = firstEl.offsetTop - lastEl.offsetHeight + "px";
virtualLoop.unshift(lastEl);
virtualLoop.pop();
} else if (
lastEl.offsetTop + lastEl.offsetHeight <
bottomBound + offsetBoundary
) {
firstEl.style.top = lastEl.offsetTop + lastEl.offsetHeight + "px";
virtualLoop.push(firstEl);
virtualLoop.shift();
}
});
}
// the function sets handlers to scrolling for reverse interaction with the linked loop
function reverseLinkLoopHandler(loop) {
loop.addEventListener("scroll", () => {
const delta = lastScrollPos.get(loop) - loop.scrollTop;
lastScrollPos.set(loop, loop.scrollTop);
// this is blocked to prevent deadlock when events of two blocks are called each other.
{
if (scrollLockElement !== null && scrollLockElement !== loop)
return;
scrollLockElement = loop;
clearTimeout(scrollLockTimeout);
scrollLockTimeout = setTimeout(
() => (scrollLockElement = null),
300
);
}
linkedLoops
.get(loop)
.scrollTo(0, linkedLoops.get(loop).scrollTop + delta);
});
}
// set scroll handlers on all loops
linkedLoops.forEach((loop) => {
infiniteScrollHandler(loop);
loop.scrollTo(0, scrollHeight / 2);
lastScrollPos.set(loop, scrollHeight / 2);
reverseLinkLoopHandler(loop);
});
/* Hide Scroll Bars */
::-webkit-scrollbar {
display: none;
}
html,
body {
margin: 0;
padding: 0;
-ms-overflow-style: none;
scrollbar-width: none;
}
/* Content will be in these eventually */
.bar-left,
.bar-right {
border-right: 2px solid black;
box-sizing: border-box;
height: 100vh;
position: fixed;
top: 0;
left: 0;
width: 48px;
z-index: 10000;
}
.bar-right {
border: none;
border-left: 2px solid black;
left: auto;
right: 0;
}
/* Split Loop */
.split-loop {
margin-left: 24px;
}
.split-loop__item {
background: white;
overflow: hidden;
}
.project {
box-sizing: border-box;
border-bottom: 2px solid black;
padding: 24px 24px 0;
width: 100%;
}
.project__media {
margin-bottom: 24px;
}
.project__img {
border: 2px solid black;
width: 100%;
max-width: 100%;
}
.project__title {
font-family: Arial;
font-size: 12px;
margin-bottom: 24px;
}
/* Tablet View */
#media screen and (min-width: 400px) {
.split-loop {
height: 100vh;
position: relative;
margin: 0 48px;
}
.split-loop__left {
border-right: 2px solid black;
box-sizing: border-box;
width: 50%;
}
.split-loop__right {
position: fixed;
right: 24px;
bottom: 0;
width: calc(50% - 48px);
}
.split-loop__item {
display: flex;
flex-flow: column;
height: 50vh;
}
.project__media {
display: flex;
flex-grow: 1;
align-items: center;
justify-content: center;
overflow: hidden;
margin-bottom: 24px;
}
.project__img {
box-sizing: border-box;
display: block;
margin-bottom: 0;
width: auto;
max-width: 100%;
height: 100%;
max-height: 100%;
object-fit: contain;
overflow: hidden;
}
/* Split Loop */
.split-loop {
position: relative;
margin: 0 48px;
}
.split-loop__left {
width: 50%;
overflow: auto;
position: relative;
max-height: 100vh;
}
.split-loop__right:before,
.split-loop__left:before {
display: block;
content: "";
z-index: -1;
height: 9999999px;
}
.split-loop__right {
box-sizing: border-box;
position: fixed;
right: 48px;
bottom: 0;
z-index: 5;
width: calc(50% - 48px);
overflow: auto;
max-height: 100vh;
}
.project {
box-sizing: border-box;
border-bottom: 2px solid black;
padding: 24px 24px 0;
position: absolute;
}
}
#media screen and (min-width: 600px) {
.split-loop__item {
height: 100vh;
}
}
<header class="bar-left"></header>
<div class="bar-right"></div>
<div class="split-loop" role="main">
<div class="split-loop__left">
<div class="split-loop__item project">
<div class="project__media">
<img src="https://www.fillmurray.com/g/600/800" alt="" class="project__img" />
</div>
<div class="project__copy">
<h2 class="project__title">Project Left #1</h2>
</div>
</div>
<div class="split-loop__item project">
<div class="project__media">
<img src="https://www.fillmurray.com/600/800" alt="" class="project__img" />
</div>
<div class="project__copy">
<h2 class="project__title">Project Left #2</h2>
</div>
</div>
<div class="split-loop__item project">
<div class="project__media">
<img src="https://www.fillmurray.com/g/600/800" alt="" class="project__img" />
</div>
<div class="project__copy">
<h2 class="project__title">Project Left #3</h2>
</div>
</div>
<div class="split-loop__item project">
<div class="project__media">
<img src="https://www.fillmurray.com/600/800" alt="" class="project__img" />
</div>
<div class="project__copy">
<h2 class="project__title">Project Left #4</h2>
</div>
</div>
</div>
<div class="split-loop__right">
<div class="split-loop__item project">
<div class="project__media">
<img src="https://www.fillmurray.com/600/800" alt="" class="project__img" />
</div>
<div class="project__copy">
<h2 class="project__title">Project Right #1</h2>
</div>
</div>
<div class="split-loop__item project">
<div class="project__media">
<img src="https://www.fillmurray.com/g/600/800" alt="" class="project__img" />
</div>
<div class="project__copy">
<h2 class="project__title">Project Right #2</h2>
</div>
</div>
<div class="split-loop__item project">
<div class="project__media">
<img src="https://www.fillmurray.com/600/800" alt="" class="project__img" />
</div>
<div class="project__copy">
<h2 class="project__title">Project Right #3</h2>
</div>
</div>
<div class="split-loop__item project">
<div class="project__media">
<img src="https://www.fillmurray.com/g/600/800" alt="" class="project__img" />
</div>
<div class="project__copy">
<h2 class="project__title">Project Right #4</h2>
</div>
</div>
</div>
</div>
I came across this website's work page and would like to recreate the xray effect of each of the card element.
Here's my code for the xray effect: https://codepen.io/carljustineoyales/pen/yLMEVYd
HTML
<section class="banner">
<h1>this is a banner page</h1>
</section>
<section class="projects" id="projects">
<div class="cardlist" >
<div class="cardlist__grid" >
<div class="card" id="card" onmouseover="setSize()" onmouseout="resetSize()">
<div class="card__category">
category
</div>
<div class="card__thumbnail">
</div>
<div class="card__info">
<div class="card__title">title</div>
<div class="card__date">date</div>
</div>
</div>
<div class="card" id="card">
<div class="card__category">
category
</div>
<div class="card__thumbnail">
</div>
<div class="card__info">
<div class="card__title">title</div>
<div class="card__date">date</div>
</div>
</div>
</div>
</div>
<div class="cardlist--skeleton" id="skeleton">
<div class="cardlist--skeleton--bg"></div>
<div class="cardlist__grid">
<div class="card">
<div class="card__category">
category
</div>
<div class="card__thumbnail card__thumbnail--black">
</div>
<div class="card__info">
<div class="card__title">title</div>
<div class="card__date">date</div>
</div>
</div>
<div class="card">
<div class="card__category">
category
</div>
<div class="card__thumbnail card__thumbnail--black">
</div>
<div class="card__info">
<div class="card__title">title</div>
<div class="card__date">date</div>
</div>
</div>
</div>
</div>
</section>
</body>
SCSS
* {
margin: 0;
padding: 0;
}
.banner {
height: 100vh;
}
.projects {
max-width: 1440px;
width: 100%;
margin: 100px auto;
// padding: 100px 0;
position: relative;
}
.cardlist {
width: 100%;
color: #000;
&__grid {
display: flex;
flex-direction: row;
justify-content: space-between;
}
&--skeleton {
--x: 0;
--y: 0;
--size: 0px;
clip-path: circle(var(--size) at var(--x) var(--y));
user-select: none;
pointer-events: none;
// clip-path: circle(100px at 0 0);
// clip-path: circle(300px at 0% 0%);
transition: clip-path 0.1s ease;
&--bg {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: #838383;
z-index: -1;
}
width: 100%;
position: absolute;
top: 0;
left: 0;
color: #fff;
z-index: 1;
background-color: #838383;
}
}
.card {
padding: 50px;
&__thumbnail {
width: 500px;
height: 644px;
background-color: #838383;
&--black {
background-color: #000;
}
}
}
JS
let mouseX=0
let mouseY=0
let size = 0;
const projects = document.querySelector('#projects');
function setSize() {
size = 200
skeleton.style.setProperty('--size', size + "px");
}
function resetSize() {
size = 0
skeleton.style.setProperty('--size', size + "px");
}
function updateCoordinates(event) {
mouseX = event.pageX - projects.offsetLeft ;
mouseY = event.pageY - projects.offsetTop ;
skeleton.style.setProperty('--x', mouseX + "px");
skeleton.style.setProperty('--y', mouseY+ "px");
}
The problem is that I can't seem to find a solution for the updating cursor position while scrolling, also the hover animation became laggy when you open the console. Is there a way to update the cursor position on scroll and why the animation became laggy when the console is open.
I'm trying to make an image gallery with HTML, CSS and JS. The CSS works but there is a problem with the JS. I've made it so you can either click on an image or click on a button to see all of the images in order. But if I click on the third or fourth image and click the L button (stands for LEFT) it jumps from that image to the first image. For some reason it just doesn't want to show the second image.
I've been trying to fix this for hours and it still doesn't work as it should.
var num = 0;
function elementID(indexes) {
var index = $(".images").index(indexes);
var num = index;
}
function myFunction(imgs) {
var expandImg = document.getElementById("expandedImg");
var imgText = document.getElementById("imgtext");
expandImg.src = imgs.src;
expandImg.parentElement.style.display = "block";
}
function right() {
if (num >= document.getElementsByClassName('images').length - 1) {
num = document.getElementsByClassName('images').length - 1;
} else {
num++;
}
var expandImg2 = document.getElementById("expandedImg");
var image = document.getElementsByClassName('images')[num];
expandImg2.src = image.src;
}
function left() {
if (num <= 0) {
num++;
return false;
} else {
num--;
}
var expandImg2 = document.getElementById("expandedImg");
var image = document.getElementsByClassName('images')[num];
expandImg2.src = image.src;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: Arial;
}
/* The grid: Four equal columns that floats next to each other */
.column {
float: left;
width: 25%;
padding: 10px;
}
/* Style the images inside the grid */
.column img {
opacity: 0.8;
cursor: pointer;
}
.column img:hover {
opacity: 1;
}
/* Clear floats after the columns */
.row:after {
content: "";
display: table;
clear: both;
}
/* The expanding image container */
.container {
position: relative;
display: none;
}
/* Expanding image text */
#imgtext {
position: absolute;
bottom: 15px;
left: 15px;
color: white;
font-size: 20px;
}
/* Closable button inside the expanded image */
.closebtn {
position: absolute;
top: 10px;
right: 15px;
color: white;
font-size: 35px;
cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div style="text-align:center">
<h2>Tabbed Image Gallery</h2>
<p><a onclick="left();" id="left">L</a> | <a onclick="right();" id="right">R</a>
</div>
<!-- The four columns -->
<div class="row">
<div class="column">
<img src="https://www.w3schools.com/howto/img_nature.jpg" alt="Nature" style="width:100%" class="images" onclick="myFunction(this);elementID(this);">
</div>
<div class="column">
<img src="https://www.w3schools.com/howto/img_snow.jpg" alt="Snow" style="width:100%" class="images" onclick="myFunction(this);elementID(this);">
</div>
<div class="column">
<img src="https://www.w3schools.com/howto/img_mountains.jpg" alt="Mountains" style="width:100%" class="images" onclick="myFunction(this);elementID(this);">
</div>
<div class="column">
<img src="https://www.w3schools.com/howto/img_lights.jpg" alt="Lights" style="width:100%" class="images" onclick="myFunction(this);elementID(this);">
</div>
</div>
<div class="container">
<span onclick="this.parentElement.style.display='none'" class="closebtn">×</span>
<img id="expandedImg" style="width:100%">
<div id="imgtext"></div>
</div>
Try this solution using the next() and prev() from jQuery.
var currentEl; // track current el
$(document).ready(() => {
$('.column').on('click', function() { // bind clicks
currentEl = this;
addImage($(this).find('img'));
});
$('.closebtn').on('click', function() { // bind clicks to close button
currentEl = undefined; // either you can do this to reset the flow, or comment to maintain the flow
});
});
function addImage(img) {
var expandImg = document.getElementById("expandedImg");
var imgText = document.getElementById("imgtext");
expandImg.src = img[0].src;
expandImg.parentElement.style.display = "block";
}
function right() { // jump to next
var next = currentEl ? $(currentEl).next() : $('.column').first();
if (next.length > 0) {
addImage($(next).find('img'));
currentEl = next;
}
}
function left() { // jump to prev
var prev = currentEl ? $(currentEl).prev() : $('.column').first();
if (prev.length > 0) {
addImage($(prev).find('img'));
currentEl = prev;
}
}
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: Arial;
}
/* The grid: Four equal columns that floats next to each other */
.column {
float: left;
width: 25%;
padding: 10px;
}
/* Style the images inside the grid */
.column img {
opacity: 0.8;
cursor: pointer;
}
.column img:hover {
opacity: 1;
}
/* Clear floats after the columns */
.row:after {
content: "";
display: table;
clear: both;
}
/* The expanding image container */
.container {
position: relative;
display: none;
}
/* Expanding image text */
#imgtext {
position: absolute;
bottom: 15px;
left: 15px;
color: white;
font-size: 20px;
}
/* Closable button inside the expanded image */
.closebtn {
position: absolute;
top: 10px;
right: 15px;
color: white;
font-size: 35px;
cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div style="text-align:center">
<h2>Tabbed Image Gallery</h2>
<p><a onclick="left();" id="left">L</a> | <a onclick="right();" id="right">R</a>
</div>
<!-- The four columns -->
<div class="row">
<div class="column">
<img src="https://www.w3schools.com/howto/img_nature.jpg" alt="Nature" style="width:100%" class="images">
</div>
<div class="column">
<img src="https://www.w3schools.com/howto/img_snow.jpg" alt="Snow" style="width:100%" class="images">
</div>
<div class="column">
<img src="https://www.w3schools.com/howto/img_mountains.jpg" alt="Mountains" style="width:100%" class="images">
</div>
<div class="column">
<img src="https://www.w3schools.com/howto/img_lights.jpg" alt="Lights" style="width:100%" class="images">
</div>
</div>
<div class="container">
<span onclick="this.parentElement.style.display='none'" class="closebtn">×</span>
<img id="expandedImg" style="width:100%">
<div id="imgtext"></div>
</div>
I saw this cool scrolling effect online...
Where the image blends with the next image when scrolling through sections. I've been trying to reproduce it, but I can't seem to figure it out?
How can I create this effect on the web?
Here is the link to where I saw the effect... http://readingbuddysoftware.com/how-it-works/
I've tried using position: fixed on the screenshots with the z-index of the section higher then the image, but the last screenshot is always on the top.
Any ideas?
Update: For various reasons (including placement, using slants...), I can't use the background-image css solution. I need a solution for using the <img> element.
This can be done using background-attchement:fixed and two similar images.
Here is a simple example:
body {
min-height:200vh;
margin:0;
background:url(https://picsum.photos/id/1069/150/150?grayscale) 20px 20px no-repeat;
background-attachment:fixed;
}
.box {
margin-top:220px;
height:200px;
background:url(https://picsum.photos/id/1069/150/150) 20px 20px no-repeat,
grey;
background-attachment:fixed;
}
<div class="box">
</div>
That you can easily scale with many images:
body {
min-height:250vh;
margin:0;
background:url(https://picsum.photos/id/1069/150/150?grayscale) 50px 50px/auto no-repeat;
background-attachment:fixed;
}
.box {
height:200px;
background:url(https://picsum.photos/id/1069/150/150) 50px 50px/auto no-repeat,
grey;
background-attachment:fixed;
}
.box:first-child {
margin-top:200px;
}
<div class="box">
</div>
<div class="box" style="background-image:url(https://picsum.photos/id/11/150/150);background-color:yellow">
</div>
<div class="box" style="background-image:url(https://picsum.photos/id/106/150/150);background-color:pink">
</div>
You can also consider the use of img and position:fixed but you will need some trick to hide the overflow using clip-path
body {
min-height: 250vh;
margin: 0;
padding-top: 100px;
}
img {
position: fixed;
top: 50px;
left: 50px;
}
.box {
height: 200px;
background: grey;
clip-path: inset(0);
}
<div class="box">
<img src="https://picsum.photos/id/1074/200/120?grayscale">
</div>
<div class="box" style="background-color:red;">
<img src="https://picsum.photos/id/1074/200/120">
</div>
<div class="box" style="background-color:yellow;">
<img src="https://picsum.photos/id/1024/200/120?grayscale">
</div>
<div class="box" style="background-color:pink;">
<img src="https://picsum.photos/id/1024/200/120">
</div>
Or using mask
body {
min-height: 250vh;
margin: 0;
padding-top: 100px;
}
img {
position: fixed;
top: 50px;
left: 50px;
}
.box {
height: 200px;
background: grey;
-webkit-mask:linear-gradient(#fff,#fff);
mask:linear-gradient(#fff,#fff);
}
<div class="box">
<img src="https://picsum.photos/id/1074/200/120?grayscale">
</div>
<div class="box" style="background-color:red;">
<img src="https://picsum.photos/id/1074/200/120">
</div>
<div class="box" style="background-color:yellow;">
<img src="https://picsum.photos/id/1024/200/120?grayscale">
</div>
<div class="box" style="background-color:pink;">
<img src="https://picsum.photos/id/1024/200/120">
</div>
For better support, here is a similar idea with some JS to avoid the use of clip-path or mask
I will update the position of the image using a CSS variables but you can easily do without:
window.onscroll = function() {
var scroll = window.scrollY || window.scrollTop || document.getElementsByTagName("html")[0].scrollTop;
document.documentElement.style.setProperty('--scroll-var', scroll+"px");
}
:root {
--scroll-var: 0px;
}
body {
min-height: 150vh;
margin: 0;
}
img {
position: fixed;
top: 20px;
left: 20px;
}
.box {
margin-top: 220px;
height: 200px;
background: grey;
position: relative;
overflow: hidden;
}
.box img {
top: calc(-220px + 20px + var(--scroll-var));
/* margin of box + top of the other image + scroll*/
position: absolute;
}
<img src="https://picsum.photos/id/1069/150/150?grayscale">
<div class="box">
<img src="https://picsum.photos/id/1069/150/150">
</div>
With many images:
window.onscroll = function() {
var scroll = window.scrollY || window.scrollTop || document.getElementsByTagName("html")[0].scrollTop;
document.documentElement.style.setProperty('--scroll-var', scroll+"px");
}
:root {
--scroll-var: 0px;
}
body {
min-height: 250vh;
margin: 0;
padding-top:200px;
}
img {
position: fixed;
top: 50px;
left: 50px;
}
.box {
height: 200px;
background: grey;
position: relative;
overflow: hidden;
}
img.f1 {
top: calc(-200px + 50px + var(--scroll-var));
position: absolute;
}
img.f2 {
top: calc(-400px + 50px + var(--scroll-var));
position: absolute;
}
img.f3 {
top: calc(-600px + 50px + var(--scroll-var));
position: absolute;
}
<img src="https://picsum.photos/id/1069/100/100?grayscale">
<div class="box">
<img class="f1" src="https://picsum.photos/id/1069/100/100">
</div>
<div class="box" style="background-color:yellow;">
<img class="f2" src="https://picsum.photos/id/107/100/100">
</div>
<div class="box" style="background-color:pink;">
<img class="f3" src="https://picsum.photos/id/1072/100/100">
</div>
I have problem with canvas tag. I need to append it into parent div. But when I set precise dimensions of parent and embed canvas tag, I get scrollbars. When I do same think with div, it works good. Here is fiddle:
https://jsfiddle.net/57yovrkx/4/
and here is code:
$(function() {
var content1 = $('#content1');
var div = $('<div/>', {width: content1[0].clientWidth, height: content1[0].clientHeight});
content1.append(div);
var content2 = $('#content2');
var canvas = $('<canvas/>', {width: content2[0].clientWidth, height: content2[0].clientHeight});
content2.append(canvas);
})
* {
box-sizing: border-box;
border: 0;
margin: 0;
padding: 0;
}
#wrap1, #wrap2 {
display: flex;
flex-direction: column;
position: absolute;
left: 0;
right: 0;
overflow: auto;
}
#wrap1 {
top: 0;
bottom: 50%;
}
#wrap2 {
top: 50%;
bottom: 0;
}
.header {
flex: 0 0 2rem;
background: darkgrey;
}
#content1, #content2 {
flex: 1;
}
#content1 {
background: lightblue;
}
#content2 {
background: lightgreen;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="wrap1">
<div class="header">
Some header
</div>
<div id="content1">
</div>
</div>
<div id="wrap2">
<div class="header">
Some header
</div>
<div id="content2">
</div>
</div>
Does anybody knows why?
Setting canvas.style.height = '100%'; before you append the canvas seems to do the trick.
https://stackoverflow.com/a/10215724/1482623