so I've done this little automatic slideshow in Javascript/jQuery. It works really well however I cannot figure out how to scale it with screen size, make it liquid. It's currently optimized for 1920x1080.
I've tried assigning this value (document.body.style.width) to the width variable with no luck, tried using percentages for the images instead of pixels and also tried using a very hackish fix with media queries all to no avail.
If anyone has an idea on how I might accomplish this do tell(again, I need it to scale with the browser window), Anyway, here's the code:
<div class="slider">
<ul class="slides">
<li class="slide"><img src="index/showcase.png" alt="#"/></li>
<li class="slide"><img src="index/pic4.png" alt="#"/></li>
<li class="slide"><img src="index/pic3.png" alt="#"/></li>
<li class="slide"><img src="index/pic5.png" alt="#"/></li>
<li class="slide"><img src="index/pic6.png" alt="#"/></li>
</ul>
</div>
.slider {
width: 1920px;
height: 780px;
overflow: hidden;
}
.slider .slides {
display: block;
width: 9600px;
height: 780px;
margin: 0;
padding: 0;
}
.slider .slide {
float: left;
list-style-type: none;
width: 1920px;
height: 780px;
}
<script type="text/javascript">
var myInterval = setInterval(function() {
console.log(new Date());
}, 1000);
</script>
<script type="text/javascript">
$(function() {
//configuration
var width = 1920;
var animationSpeed = 1000;
var pause = 4000;
var currentSlide = 1;
//cache DOM
var $slider = $('.slider');
var $slideContainer = $slider.find('.slides');
var $slides = $slideContainer.find('.slide');
var interval;
function startSlider() {
interval = setInterval(function() {
$slideContainer.animate({'margin-left': '-='+width}, animationSpeed,
function(){
currentSlide++;
if (currentSlide === $slides.length) {
currentSlide = 1;
$slideContainer.css('margin-left', 0);
}
});
}, pause);
}
// function stopSlider() {
// clearInterval(interval);
//}
//$slider.on('mouseenter', startSlider).on('mouseleave', startSlider);
startSlider();
});
</script>
vw and vh may be what you are after. Instead of width: 20% or width: 550px, you do width: 100vw to be 100% of the viewport's width (vh is viewport height). Then it should resize as the viewport resizes.
Related
I am trying to create a script, that opens and closes the menu. the problem is that I need to figure out the element`s height while it-s height is set to 0 from css.
I come out with a really ugly solution, I wonder if there is a more elegant way to do this.
my solution is to set visibility to hidden, then set height to auto, then query the height, after that to set back the height, and visibility.
I need this for css animation, because css anim it is not working with height auto, and height 0px, I need to have the height in px.
this is my code:
document.getElementById('menu_button').onclick = function() {
if (document.getElementById('mobile-menu').style.height == '0px') {
document.getElementById('mobile-menu').style.visibility = 'hidden';
document.getElementById('mobile-menu').style.height = 'auto';
var MobileMenuHeight = document.getElementById('mobile-menu').clientHeight;
document.getElementById('mobile-menu').style.height = '0px';
document.getElementById('mobile-menu').style.visibility = 'visible';
setTimeout(() => { document.getElementById('mobile-menu').style.height = MobileMenuHeight + 'px'; }, 50);
} else {
document.getElementById('mobile-menu').style.height = "0px";
}
}
You can use getComputedStyle.
if (getComputedStyle(document.getElementById('mobile-menu')).height == '0px')
Finally I figured out a better and simple solution.
I just put the menu in a container with overflow: hidden and I scale the container, this way the menu itself can keep it's height.
function toggleMobileMenu() {
document.getElementById('menu-button').onclick = function() {
var MobileMenuHeight = document.getElementById('mobile-menu').clientHeight;
var MenuContainerHeight = document.getElementById('mobile-menu-container').clientHeight;
if (MenuContainerHeight == 0) {
document.getElementById('mobile-menu-container').style.height = MobileMenuHeight + 'px';
} else {
document.getElementById('mobile-menu-container').style.height = "0px";
}
}
}
document.onload = toggleMobileMenu();
#menu-button {
position: absolute;
width: 40px;
height: 40px;
right: 16px;
top: 60px;
z-index: 98;
}
#menu-button div {
width: 90%;
height: 6px;
margin: 6px auto;
background-color: #555;
border-radius: 3px;
}
.mobile-menu-container {
background: #ddd;
overflow: hidden;
height: 0;
transition: height 0.33s;
}
.mobile-menu {
background: #8888ff;
}
<html>
<head>
<meta charset = "UTF-8">
</head>
<body>
<div id="menu-button"><div></div><div></div><div></div></div>
<div id = "mobile-menu-container" class = "mobile-menu-container">
<div class = "mobile-menu" id="mobile-menu">
<div class="menu-container">
<ul>
<li>Menu item 1</li>
<li>Menu item 1</li>
<li>Menu item 1</li>
<li>Menu item 1</li>
<li>Menu item 1</li>
</ul>
</div>
</div>
</div>
</body>
I am creating a custom image slider with custom slide effect in jQuery which has both next & previous buttons and also slides automatically with 5 seconds timeout. Although it works nicely in a quick look but sometimes( I dont know exactly when, maybe when I press the buttons or if I leave it open for some time and minimize the window) the iterval bugs and the slides change after 1 second or less. Also when i press the button i tell it to 1) clear iterval 2) change slide 3) set interval again which means that after i change a slide with the button the timer is set to 5 seconds from the start but this is not happening all the times.Here is the code.
$(document).ready(function() {
'use strict';
var $carousel = $('.carousel');
var $nextBtn = $('#next');
var $prevBtn = $('#prev');
var animationSpeed = 1000;
var pause = 5000;
var interval;
function nextSlide() {
$('.carousel__list').animate({
left: '-200%'
}, 500, function() {
$('.carousel__list').css('left', '-100%');
$('.carousel__item').last().after($('.carousel__item').first());
});
}
function prevSlide() {
$('.carousel__list').animate({
left: '0%'
}, 400, function() {
$('.carousel__list').css('left', '-100%');
$('.carousel__item').first().before($('.carousel__item').last());
});
}
function startSlider() {
interval = setInterval(function() {
nextSlide();
}, pause);
}
function stopSlider() {
clearInterval(interval);
}
$carousel.on('mouseenter', stopSlider).on('mouseleave', startSlider);
startSlider();
$nextBtn.on('click', function() {
stopSlider();
nextSlide();
startSlider();
});
$prevBtn.on('click', function() {
stopSlider();
prevSlide();
startSlider();
});
});
*,
*::after,
*::before {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.carousel {
width: 100%;
height: 65vh;
overflow: hidden;
position: relative;
}
.carousel__list {
width: 400%;
height: 100%;
left: -100%;
position: relative;
list-style: none;
}
.carousel__item {
width: calc(100% / 4);
height: 100%;
float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="carousel">
<ul class="carousel__list">
<li class="carousel__item" style="background-color: red"></li>
<li class="carousel__item" style="background-color: green"></li>
<li class="carousel__item" style="background-color: blue"></li>
<li class="carousel__item" style="background-color: yellow"></li>
</ul>
</section>
<button id="prev">PREVIOUS</button>
<button id="next">NEXT</button>
And here is a codepen: https://codepen.io/anon/pen/erpyJj
You are creating more intervals than you think and you don't actually clear each one because you overwrite the interval variable and then you don't a have a reference to the previous intervals, which may still be active.
What you could do is put every interval you create in an array, then when you need to stop all intervals, iterate through that array, clear each interval and empty the array.
// ...
var intervals = [];
// ...
function stopSlider() {
console.log("stopSlider() intervals (Before clear): ", intervals);
intervals.forEach(function(interval) {
clearInterval(interval); // stop one interval
});
intervals = []; // clear the array
console.log("stopSlider() intervals (After clear): ", intervals);
}
Here is your demo with many console logs. You can see that it doesn't matter how much you click on any button, the slider only automatically slides every 5 s.
$(document).ready(function() {
"use strict";
//cache dom elements
var $carousel = $(".carousel");
var $nextBtn = $("#next");
var $prevBtn = $("#prev");
var animationSpeed = 1000;
var pause = 5000;
var intervals = [];
function nextSlide() {
console.log("nextSlide() intervals: ", intervals);
$(".carousel__list").animate({
left: "-200%"
}, 500, function() {
$(".carousel__list").css("left", "-100%");
$(".carousel__item")
.last()
.after($(".carousel__item").first());
});
}
function prevSlide() {
console.log("prevSlide() intervals: ", intervals);
$(".carousel__list").animate({
left: "0%"
}, 400, function() {
$(".carousel__list").css("left", "-100%");
$(".carousel__item")
.first()
.before($(".carousel__item").last());
});
}
function startSlider() {
console.log("startSlider() interval (BEFORE): ", intervals);
var interval = setInterval(function() {
nextSlide();
}, pause);
intervals.push(interval);
console.log("startSlider() interval (AFTER): ", intervals);
}
function stopSlider() {
console.log("stopSlider() intervals (Before clear): ", intervals);
intervals.forEach(function(interval) {
clearInterval(interval); // stop one interval
});
intervals = []; // clear the array
console.log("stopSlider() intervals (After clear): ", intervals);
}
$carousel.on("mouseenter", stopSlider).on("mouseleave", startSlider);
startSlider();
$nextBtn.on("click", function() {
stopSlider();
nextSlide();
startSlider();
});
$prevBtn.on("click", function() {
stopSlider();
prevSlide();
startSlider();
});
});
*,
*::after,
*::before {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.carousel {
width: 100%;
height: 20vh;
overflow: hidden;
position: relative;
}
.carousel__list {
width: 400%;
height: 100%;
left: -100%;
position: relative;
list-style: none;
}
.carousel__item {
width: calc(100% / 4);
height: 100%;
float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="carousel">
<ul class="carousel__list">
<li class="carousel__item" style="background-color: red"></li>
<li class="carousel__item" style="background-color: green"></li>
<li class="carousel__item" style="background-color: blue"></li>
<li class="carousel__item" style="background-color: yellow"></li>
</ul>
</section>
<button id="prev">PREVIOUS</button>
<button id="next">NEXT</button>
How to get the browser's width to use it as a VARIABLE?
I know about the #media. what I need is getting the width and do some calculation to it
I tried using jQuery, it works great if the browser's width is FIXED, but when I resize the browse window it doesn't work
here is what I want to do:
html
<section id="slider">
<div class="slides">
<div class="slide">
<h1>silde 1</h1>
<p>Lorem ipsum dolor</p>
</div>
<div class="slide">
<h1>silde 2</h1>
<p>Lorem ipsum dolor</p>
</div>
</div> </section>
SCSS
$browser-width: (BROWSER WIDTH HERE) * .75 ;
#slider {
overflow: hidden;
position: relative;
margin: auto;
width: $browser-width;
.slides {
display: block;
margin: 0;
padding: 0;
width: 6000px;
}
.slide {
width: $browser-width;
display: inline-block;
float: left;
text-align: center;
}
}
What I did as a temporary solution is this:
using jQuery:
$(document).ready(function(){
var width = $(window).width() * .75;
var $slider = $('#slider');
var $slideContainer = $slider.find('.slides');
var $slides = $slideContainer.find('.slide');
$slider.css("width", width);
$slides.css("width", width);
/* function to make the slider here */
});
width = 75% doesn't work nor does width = 75vw
Never mind I found the problem
vw is the answer, it didn't work because I made this mistake in my sliding function
'margin-left' : '-=' + width
what I needed to do was this:
'margin-left' : '-=' + width + "vw"
never forget the units in your code .. lesson learned
here is my sliding function to those interested:
'use strict';
$(document).ready(function(){
var width = 75;
var animationSpeed = 1000;
var pause = 1000;
var currentSlide = 1;
var $slider = $('#slider');
var $slideContainer = $slider.find('.slides');
var $slides = $slideContainer.find('.slide');
var interval;
function startSlider(){
interval = setInterval(function() {
$slideContainer.animate({'margin-left' : '-='+width + "vw"}, animationSpeed, function(){
currentSlide++;
if (currentSlide === $slides.length){
currentSlide = 1;
$slideContainer.css('margin-left', 0);
}
});
}, pause);
}
function stopSlider(){
clearInterval(interval);
}
$slider.on('mouseenter', stopSlider).on('mouseleave', startSlider);
startSlider();
});
I'm currently in the middle making my carousel responsive. So far I've managed to make it responsive only if the user resizes and refreshes browser only then it will resize programmatically. How can I make it resize without having to refresh the browser.
Update:
I tried working with the answers below. Currently it stays on a fixed value even if I resize browser. Inside my css there is no fixed value placed
$(document).ready(function() {
var sliderWidth = 0;
var sliderContainer = $('.slider-container');
var slider = $('.slider-container .slider');
var sliderItems = $('.slider li');
var sliderContainerWidth = sliderContainer.width();
sliderItems.width(sliderContainerWidth / 2);
$('.slider-container ul.slider').children().each(function() {
sliderWidth += $(this).outerWidth();
slider.width(sliderWidth + 1000);
});
$('.btns .prev').on('click', function() {
prevSlide();
})
function prevSlide() {
var sliderItemsWidth = sliderItems.width();
var leftIndent = parseInt($(sliderItems).css('left')) - sliderItemsWidth;
function animate() {
$('.slider-container .slider:not(:animated)').animate({
'left': leftIndent
}, 100)
}
animate();
}
})
.wrapper {
max-width: 1280px;
margin: 0 auto;
background-color: #ccc;
}
.wrapper .slider-container {
float: left;
position: relative;
overflow: hidden;
width: 100%;
background-color: beige;
}
.wrapper .slider-container .slider {
display: flex;
flex-wrap: wrap;
position: relative;
}
.wrapper .slider-container .slider li {
height: 300px;
background-color: #ccc;
position: relative;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div class="slider-container">
<ul class="slider">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<ul class="btns">
<li class="prev">prev</li>
<li class="next">next</li>
</ul>
</div>
</div>
As per my comments, you can put the resizing bits into a function and call that on window resize:
$(document).ready(function() {
var sliderContainer = $('.slider-container');
var slider = $('.slider-container .slider');
var sliderItems = $('.slider li');
function resize() {
var sliderWidth = 0;
var sliderContainerWidth = sliderContainer.width();
sliderItems.width(sliderContainerWidth / 2);
$('.slider-container ul.slider').children().each(function() {
sliderWidth += $(this).outerWidth();
slider.width(sliderWidth + 1000);
});
}
$('.btns .prev').on('click', function() {
prevSlide();
})
function prevSlide() {
var sliderItemsWidth = sliderItems.width();
var leftIndent = parseInt($(sliderItems).css('left')) - sliderItemsWidth;
function animate() {
$('.slider-container .slider:not(:animated)').animate({
'left': leftIndent
}, 100)
}
animate();
}
resize(); // call onload
$(window).on('resize', function () {
resize(); // call when browser is resized
});
})
If this is a duplicate apologies I could not find an answer.
I am making a Pure Javascript Slideshow and have nearly done it. However I am facing an issue i cannot seem to resolve.
I cannot get the images to fill the div with 100% width and 100% height. Which once done should slide all images separately, ultimately finishing my slideshow.
Steps taken to resolve:
I have played with the CSS, and changed the position styles between relative and absolute. I have added width:100%; to the divs. I have added in an extra style for the images - #slide li img {width:100%; height:100%}; Yet nothing seems to work. If #slide li img & #slide li & #slide all have width/height at 100% then the first image scales to 100% of the combined images width and height set in the Javascript, Which blows it way out of proportion and will only slide that one image.
I have tried setting the width/height separately in the javascript using document.getElementsByClassName, Yet it still does not fill the contaning div
Here is the code:
function Slide() {
ul = document.getElementById("slide");
liItems = ul.children;
liNumber = liItems.length;
imageNumber = 0;
sliderWidth = 0;
currImg = 0;
// Left + Right Arrows
leftArrow = document.getElementById("left");
rightArrow = document.getElementById("right");
for (i = 0; i < liNumber; i++) {
imageWidth = liItems[i].children[0].clientWidth;
sliderWidth += imageWidth;
imageNumber++;
}
// Set UL's Width as total width of all images in slider.
ul.style.width = parseInt(sliderWidth) + "px";
slider(ul);
function slider(ul) {
animate({
delay: 1000 / 60,
duration: 3000,
delta: function(p) {
return Math.max(0, -1 + 2 * p)
},
step: function(delta) {
ul.style.left = '-' + parseInt(currImg * imageWidth + delta * imageWidth) + "px";
},
callback: function() {
currImg++;
//Keep sliding if not last image
if (currImg < liNumber - 1) {
slider(ul);
}
// Slide back to first image, if last image
else {
leftPosition = (liNumber - 1) * imageWidth;
//after set seconds, call goback for first image
setTimeout(function() {
goBack(leftPosition)
}, 2000);
setTimeout(function() {
slider(ul)
}, 3000);
}
}
});
function goBack(leftPosition) {
currImg = 0;
setInterval(function() {
if (leftPosition >= 0) {
ul.style.left = '-' + parseInt(leftPosition) + "px";
leftPosition -= imageWidth;
}
}, 1000 / 60);
}
function animate(opts) {
start = new Date;
id = setInterval(function() {
timePassed = new Date - start;
progress = timePassed / opts.duration
if (progress > 1) {
progress = 1;
}
delta = opts.delta(progress);
opts.step(delta);
if (progress == 1) {
clearInterval(id);
opts.callback();
}
}, opts.delay || 1000 / 60);
}
}
}
window.onload = Slide;
#slidecontainer {
height: 100%;
width: 100%;
overflow: hidden;
}
#slide {
position: relative;
z-index: 0;
list-style-type: none;
padding: 0;
}
#slide li {
position: relative;
left: 0;
top: 4%;
margin: 0;
padding: 0;
float: left;
width: 25%;
/* Adjust this value within the range of images i.e 4 images = 25%, 5 images = 20% */
}
.slideimg {
width: 100%;
height: 100%;
}
<div id="slidecontainer">
<ul id="slide">
<li>
<img src="images/style.jpg" alt="1" class="slideimg" />
</li>
<li>
<img src="images/style1.jpg" alt="2" class="slideimg" />
</li>
<li>
<img src="images/style2.jpg" alt="3" class="slideimg" />
</li>
<li>
<img src="images/style3.jpg" alt="4" class="slideimg" />
</li>
</ul>
</div>
Please do not give a jquery solution, It needs to be Vanilla.
1. 100% height
If you want to scale things to 100% of the height of the window, you'll need to make sure enough (when using position: static) or all (when using position: relative) parent elements also use 100% of the height.
In a stack snippet, this means adding these rules to both html and body, and to all of your own elements.
2. 100% width
The width is a bit easier, because every display: block element will automatically fill up its parent. To be certain, you can just add a width: 100% rule to all of the previously mentioned elements.
The problem your css had, was that each float had a width of 25% relative to its parent, which only had a width of 100%. Changing this to 400% (the number of slides * 100), fixes the width.
Here's an example of just the full screen slides. Note:
I'd swap the tag and id selectors with class selectors if I were you
I'd use display: flex on the ul and flex-grow: 1 on the lis instead of float, but both will work.
html,
body,
#slidecontainer,
#slide,
li,
img {
width: 100%;
height: 100%;
}
* {
margin: 0;
padding: 0;
position: relative;
}
/* turn this rule on and scroll via js to slide */
#slidecontainer {
/* overflow-x: hidden; */
}
#slide {
width: 400%; /* (100 * slideCount) */
}
li {
float: left;
width: 25%; /* (100 / slideCount) */
list-style: none;
}
img {
display: block;
background: #efefef;
}
<div id="slidecontainer">
<ul id="slide">
<li>
<img src="images/style.jpg" alt="1" class="slideimg" />
</li>
<li>
<img src="images/style1.jpg" alt="2" class="slideimg" />
</li>
<li>
<img src="images/style2.jpg" alt="3" class="slideimg" />
</li>
<li>
<img src="images/style3.jpg" alt="4" class="slideimg" />
</li>
</ul>
</div>
Bonus: without javascript
Now, just for fun, here's an implementation without javascript :) It's quite some work to change the number of slides though, so I'd go with a hybrid approach or use a css pre-processor to generate the animation keyframes if I were you. (Only tested in chrome)
html, body, #slidecontainer {
width: 100%;
height: 100%;
overflow-x: hidden;
}
* {
padding: 0;
margin: 0;
position: relative;
box-sizing: border-box;
}
#slide {
position: relative;
width: 400%;
height: 100%;
display: flex;
animation-duration: 7s;
animation-name: slide;
animation-iteration-count: infinite;
}
#slide > li {
flex-grow: 1;
list-style: none;
}
.slideimg {
width: 100%;
height: 100%;
}
#keyframes slide {
0% {
transform: translate3d(0, 0, 0);
}
20% {
transform: translate3d(0, 0, 0);
}
25% {
transform: translate3d(-25%, 0, 0);
}
45% {
transform: translate3d(-25%, 0, 0);
}
50% {
transform: translate3d(-50%, 0, 0);
}
70% {
transform: translate3d(-50%, 0, 0);
}
75% {
transform: translate3d(-75%, 0, 0);
}
95% {
transform: translate3d(-75%, 0, 0);
}
}
<div id="slidecontainer">
<ul id="slide">
<li style="background: green;">
<img src="images/style.jpg" alt="1" class="slideimg" />
</li>
<li style="background: blue;">
<img src="images/style1.jpg" alt="2" class="slideimg" />
</li>
<li style="background: yellow;">
<img src="images/style2.jpg" alt="3" class="slideimg" />
</li>
<li style="background: red;">
<img src="images/style3.jpg" alt="4" class="slideimg" />
</li>
</ul>
</div>