I have written the following code to scroll an element 20 more pixels to the right.
const button = document.getElementById('slide');
button.onclick = function () {
document.getElementById('container').scrollLeft += 20;
};
How can I make the scrolling smooth? I have tried using Element#scroll like so:
const button = document.getElementById('slide');
button.onclick = function () {
document.getElementById('container').scroll({
left: += 20,
behavior: smooth
});
};
Am I able to do this?
You can use Element#scrollBy to scroll a certain amount from the current position.
button.onclick = function () {
document.getElementById('container').scrollBy({
left: 20,
behavior: 'smooth'
});
};
Is this what you are looking for?
From MDN:
scrollBy() scrolls by a particular amount, whereas scroll() scrolls to an absolute position in the document.
https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollBy
const container = document.querySelector("#container");
const button = document.querySelector("#btnScroll");
button.addEventListener('click', e => {
container.scrollBy({
left: 200,
behavior: 'smooth'
});
});
#container {
position: relative;
max-width: 200px;
overflow-x: scroll;
display: flex;
margin: 20px;
}
img {
display: inline-block
}
<div id="container">
<img src="https://dummyimage.com/200x100/000/fff">
<img src="https://dummyimage.com/200x100/0f0/000">
<img src="https://dummyimage.com/200x100/00f/fff">
<img src="https://dummyimage.com/200x100/f00/fff">
</div>
<button id="btnScroll">Scroll 200px</button>
Related
What's wrong with my code? scrollTo() goes to the wrong position when I click and anchor with href value using hash # (div element ID).
This is my code, I just want to scroll to the comment element, but still overlap on the fixed header (bootstrap 5 fixed header).
if (document.querySelectorAll('a').length) {
document.querySelectorAll('a').forEach( anchor => {
anchor.addEventListener('click', event => {
let URL = event.target.href.split('#');
if (typeof URL[1] != undefined) {
let element = document.getElementById(URL[1]);
let offset = element.offsetTop;
let navigation = document.getElementById('main-navigation').clientHeight
let scroll = offset - navigation;
window.scrollTo(0, scroll);
}
});
});
}
Anyone can help me?
Call event.preventDefault() in the click handler, otherwise after your call to scrollTo, the page's hash will change, with an automatic scroll to the anchored element overriding yours.
document.querySelectorAll('a').forEach( anchor => {
anchor.addEventListener('click', event => {
let URL = event.target.href.split('#');
if (typeof URL[1] != undefined) {
let element = document.getElementById(URL[1]);
let offset = element.offsetTop;
let navigation = document.querySelector('.over').clientHeight
let scroll = offset - navigation;
window.scrollTo(0, scroll);
event.preventDefault(); // avoid internal scroll to anchor
}
});
});
.over {
height: 50px;
background: salmon;
position: sticky;
top: 0;
}
#foo {
margin-top: 250vh;
height: 250vh;
}
#foo
<div class="over"></div>
<div id="foo">Target element</div>
You can achieve that by using the scrollIntoView() function. see the below example. you have to target the element to scroll:
let i = 0;
function myFunction() {
if(i === 0){
const elmnt = document.getElementById("content");
elmnt.scrollIntoView();
i += 1
}
else {
const elmnt = document.getElementById("content2");
elmnt.scrollIntoView();
}
}
#myDIV {
height: 250px;
width: 250px;
overflow: auto;
background: green;
}
#content {
margin:500px;
height: 800px;
width: 2000px;
background-color: coral;
}
#content2 {
margin:500px;
height: 800px;
width: 2000px;
background-color: red;
}
<p>Click the button to scroll to section.</p>
<button onclick="myFunction()">Scroll</button>
<div id="myDIV">
<div id="content">
Some text inside an element.
</div>
<div id="content2">
Some text inside an element.
</div>
</div>
Most importantly you need to stop the default behavior. When an internal link is clicked the default action is to jump to that link. You need to override that.
Next, we can make a couple of little tweaks. First, only select internal links with an attribute selector that selects a tags where the href start with "#". Next, instead of splitting the url from the href, grab the raw value directly from the attribute.
//Get internal links
document.querySelectorAll("a[href^='#']").forEach(function(el) {
el.addEventListener("click", function(e) {
//Stops the inbuild scroll
e.preventDefault();
//Get the id straight from the attribute
let selector = this.getAttribute("href");
//Get the target element
let element = document.querySelector(selector);
//you know the rest
let offset = element.offsetTop;
let navigation = document.getElementById('main-navigation').clientHeight
let scroll = offset - navigation;
window.scrollTo(0, scroll);
});
});
/*CSS Purely for demo purposes.*/
.fixed-top {
background-color: #EEE;
padding: 15px;
}
article:first-of-type{
margin-top:90px;
}
article {
min-height: 50vh;
border-bottom: 1px solid black;
}
nav {
background-color: #ECECEC;
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<div class="fixed-top" id="main-navigation">Some Top Stuff
<nav>
Article 1
Article 2
Article 3
</nav>
</div>
<article id="art1">
<h1>Article 1</h1>
</article>
<article id="art2">
<h1>Article 2</h1>
</article>
<article id="art3">
<h1>Article 3</h1>
</article>
I'm trying to figure out a better way to scroll the images that are farthest to the left and right into view if they are partially out of the parent div when they are clicked.
Would anyone know how I can better detect when they are partially out of view via JS?
If there a better way to go about sliding the available images into view?
Trying to get a suitable method that is not viewport width dependant to work for all the device screens.
const available_images_div = document.getElementById('available-images-div');
available_images_div.addEventListener('click', function(e) {
if (e.target.nodeName == 'IMG') {
const selected_image = e.target;
document.getElementById('active-img').src = selected_image.src;
let added_offset = selected_image.offsetLeft + selected_image.offsetWidth;
let subtracted_offset = selected_image.offsetLeft - selected_image.offsetWidth;
// Check if clicked image is partially or fully it's container's width on the right side
if (added_offset > available_images_div.clientWidth) {
// If the clicked image has an image to the right of it scroll that image into view
if (selected_image.nextElementSibling) selected_image.nextElementSibling.scrollIntoView({
behavior: "smooth"
});
// else scroll the clicked image into view
else selected_image.scrollIntoView({
behavior: "smooth"
});
}
// Check if the container was scrolled and if the clicked image is the one furthest to the left of the containers view port
if (available_images_div.scrollLeft > 0 && subtracted_offset < available_images_div.scrollLeft) {
// If the clicked image has an image to the left of it scroll that image into view
if (selected_image.previousElementSibling) selected_image.previousElementSibling.scrollIntoView({
behavior: "smooth"
});
// else scroll the clicked image into view
else selected_image.scrollIntoView({
behavior: "smooth"
});
}
}
});
#store-img-inner-div {
width: 500px;
}
#store-img-inner-div img {
width: 100%;
height: 100%;
border-radius: 5px;
border: 1px solid #ccc;
}
#available-images-div {
display: flex;
margin-top: 3rem;
overflow-x: hidden;
position: relative;
}
#available-images-div img {
width: 20%;
cursor: pointer;
}
#available-images-div img:not(:last-of-type) {
margin-right: 10px;
}
<div id="store-img-inner-div">
<div id="active-image-div">
<img id="active-img" src="https://source.unsplash.com/U2BI3GMnSSE/1600x900">
</div>
<div id="available-images-div">
<img src="https://source.unsplash.com/U2BI3GMnSSE/1600x900">
<img src="https://source.unsplash.com/wawEfYdpkag/1600x900">
<img src="https://source.unsplash.com/rRiAzFkJPMo/1600x900">
<img src="https://source.unsplash.com/rSpMla5RItA/1600x900">
<img src="https://source.unsplash.com/bIZJRVBLfOM/1600x900">
<img src="https://source.unsplash.com/jM8HUcJtXB0/1600x900">
</div>
</div>
get parent left
get parent width
get target left
get target width
const x = parent.width + parent.left - (target.width + target.left)
if(x > 0) {
console.log("passed");
} else if(x == 0) {
console.log("on line");
} else if( x < 0 ) {
console.log(" no ")
}
getting Element offset and width and height:
Element.offsetLeft || Element.getBoundingClientRect().x
sometimes one of these works if you want you can use jQuery one: ( for top and left )
if ( !elem.getClientRects().length ) {
return { top: 0, left: 0 };
}
// Get document-relative position by adding viewport scroll to viewport-relative gBCR
rect = elem.getBoundingClientRect();
win = elem.ownerDocument.defaultView;
return {
top: rect.top + win.pageYOffset,
left: rect.left + win.pageXOffset
};
for height and width you can use Element.getBoundingClientRect().width/height || Element.offsetWidth/offsetHeight
this is up to you to use offset or getBounding
I am creating div dynamically inside a div with negative margins, but my div outer scroller is not activating to scroll and see those dynamically created div.
HTML code
<html>
<body align="center">
<div id "TC" class = "Tile_container">
</div>
</body>
</html>
Here i am creating tile container with x scroll and y scroll.
CSS code
.Tile_container
{
height: 500px;
width: 500px;
background-color: lightgray;
position: relative;
overflow-x: scroll;
overflow-y: scroll;
}
JS code
$(document).ready(function () {
var tileContainer = document.getElementsByClassName("Tile_container")[0];
var newTile = document.createElement("div");
newTile.setAttribute("class", "PlayerTile");
var strTop = "" + (-100) + "px";
var strLeft = ""+ (-100) + "px";
newTile.style.left = strLeft;
newTile.style.top = strTop;
tileContainer.appendChild(newTile);
});
My scrollers are activating when i create inner div at position more than the Tile_container div dimension.
can anyone please tell how to scroll and see those created div. in that div i have other functionalities to add.
You have moved the PlayerTile off the top and left of the parent div.
overflow-x and overflow-y will not scroll for contents that are off the top or left.
Scrolling to the right and down works fine.
var tileContainer = document.getElementById("TC");
window.onload = (function() {
var newTile = document.createElement("div");
newTile.id = 'newtile';
newTile.setAttribute("class", "PlayerTile");
tileContainer.appendChild(newTile);
});
function moveTile(direction, value) {
const tile = document.getElementById('newtile');
if (direction === 'horizontal') {
tile.style.left =
Number(tile.style.left.replace('px', '')) +
value + 'px';
} else {
tile.style.top =
Number(tile.style.top.replace('px', '')) +
value + 'px';
}
}
const moveRight = () => moveTile('horizontal', 60);
const moveLeft = () => moveTile('horizontal', -60);
const moveUp = () => moveTile('vertical', -12);
const moveDown = () => moveTile('vertical', 12);
function reset() {
const tile = document.getElementById('newtile');
tile.style.left = tile.style.top = '12px';
}
.Tile_container {
height: 140px;
width: 90%;
background-color: lightgray;
position: relative;
overflow-x: scroll;
overflow-y: scroll;
}
.PlayerTile {
height: 100px;
width: 200px;
background-color: dodgerBlue;
position: absolute;
top: 12px;
left: 12px;
}
Move Tile: <button onclick="moveRight()">Right</button>
<button onclick="moveLeft()">Left</button>
<button onclick="moveUp()">Up</button>
<button onclick="moveDown()">Down</button>
<button onclick="reset()">Reset</button><br/>
<div id="TC" class="Tile_container"></div>
When I click on <a class="Navigation" id="WorldHeader" href="#WorldTitle">Go to World</a>, my window put directly the div with the id directly on top. Is there a way to offset the window position when I click on the tag? My header is hiding the content, but I want to keep it.
Solution
Assuming based on the JQuery tag that, and using the reference of #WebMarie, the following solution must help you:
$('#WorldHeader').on('click', function(event) {
event.preventDefault(); // Prevent the default <a> action.
let myOffset = 50; // Pixels.
let newScrollPosition = $("#WorldTitle").offset().top - myOffset;
$('html, body').scrollTop(newScrollPosition); // Set the current vertical position of the scroll bar.
});
With animation:
$('#WorldHeader').on('click', function(event) {
event.preventDefault();
let myOffset = 50; // Pixels.
let animationDuration = 1000; // Miliseconds.
let newScrollPosition = $("#WorldTitle").offset().top - myOffset;
$('html, body').animate({
scrollTop: newScrollPosition // Set the current vertical position of the scroll bar.
}, animationDuration);
});
Example of use
$('#WorldHeader').on('click', function(event) {
event.preventDefault();
let myOffset = 50; // Pixels.
let animationDuration = 1000; // Miliseconds.
let newScrollPosition = $("#WorldTitle").offset().top - myOffset;
$('html, body').animate({
scrollTop: newScrollPosition // Set the current vertical position of the scroll bar.
}, animationDuration);
});
#WorldTitle {
margin: 20px 0;
width: 100%;
height: 150px;
background-color: red;
}
.blue {
width: 100%;
height: 500px;
background-color: blue;
}
.green {
width: 100%;
height: 500px;
background-color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<a class="Navigation" id="WorldHeader" href="#WorldTitle">Go to World</a>
<div class="blue"></div>
<div id="WorldTitle"></div>
<div class="green"></div>
I'm trying to resize my images for a slideshow. When I plug them into an array and code them into a slideshow, the cropping is kind of off. I tried using object-position in CSS but that changes all the images in one shot and what works for one image doensn't necessarily work for others.
Here is the HTML:
<container class="main-img-cont">
<img class="main-img" alt="">
</container>
Here is the CSS:
.main-img-cont {
width: 100%;
height: 650px;
display: flex;
img {
width: 100%;
object-fit: cover;
object-position: 0 30%;
} // closes img
} // closes .main-img
Javascript:
window.onload = () => {
var mainImg = document.querySelector('.main-img');
let slideshow = [
'../img/jevon_cochran_pelourinho.jpg',
'../img/me_in_Pernambues.JPG',
'../img/quibdo_boat_ride.jpg'
];
var index = 0;
var interval = 1000;
function slide() {
mainImg.src = slideshow[index];
index++;
if (index >= slideshow.length) {
index = 0;
}
}
setInterval(slide, interval);
}