How do you get multiple automatic slideshows on one page? - html

I am currently following the W3 HTML/CSS tutorial on getting multiple slideshows on one page. The tutorial has examples for multiple slideshows (manual) or ONE automatic slideshow, but no examples for multiple (automatic) slideshows. I attempted to combine the tutorial, keeping in mind that the indexes for each individual slideshow needed to be intact, but no matter what I do, it would not automatically transition.
This is the link to the W3 tutorial: https://www.w3schools.com/howto/howto_js_slideshow.asp(https://www.w3schools.com/howto/howto_js_slideshow.asp)
This is the code that I attempted to change/use to automatically transition the slides:
var slideIndex = [1,1];
/* Class the members of each slideshow group with different CSS classes */
var slideId = ["mySlides1", "mySlides2"]
showSlides(1, 0);
showSlides(1, 1);
function plusSlides(n, no) {
showSlides(slideIndex[no] += n, no);
}
function showSlides(n, no) {
var i;
var x = document.getElementsByClassName(slideId[no]);
if (n > x.length) {slideIndex[no] = 1}
if (n < 1) {slideIndex[no] = x.length}
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
n++; /* WHAT I ADDED */
x[slideIndex[no]-1].style.display = "block";
setTimeout(showSlides(n, x), 2000); /* WHAT I ADDED */
}
The capitalized comment next to the code line is what I added to the tutorial code. Otherwise, the rest of the code is exactly the same as the tutorial with no changes. I have tried setInterval and moving the code in different spots, but nothing works.

Just a couple of changes and you are there. I also added an option to change delays, take a look:
/* Find all slideshow containers */
var slideshowContainers = document.getElementsByClassName("slideshow-container");
/* For each container get starting variables */
for(let s = 0; s < slideshowContainers.length; s++) {
/* Read the new data attribute */
var cycle = slideshowContainers[s].dataset.cycle;
/* Find all the child nodes with class mySlides */
var slides = slideshowContainers[s].querySelectorAll('.mySlides');
var slideIndex = 0;
/* Now we can cycle slides, but this recursive function must have parameters */
/* slides and cycle never change, those are unique for each slide container */
/* slideIndex will increase during each iteration */
showSlides(slides, slideIndex, cycle);
};
/* Function is alsmost same, but now it uses 3 new parameters */
function showSlides(slides, slideIndex, cycle) {
for (i = 0; i < slides.length; i++) {
slides[i].style.display = "none";
};
slideIndex++;
if (slideIndex > slides.length) {
slideIndex = 1
};
slides[slideIndex - 1].style.display = "block";
/* Calling same function, but with new parameters and cycle time */
setTimeout(function() {
showSlides(slides, slideIndex, cycle)
}, cycle);
};
* {
box-sizing: border-box;
}
body {
font-family: Verdana, sans-serif;
}
.mySlides {
display: none;
}
img {
vertical-align: middle;
}
/* Slideshow container */
.slideshow-container {
max-width: 320px;
position: relative;
margin: auto;
}
/* Caption text */
.text {
color: #f2f2f2;
font-size: 15px;
padding: 8px 12px;
position: absolute;
bottom: 8px;
width: 100%;
text-align: center;
}
/* Number text (1/3 etc) */
.numbertext {
color: #f2f2f2;
font-size: 12px;
padding: 8px 12px;
position: absolute;
top: 0;
}
/* The dots/bullets/indicators */
.dot {
height: 15px;
width: 15px;
margin: 0 2px;
background-color: #bbb;
border-radius: 50%;
display: inline-block;
transition: background-color 0.6s ease;
}
.active {
background-color: #717171;
}
/* Fading animation */
.fade {
-webkit-animation-name: fade;
-webkit-animation-duration: 1.5s;
animation-name: fade;
animation-duration: 1.5s;
}
#-webkit-keyframes fade {
from {
opacity: .4
}
to {
opacity: 1
}
}
#keyframes fade {
from {
opacity: .4
}
to {
opacity: 1
}
}
/* On smaller screens, decrease text size */
#media only screen and (max-width: 300px) {
.text {
font-size: 11px
}
}
<h2>Automatic Slideshow</h2>
<p>Change image every 2 seconds:</p>
<div class="slideshow-container" data-cycle="2000">
<div class="mySlides fade">
<div class="numbertext">1 / 3</div>
<img src="https://placeimg.com/320/240/animals">
<div class="text">Caption Text</div>
</div>
<div class="mySlides fade">
<div class="numbertext">2 / 3</div>
<img src="https://placeimg.com/320/240/nature">
<div class="text">Caption Two</div>
</div>
<div class="mySlides fade">
<div class="numbertext">3 / 3</div>
<img src="https://placeimg.com/320/240/people">
<div class="text">Caption Three</div>
</div>
</div>
<p>Change image every 3 seconds:</p>
<div class="slideshow-container" data-cycle="3000">
<div class="mySlides fade">
<div class="numbertext">1 / 2</div>
<img src="https://placeimg.com/320/240/animals">
<div class="text">Caption 1</div>
</div>
<div class="mySlides fade">
<div class="numbertext">2 / 2</div>
<img src="https://placeimg.com/320/240/nature">
<div class="text">Caption 2</div>
</div>
</div>
Also on JSFiddle
What is most important here is the scope of Javascript variables. I suggest reading about JS Variables, than google javascript scope variables and you may find articles like this one, or that one.

Related

Memory Game Cards Not Rotating Properly

I have been learning how to create a memory game and thought I was following the instructions carefully but I have run into a snag. In my html, I have a div for the card and two child divs to style the front and back of the card.
<div class="container">
<div id="memory_board">
<div class="card">
<div id="back0" class="cardFace cardFaceBack"></div>
<div id="front0" class="cardFace cardFaceFront" class="card"></div>
</div>
</div>
</div>
The number of cards for the memory game will vary.
When I run the code, they are stacked on top of each other meaning when you click on one card, the back flips over as expected but the front flips over underneath its original position. Here is my codepen. How can I adjust me code so that it looks like the card flips over properly?
=============== Edit ===================
Quick question, when I include a link to codepen, do I still have include all of the code?
The css for this game is:
* {
margin:0;
padding:0;
box-sizing:border-box;
}
div.container {
display: flex;
justify-content: center;
align-items: center;
vertical-align: middle;
}
div#memory_board{
background:#CCC;
border:#999 1px solid;
display: inline-block;
padding: 10px;
perspective: 1000px;
}
.card {
width:100px;
height:133px;
display: inline-block;
margin:0px;
padding:10px;
transition: transform 1s;
transform-style: preserve-3d;
transform-origin: center right;
cursor: pointer;
position: relative;
}
.card.is-flipped {
transform: translateX(-100%) rotateY(-180deg);
}
.cardFace {
position: absolute;
width: 100%;
height: 100%;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
.cardFaceFront {
position: inherit;
background: whitesmoke;
color: black;
font-weight: bold;
font-size: 40px;
border:#000 1px solid;
text-align:center;
vertical-align: middle;
transform: rotateY(180deg);
}
.cardFaceBack {
background: url("https://images.cdn2.stockunlimited.net/preview1300/playing-cards-
background_1608080.jpg"); no-repeat;
background-size: cover;
position: relative;
border:#000 1px solid;
}
In addition, the javascript for this program is:
var memory_array = ['A','A','B','B'];
var memory_values = [];
var memory_tile_ids = [];
var tiles_flipped = 0;
const memory_board = document.getElementById('memory_board');
let getRndInteger = (min, max) => Math.floor(Math.random() * (max - min) ) + min
// the following function randomly shuffles elements in an array using the Fisher-Yates (aka Knuth) shuffle
let shuffle = array => {
let currentIndex = array.length, randomIndex;
// While there remain elements to shuffle...
while (currentIndex != 0) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
// And swap it with the current element.
[array[currentIndex], array[randomIndex]] = [
array[randomIndex], array[currentIndex]];
}
return array;
}
function initiateCard () {
let card = document.querySelectorAll('.card');
card.forEach( card => card.addEventListener ( 'click', () => {
card.classList.toggle('is-flipped');
}));
}
function newBoard() {
let memoryArray = shuffle (memory_array);
for (let i = 0; i <= memoryArray.length - 1; i++) {
document.getElementById("front" + i).innerText = memory_array[i];
}
}
$( document ).ready(function() {
newBoard ();
initiateCard ();
});
When the game starts, the memory_array shuffles propery and each element is distributed to the cards. However, when you turn a card,
I thought I had followed the instructions but I do not understand why, when turned, the front face is below where the back was. What adjustments do I have to make, after turning the card, so the front of the card in the same place as the back of the card, not below it.
an animation or a gif will be of help to as what you want to achieve, from your comment in your code I could see you are trying to replicate this, but the way you structure your code doesn't seem to be as this
https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
Okay, so a couple of things. I couldn't get your js to work. Getting this error "Uncaught TypeError: Cannot set properties of null (setting 'innerText')".
And with your CSS you need to position the front and back with position: absolute; otherwise, they affect each other. The back was pushing the front down the page.
And if you set transform-origin: center center; you don't need to do the additional transform: translateY(-100%);
var memory_array = ['A', 'A', 'B', 'B'];
var memory_values = [];
var memory_tile_ids = [];
var tiles_flipped = 0;
const memory_board = document.getElementById('memory_board');
let getRndInteger = (min, max) => Math.floor(Math.random() * (max - min)) + min
// the following function randomly shuffles elements in an array using the Fisher-Yates (aka Knuth) shuffle
let shuffle = array => {
let currentIndex = array.length, randomIndex;
// While there remain elements to shuffle...
while (currentIndex != 0) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
// And swap it with the current element.
[array[currentIndex], array[randomIndex]] = [
array[randomIndex], array[currentIndex]];
}
return array;
}
function initiateCard() {
let card = document.querySelectorAll('.card');
card.forEach(card => card.addEventListener('click', () => {
card.classList.toggle('is-flipped');
}));
}
function newBoard() {
let memoryArray = shuffle(memory_array);
for (let i = 0; i <= memoryArray.length - 1; i++) {
document.getElementById("front" + i).innerText = memory_array[i];
}
}
$(document).ready(function () {
newBoard();
initiateCard();
});
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
div.container {
display: flex;
justify-content: center;
align-items: center;
vertical-align: middle;
}
div#memory_board {
background: #CCC;
border: #999 1px solid;
display: inline-block;
padding: 10px;
perspective: 1000px;
}
.card {
width: 100px;
height: 133px;
display: inline-block;
margin: 0px;
/* padding: 10px; */
transition: transform 1s;
transform-style: preserve-3d;
cursor: pointer;
position: relative;
transform-origin: center center;
}
.card.is-flipped {
transform: rotateY(180deg);
}
.cardFace {
position: absolute;
width: 100%;
height: 100%;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
.cardFaceFront {
position: absolute;
background: whitesmoke;
color: black;
font-weight: bold;
font-size: 40px;
border: #000 1px solid;
text-align: center;
vertical-align: middle;
transform: rotateY(180deg);
}
.cardFaceBack {
background: url("https://images.cdn2.stockunlimited.net/preview1300/playing-cards-background_1608080.jpg") no-repeat;
background-size: cover;
position: absolute;
border: #000 1px solid;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<div class="container">
<div id="memory_board">
<div class="card is-flipped">
<div id="back0" class="cardFace cardFaceBack"></div>
<div id="front0" class="cardFace cardFaceFront" class="card"></div>
</div>
<div class="card">
<div id="back0" class="cardFace cardFaceBack"></div>
<div id="front0" class="cardFace cardFaceFront" class="card"></div>
</div>
<div class="card">
<div id="back0" class="cardFace cardFaceBack"></div>
<div id="front0" class="cardFace cardFaceFront" class="card"></div>
</div>
<div class="card">
<div id="back0" class="cardFace cardFaceBack"></div>
<div id="front0" class="cardFace cardFaceFront" class="card"></div>
</div>
</div>
</div>

CSS combination of :active and :not psuedo classes

I have a code where the "card" class takes the user to an article when clicked.
And its child, "category", takes the user to another website when clicked.
<div class="card">
<div class="img"></div>
<div class="category"></div>
<div class="title"></div>
<div class="description"></div>
</div>
I'm trying to write CSS animations with div:active for these two divs.
So when I have the following, the whole card animates:
.card:active {
transform: translateX(50px);
transition: all 0.5s ease;
}
But I don't want the card to animate when the user clicks on the category div.
So, I tried something like the following, and others, which didn't work.
:not(.category).card:active{
transform: translateX(50px);
transition: all 0.5s ease;
}
Is there a combination of :not and :active pseudo classes that I could use to make the card animate when clicked, but not animate when the category is being clicked?
solution 1, CSS only
Generally one could use...
/* CSS */
.card { pointer-events: none }
.card>:not(.category) { pointer-events: auto } /* all kids except .category */
.card:active { transform: translateX(50px) }
/* HTML */
<div class="card">
<div class="img">image</div>
<div class="category">CATEGORY</div>
<div class="title">no-card</div>
<div class="description">description</div>
</div>
...and clicking any child of .card, except class .category, will trigger the card :active event as well as :hover. However, any card space not occupied by child elements wil not trigger any event (i.e. .card:padding and .category will not trigger :active or :hover).
Another drawback is that .category will listen to no events at all and therefore cannot be an input element that needs to handle those events (like a <button>, as shown in the demo).
If this is acceptable, this solution is the easiest to code and maintain.
solution 2, CSS plus JS
This solution uses only simple CSS...
.effect:active { transform: translateX(50px) } /* NOT .card:active */
...and some Vanilla Javascript (pseudo code) that simply removes/adds the .effect class from .card when appropriate.
forEach cardList.item do
card.onmouseover = enableEffect();
card.category.onmouseenter = disableEffect();
card.category.onmouseout = enableEffect();
disableEffect = remove class 'effect' from .card
enableEffect = add class 'effect' to .card
The below snippet includes both solutions, is heavily commented and includes a few responsiveness extras (like CSS columns, main font and page spacing. Math used MathIsFun: Linear Equation).
Just copy the code and have fun with it!
SNIPPET
'use-strict';
// Traverse an array and execute the passed callback function for each array element found
var forEachEntryIn = function (array, callback, scope) {
for (var i = 0; i < array.length; i++) { callback.call(scope, i, array[i]); } };
// Get the list of cards
var cards = document.getElementsByClassName('card');
// Make this a function and you can toggle it with a <button>
var DEBUG = false; // set to 'true' for debug view and some console output
(DEBUG) ? document.body.setAttribute('outlines','1') : document.body.setAttribute('outlines','0');
// Traverse the list of cards
forEachEntryIn( cards,
function (idx,card,scope) {
// '.effect' is needed by default,
// so why add it in HTML class="" property when we can do it here...
card.classList.add('effect'); // remove if you want to assign in HMTL anyway
/*
MOUSEOVER events are bubbled to child elements
MOUSEENTER does not bubble, needed on '.category'
target: the element that triggered the event ('.card' OR any of its child elements)
currentTarget: the element that the event listener is attached to: '.card'
*/
card.onmouseover = function(e) { // Attach 'MOUSEOVER' listener to '.card'
// Parent check: event may be bubbled (from any '.card' children)
// So, is the parent a '.card' or maybe its parent?
if (e.target.parentElement == e.currentTarget) {
enableEffect(e.target.parentElement); // Activate '.card' animation
};
// NOTE: Disable the check, click a card and see what happens....funny!
};
var category = card.querySelector('.category');
if (card.contains(category)) {
category.onmouseenter = function(e) { disableEffect(e.currentTarget.parentElement); };
category.onmouseout = function(e) { enableEffect (e.currentTarget.parentElement); };
};
} // end function (idx,el,scope)
); // end forEachEntryIn
// Helper functions to keep main loop readable
function enableEffect(parent) {
if (!parent.classList.contains('effect')) { // if parent has no '.effect'
parent.classList.add('effect'); // then add it
};
if (DEBUG) logInfo(parent);
};
function disableEffect(parent) {
if (parent.classList.contains('effect')) { // parent if has '.effect'
parent.classList.remove('effect'); // then remove it
};
if (DEBUG) logInfo(parent);
};
// For debugging
function logInfo(p) {
console.log( // Show some info in browser console
((p.className) ? '<' + p.tagName +' class="' + p.className + '">': '<' + p.tagName +'>' ),
p.classList.contains('effect')
);
};
/********************************/
/* demo for CSS only solution 1 */
/********************************/
.no-card {
pointer-events: none;
}
.no-card>:not(.category) {
pointer-events: auto;
}
.no-card:active {
transform: translateX(50px);
transition: all 0.5s ease;
}
/***********************************/
/* demo for CSS plus JS solution 2 */
/***********************************/
/* class will be assigned with JS */
.effect:active {
transform: translateX(50px);
transition: all 0.5s ease;
}
/*****************************************************/
/* below just demo, everything can be safely removed */
/*****************************************************/
/**************************/
/* preferred global rules */
/**************************/
html,body { box-sizing: border-box; width: 100%; max-width: 100% }
*::before,*::after, * { box-sizing: inherit }
body { margin: 0 }
/* ALL math reference: https://www.mathsisfun.com/equation_of_line.html */
/* responsive base font size using y = mx + b */
html { font-size: calc(0.625vmin + 0.75rem) } /* (320,14)(1280,20) */
/* prohibit user from selecting text (put in <body>) */
[no-select] { -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none }
[do-select] { -webkit-user-select: text; -moz-user-select: text; -ms-user-select: text; user-select: text; cursor: auto }
/* enable user to select text (put in specific elements) */
/* to show all elements with outlines (assigned to <body> with JS) */
[outlines="1"] * { outline: 1px dashed }
/***********************************/
/* Extra: plain responsive columns */
/***********************************/
body {
/*
responsive page padding using y = mx + b
p1(320,32) p2(1920, 72) => y = 0.025x + 24
p3(320, 8) p4(1920,320) => y = 0.195x - 54.4
*/
padding: calc(2.5vh + 24px) calc(19.5vw - 54.4px);
}
.cardList {
column-count: 3; /* preferred number of columns given column-width */
column-gap: 0; /* handled with card margins */
/*
column width using y = mx + b
mobile/tablet, 1 column : 320 - 60 = 260px
desktop, 3 columns: (1920 - 640) / 3 = 426 minus animation gap = 376px
p1(320,260) p2(1920,376)
=> y = 7.25x + 236.8
*/
column-width: calc(7.25vw + 230.8px); /* (320,260)(1920,376) */
/* (320,260)(1920,376) for scrollbar => 236.8 - (18/3) = 230.8px */
}
.card {
break-inside: avoid; /* don't split card over columns */
}
/******************/
/* card eye-candy */
/******************/
.wrapper,
.cardList {
background-color: rgba(0,0,0,.1); /* just to review body padding */
padding: 2rem 0;
}
.no-card, .card {
background-color: CornSilk;
padding: 1rem;
margin : 1rem;
margin-right: 60px; /* animation width plus 10px space */
/* GMC elevation 1dp */
box-shadow: 0px 2px 1px -1px rgba(0,0,0,.20),
0px 1px 1px 0px rgba(0,0,0,.14),
0px 1px 3px 0px rgba(0,0,0,.12);
}
.card:first-child { margin-top: 0 } /* otherwise jagged column tops */
/* Some :hover animation */
.no-card:hover, .card:hover {
/* GMC elevation 3dp */
box-shadow: 0px 3px 3px -2px rgba(0,0,0,.20),
0px 3px 4px 0px rgba(0,0,0,.14),
0px 1px 8px 0px rgba(0,0,0,.12);
}
<body no-select>
<h2>solution 1, CSS only</h2>
<div class="wrapper">
<div class="no-card">
<div class="img">image</div>
<button class="category">CATEGORY</button>
<div class="title">no-card</div>
<div class="description">description</div>
</div>
</div>
<h2>solution 2, CSS plus JS</h2>
<div class="cardList">
<div class="card">
<div class="img">image</div>
<button class="category">CATEGORY</button>
<div class="title">card 1</div>
<div class="description">description</div>
</div>
<div class="card">
<div class="img">image</div>
<button class="category">CATEGORY</button>
<div class="title">card 2</div>
<div class="description">description</div>
</div>
<div class="card">
<div class="img">image</div>
<button class="category">CATEGORY</button>
<div class="title">card 3</div>
<div class="description">description</div>
</div>
<div class="card">
<div class="img">image</div>
<button class="category">CATEGORY</button>
<div class="title">card 4</div>
<div class="description">description</div>
</div>
<div class="card">
<div class="img">image</div>
<div>some other element</div>
<div class="title">card 5</div>
<div class="description">description</div>
</div>
<div class="card">
<div class="img">image</div>
<button class="category">CATEGORY</button>
<div class="title">card 6</div>
<div class="description">description</div>
</div>
</div>
</body>

I have some issues while making an slideshow

I'm trying to make an slideshow, but when it moves to the next (or previous) image, there is nothing on the background.
I would like the image you're going to see appearing behind the one you are seeing, something like when you are shuffling cards.
Aditionally, I would like to have different animations when you click on the right or on the left arrow, to match it's movement.
Here is the code I'm using right now:
Code
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.7.2/animate.min.css">
<style>
.mySlides {display: none}
img {vertical-align: middle;}
/* Slideshow container */
.slideshow-container {
overflow: hidden;
max-width: 300px;
position: relative;
margin: auto;
}
/* Next & previous buttons */
.prev, .next {
cursor: pointer;
position: absolute;
top: 50%;
width: auto;
padding: 16px;
margin-top: -22px;
color: white;
font-weight: bold;
font-size: 18px;
transition: 0.6s ease;
border-radius: 0 3px 3px 0;
user-select: none;
}
/* Position the "next button" to the right */
.next {
right: 0;
border-radius: 3px 0 0 3px;
}
/* On hover, add a black background color with a little bit see-through */
.prev:hover, .next:hover {
background-color: rgba(0,0,0,0.8);
}
</style>
</head>
<body>
<div class="slideshow-container">
<div class="mySlides animated slideInLeft">
<img src="https://pruebas20.webcindario.com/img_snow_wide.jpg" style="width:100%">
</div>
<div class="mySlides animated slideInRight">
<img src="https://pruebas20.webcindario.com/img_nature_wide.jpg" style="width:100%">
</div>
<div class="mySlides slideInRight">
<img src="https://pruebas20.webcindario.com/img_mountains_wide.jpg" style="width:100%">
</div>
<a class="prev" onclick="plusSlides(-1)">❮</a>
<a class="next" onclick="plusSlides(1)">❯</a>
</div>
<script>
var slideIndex = 1;
showSlides(slideIndex);
function plusSlides(n) {
showSlides(slideIndex += n);
}
function currentSlide(n) {
showSlides(slideIndex = n);
}
function showSlides(n) {
var i;
var slides = document.getElementsByClassName("mySlides");
var dots = document.getElementsByClassName("dot");
if (n > slides.length) {slideIndex = 1}
if (n < 1) {slideIndex = slides.length}
for (i = 0; i < slides.length; i++) {
slides[i].style.display = "none";
}
for (i = 0; i < dots.length; i++) {
dots[i].className = dots[i].className.replace(" active", "");
}
slides[slideIndex-1].style.display = "block";
dots[slideIndex-1].className += " active";
}
</script>
</body>
</html>
Thank you!
The problem is that you are hiding all but the current slide, both with javascript and css.
for (i = 0; i < slides.length; i++) {
slides[i].style.display = "none";
}
.mySlides {display: none}
You would need to remove this, but change the z-index of the slides instead so that the current slide is on top, and at the same time add the slideInRight/slideInLeft classes. You would also need to absolutely position the slides within the container, so that they occupy the same position.
Yes, Mark Fisher is correct. You need to play around with the z-index of the slides. To be honest it would probably be easier to use a plugin such as Slick Slider if you want to have cool transitions etc.
I have created a codepen based on your code. It is not perfect, but perhaps you can get an idea of how to do this. Your slides need to be positioned absolutely within the slide wrapper in order to be "revealed" behind each other when you move between slides. I have used a CSS transition on the position to animate the slide.
.mySlides {position: absolute; left: 0; z-index: 0;transition: left 1s linear; width: 300px; height: 105px;}
https://codepen.io/moorehannah/pen/eqdXby

CSS: Make children inside parent responsive

So I am not using any CSS framework like bootstrap to get responsiveness out of the box which is why I am having trouble making responsive layout.
Please see jsbin
I essentially what to auto-resize colorful boxes based on browser window size eg that should shrink or grow automatically based on window size. Colorful boxes inside their parent should always be in horizontal row but should be able to adjust their width and height like this example.
I tried using flex-wrap: nowrap; but it didn't do the trick :(
Please note that colorful boxes are using position:absolute with parent's position being relative. I am also adding left css property to these boxes via JavaScript to change their position for the sake of sliding animation.
function Carousel(options) {
options = options || {};
// options vars
let speed = options.speed || 1; // animation speed in seconds
let width = options.width || 200;
let height = options.height || 100;
let space = options.space || 30;
// other vars
let container = document.querySelector('.carousel-container .carousel');
let slides = container.querySelectorAll('.carousel-item');
let curSlide = null;
let prevSlide = null;
let nextSlide = null;
if (areSlidesPresent()) {
setup();
}
// functions //
function setup() {
// we assume first slide to be current one as per UI requirements
//slides[0].classList.add("current");
curSlide = slides[0];
// we assume second slide to be next as per UI requirements
nextSlide = slides[1];
// we assume last slide to be prev as per UI requirements
prevSlide = slides[slides.length - 1];
// position elements horizontally
positionSlides();
}
function areSlidesPresent() {
return slides.length > 0;
}
this.getCurrentSlide = function() {
return curSlide;
}
this.getNextSlide = function() {
return nextSlide;
}
this.getPreviousSlide = function() {
return prevSlide;
}
this.setNextSlide = function() {
if (areSlidesPresent()) {
let allSlides = [];
// build new order of slides
allSlides.push(nextSlide);
// middle ones
for (let i = 2; i < slides.length; i++) {
allSlides.push(slides[i]);
}
allSlides.push(curSlide);
// now add to DOM after cleaning previous slide order
for (let i = 0; i < allSlides.length; i++) {
container.appendChild(allSlides[i]);
}
slides = allSlides;
setup();
}
}
this.setPreviousSlide = function() {
if (areSlidesPresent()) {
let allSlides = [];
// build new order of slides
allSlides.push(prevSlide);
allSlides.push(curSlide);
// middle ones
for (let i = 1; i < slides.length - 1; i++) {
allSlides.push(slides[i]);
}
// now add to DOM after cleaning previous slide order
for (let i = 0; i < allSlides.length; i++) {
container.appendChild(allSlides[i]);
}
slides = allSlides;
setup();
}
}
function positionSlides() {
curSlide.style.marginLeft = '0px';
for (let i = 0; i < slides.length; i++) {
slides[i].querySelector('.carousel-content').style.width = (width) + 'px';
slides[i].querySelector('.carousel-content').style.height = (height) + 'px';
let elementWidth = getStyle(nextSlide, 'width');
if (i === 0) {
slides[i].style.zIndex = -10;
//slides[i].style.opacity = '1';
slides[i].querySelector('.carousel-content').style.width = (width + 50) + 'px';
slides[i].querySelector('.carousel-content').style.height = (height + 50) + 'px';
} else {
slides[i].style.zIndex = 0;
//slides[i].style.opacity = '0.7';
}
if (i > 0) {
slides[i].style.marginLeft = (space * 2) + 'px';
elementWidth = parseInt(elementWidth, 10) + space;
}
slides[i].style.transition = speed + 's';
slides[i].style.left = (elementWidth * i) + 'px';
}
}
function getStyle(el, prop) {
return window.getComputedStyle(el, null).getPropertyValue(prop)
.replace('px', '')
.replace('em', '');
}
}
// utility
function log(text) {
console.log(text);
}
var options = {
speed: 1, // animation speed
width: 250, // slide width
height: 150, // slide height
space: 25 // space in px between slides
};
var carousel = new Carousel(options);
function selectCurrent() {
log(carousel.getCurrentSlide());
}
function selectNext() {
carousel.setNextSlide();
}
function selectPrev() {
carousel.setPreviousSlide();
}
.carousel-container {
width: auto;
height: auto;
margin: 25px;
display: flex;
align-items: center;
justify-content: center;
}
.carousel {
height: 100%;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
.carousel .carousel-item {
position: absolute;
transition: transform .5s ease-in-out;
color: #fff;
margin-left: 10px;
-webkit-box-reflect: below 10px -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(70%, transparent), to(rgba(255, 255, 255, 0.2)));
}
.carousel .carousel-item:first-child .carousel-content {
opacity: 1;
}
.carousel .carousel-item .carousel-title {
font-size: 24px;
text-align: center;
}
.carousel .carousel-item .carousel-content {
font-size: 18px;
font-weight: bold;
border: 1px solid #ccc;
display: flex;
align-items: center;
justify-content: center;
border-radius: 10px;
}
/* temp css below */
body {
background: #2C374A;
padding-top: 150px;
}
.navigation {
display: flex;
align-items: center;
justify-content: center;
margin-top: 150px;
}
.button {
color: #444;
padding: 10px;
width: 60px;
cursor: pointer;
background: #CCC;
text-align: center;
font-weight: bold;
border-radius: 5px;
border-top: 1px solid #FFF;
box-shadow: 0 5px 0 #999;
transition: box-shadow 0.1s, top 0.1s;
margin: 10px;
}
.button:hover,
.button:hover {
color: #000;
}
.button:active,
.button:active {
top: 104px;
box-shadow: 0 1px 0 #999;
}
<div class="carousel-container">
<div class="carousel">
<div class="carousel-item">
<div class="carousel-title">Make a Call</div>
<div class="carousel-content" style="background:#0E6DE8;border:10px solid #78B1FA">Slide One</div>
</div>
<div class="carousel-item">
<div class="carousel-title">Send a Message</div>
<div class="carousel-content" style="background:#D90080;border:10px solid #E357A9">Slide Two</div>
</div>
<div class="carousel-item">
<div class="carousel-title">Send a Picture</div>
<div class="carousel-content" style="background:#FEC601;border:10px solid #FFDD64">Slide Three</div>
</div>
<div class="carousel-item">
<div class="carousel-title">Send a Video</div>
<div class="carousel-content" style="background:#3DB365;border:10px solid #90E0AB">Slide Four</div>
</div>
</div>
</div>
<div class="navigation">
<div class="button" onclick="selectNext()">Next</div>
<div class="button" onclick="selectCurrent()">Select</div>
<div class="button" onclick="selectPrev()">Prev</div>
</div>
Problem here was:
Width was hard-coded in your JS, so if width is in px it can't be responsive.
By applying position:absolute to you carousel-item, it forced the children to get out of the box.
What I did:
Got rid of the static width and other functionalities related to width from your JS
Removed position:absolute from carousel-item
Let me know if this is what you are expecting.
function Carousel(options) {
options = options || {};
// options vars
let speed = options.speed || 1; // animation speed in seconds
// let width = options.width || 100;
let height = options.height || 100;
let space = options.space || 30;
// other vars
let container = document.querySelector('.carousel-container .carousel');
let slides = container.querySelectorAll('.carousel-item');
let curSlide = null;
let prevSlide = null;
let nextSlide = null;
if (areSlidesPresent()) {
setup();
}
// functions //
function setup() {
// we assume first slide to be current one as per UI requirements
//slides[0].classList.add("current");
curSlide = slides[0];
// we assume second slide to be next as per UI requirements
nextSlide = slides[1];
// we assume last slide to be prev as per UI requirements
prevSlide = slides[slides.length - 1];
// position elements horizontally
positionSlides();
}
function areSlidesPresent() {
return slides.length > 0;
}
this.getCurrentSlide = function() {
return curSlide;
}
this.getNextSlide = function() {
return nextSlide;
}
this.getPreviousSlide = function() {
return prevSlide;
}
this.setNextSlide = function() {
if (areSlidesPresent()) {
let allSlides = [];
// build new order of slides
allSlides.push(nextSlide);
// middle ones
for (let i = 2; i < slides.length; i++) {
allSlides.push(slides[i]);
}
allSlides.push(curSlide);
// now add to DOM after cleaning previous slide order
for (let i = 0; i < allSlides.length; i++) {
container.appendChild(allSlides[i]);
}
slides = allSlides;
setup();
}
}
this.setPreviousSlide = function() {
if (areSlidesPresent()) {
let allSlides = [];
// build new order of slides
allSlides.push(prevSlide);
allSlides.push(curSlide);
// middle ones
for (let i = 1; i < slides.length - 1; i++) {
allSlides.push(slides[i]);
}
// now add to DOM after cleaning previous slide order
for (let i = 0; i < allSlides.length; i++) {
container.appendChild(allSlides[i]);
}
slides = allSlides;
setup();
}
}
function positionSlides() {
curSlide.style.marginLeft = '0px';
for (let i = 0; i < slides.length; i++) {
// slides[i].querySelector('.carousel-content').style.width = (width) + 'px';
slides[i].querySelector('.carousel-content').style.height = (height) + 'px';
let elementWidth = getStyle(nextSlide, 'width');
if (i === 0) {
slides[i].style.zIndex = -10;
//slides[i].style.opacity = '1';
// slides[i].querySelector('.carousel-content').style.width = (width + 50) + 'px';
slides[i].querySelector('.carousel-content').style.height = (height + 50) + 'px';
} else {
slides[i].style.zIndex = 0;
//slides[i].style.opacity = '0.7';
}
if (i > 0) {
slides[i].style.marginLeft = (space * 2) + 'px';
// elementWidth = parseInt(elementWidth, 10) + space;
}
slides[i].style.transition = speed + 's';
// slides[i].style.left = (elementWidth * i) + 'px';
}
}
function getStyle(el, prop) {
return window.getComputedStyle(el, null).getPropertyValue(prop)
.replace('px', '')
.replace('em', '');
}
}
// utility
function log(text) {
console.log(text);
}
var options = {
speed: 1, // animation speed
width: 250, // slide width
height: 150, // slide height
space: 25 // space in px between slides
};
var carousel = new Carousel(options);
function selectCurrent() {
log(carousel.getCurrentSlide());
}
function selectNext() {
carousel.setNextSlide();
}
function selectPrev() {
carousel.setPreviousSlide();
}
.carousel-container {
height: auto;
margin: 25px;
display: flex;
}
.carousel {
flex: 1;
height: 100%;
width: 100vh;
/* overflow:hidden; */
display: flex;
align-items: center;
justify-content: center;
}
.carousel .carousel-item {
transition: transform .5s ease-in-out;
color: #fff;
flex: 1;
margin-left: 10px;
-webkit-box-reflect: below 10px -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(70%, transparent), to(rgba(255, 255, 255, 0.2)));
}
.carousel .carousel-item:first-child .carousel-content {
opacity: 1;
}
.carousel .carousel-item .carousel-title {
font-size: 24px;
text-align: center;
}
.carousel .carousel-item .carousel-content {
font-size: 18px;
font-weight: bold;
border: 1px solid #ccc;
display: flex;
align-items: center;
justify-content: center;
border-radius: 10px;
}
/* temp css below */
body {
background: #2C374A;
}
.navigation {
display: flex;
align-items: center;
justify-content: center;
}
.button {
color: #444;
padding: 10px;
width: 60px;
cursor: pointer;
background: #CCC;
text-align: center;
font-weight: bold;
border-radius: 5px;
border-top: 1px solid #FFF;
box-shadow: 0 5px 0 #999;
transition: box-shadow 0.1s, top 0.1s;
margin: 10px;
}
.button:hover,
.button:hover {
color: #000;
}
.button:active,
.button:active {
box-shadow: 0 1px 0 #999;
}
<div class="navigation">
<div class="button" onclick="selectNext()">Next</div>
<div class="button" onclick="selectCurrent()">Select</div>
<div class="button" onclick="selectPrev()">Prev</div>
</div>
<div class="carousel-container">
<div class="carousel">
<div class="carousel-item">
<div class="carousel-title">Make a Call</div>
<div class="carousel-content" style="background:#0E6DE8;border:10px solid #78B1FA">Slide One</div>
</div>
<div class="carousel-item">
<div class="carousel-title">Send a Message</div>
<div class="carousel-content" style="background:#D90080;border:10px solid #E357A9">Slide Two</div>
</div>
<div class="carousel-item">
<div class="carousel-title">Send a Picture</div>
<div class="carousel-content" style="background:#FEC601;border:10px solid #FFDD64">Slide Three</div>
</div>
<div class="carousel-item">
<div class="carousel-title">Send a Video</div>
<div class="carousel-content" style="background:#3DB365;border:10px solid #90E0AB">Slide Four</div>
</div>
</div>
</div>

How to change data visible range to % percent

I am using this for my header that changes in a one page scroll up and down page. I noticed that it's not responsive so i am asking you if you maybe know a way to make that responsive. Like changing the 0-690 into a percentage so that it will work on mobile and also on a tv screen.
HTML
<div class="header header-1" data-visible-range="0-690">Portfolio</div>
<div class="header header-2" data-visible-range="691-2100">Services</div>
<div class="header header-3" data-visible-range="2101-">Contact</div>
CSS
.header-1 {
background-color:dimgray;
display: block;
}
.header-2 {
background-color:dimgray;
}
.header-3 {
background-color:dimgray;
}
.header {
position: fixed;
top: 0;
left: 0;
height:8vmax;
width: 100%;
display: none;
visibility:hidden;
transition: visibility .4s, opacity .4s ease-in-out;opacity:0;
font-size:4vmax;padding:1.58vmax;color:white;
}
What if, instead of basing it off pixels, you just checked to see if an element hit the top of the page, and then changed the header?
We'll call these elements "triggers." See my code below for an example of how they work.
let updateHeader = () => {
let scrollTop = $(window).scrollTop(),
triggerTitle = "Hi";
$('.trigger').each((i, el) => {
let topPos = $(el).offset().top,
distance = topPos - scrollTop;
if (distance < 0)
triggerTitle = $(el).data('title');
});
$('header h2').text(triggerTitle);
}
$(window).scroll(updateHeader);
$(window).on('touchmove', updateHeader);
body {
margin: 0;
}
#container {
height: 1000px;
}
header {
width: 100%;
position: fixed;
top: 0;
background-color: red;
}
p {
margin: 200px 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<header><h2>Hi</h2></header>
<p class="trigger" data-title="section1">
trigger1
</p>
<p class="trigger" data-title="section2">
trigger2
</p>
<p class="trigger" data-title="section3">
trigger3
</p>
</div>
As you scroll down the page, each trigger hits the top of the page, and the text in the header will change to the the value of the latest trigger's data-title. You could position these triggers appropriately above each of your website's sections, so that, no matter what size the screen, the header should update at the right time. Here's a codepen.
EDIT
Try this JS instead for maximum compatibility (no es6 involved).
function updateHeader() {
var scrollTop = $(window).scrollTop(),
triggerTitle = "Hi";
$('.trigger').each(function(i, el) {
var topPos = $(el).offset().top,
distance = topPos - scrollTop;
if (distance < 0)
triggerTitle = $(el).data('title');
});
$('header h2').text(triggerTitle);
}
$(window).scroll(updateHeader);
$(window).on('touchmove', updateHeader);