Split Landing Page (HTML, CSS, JavaScript) - javascript

I watched the tutorial from Traversy Media for a Split Landing Page. (https://www.youtube.com/watch?v=oRmQN244Ir0)
I wanted to tweak the page to have three sections instead of two, but i can't get it done.
It doesn't show the content of the left section. Instead the middle section is overlapping the left, and if i hover over it, the left section transitions into the middle.
Also if i hover over the middle section, no transition at all is being performed.
const left = document.querySelector('.left');
const middle = document.querySelector('.middle');
const right = document.querySelector('.right');
const container = document.querySelector('.container');
left.addEventListener('mouseenter', () => {
container.classList.add('hover-left');
});
left.addEventListener('mouseleave', () => {
container.classList.remove('hover-left');
});
middle.addEventListener('mouseenter', () => {
container.classList.add('hover-middle');
});
middle.addEventListener('mouseleave', () => {
container.classList.remove('hover-middle');
});
right.addEventListener('mouseenter', () => {
container.classList.add('hover-right');
});
right.addEventListener('mouseleave', () => {
container.classList.remove('hover-right');
});
:root {
--container-bg-color: #333;
--left-bg-color: rgba(223, 39, 39, 0.7);
--left-button-hover-color: rgba(161, 11, 11, 0.3);
--middle-bg-color: #ededed;
--middle-button-hover-color: #ffba00;
--right-bg-color: rgba(43, 43, 43, 0.8);
--right-button-hover-color: rgba(92, 92, 92, 0.3);
--hover-width: 66%;
--other-width: 16.5%;
--speed: 1000ms;
}
html,
body {
padding: 0;
margin: 0;
font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif;
width: 100%;
height: 100%;
overflow-x: hidden;
}
h1 {
font-size: 4rem;
color: #fff;
position: absolute;
left: 50%;
top: 20%;
transform: translateX(-50%);
white-space: nowrap;
}
.button {
display: block;
position: absolute;
left: 50%;
top: 40%;
height: 2.5rem;
padding-top: 1.3rem;
width: 15rem;
text-align: center;
color: #fff;
border: #fff solid 0.2rem;
font-size: 1rem;
font-weight: bold;
text-transform: uppercase;
text-decoration: none;
transform: translateX(-50%);
}
.split.left .button:hover {
background-color: var(--left-button-hover-color);
border-color: var(--left-button-hover-color);
}
.split.middle .button:hover {
background-color: var(--middle-button-hover-color);
border-color: var(--middle-button-hover-color);
}
.split.right .button:hover {
background-color: var(--right-button-hover-color);
border-color: var(--right-button-hover-color);
}
.container {
position: relative;
width: 100%;
height: 100%;
background: var(--container-bg-color);
}
.split {
position: absolute;
width: 33%;
height: 100%;
overflow: hidden;
}
.split.left {
left: 0;
background: url(/img/design.jpeg) center center no-repeat;
background-size: cover;
}
.split.left:before {
position: absolute;
content: "";
width: 100%;
height: 100%;
background: var(--left-bg-color);
}
.split.middle {
left:33.3%;
background: url(/img/pexels.jpeg) center center no-repeat;
background-size: cover;
}
.split.middle:before {
position: absolute;
content: "";
width: 100%;
height: 100%;
background: var(--middle-bg-color);
}
.split.right {
right: 0;
background: url(/img/code.png) center center no-repeat;
background-size: cover;
}
.split.right:before {
position: absolute;
content: "";
width: 100%;
height: 100%;
background: var(--right-bg-color);
}
.split.left,
.split.right,
.split.middle,
.split.middle:before,
split.right:before,
split.left:before {
transition: var(--speed) all ease-in-out;
}
.hover-left .left {
width: var(--hover-width);
}
.hover-left .right {
width: var(--other-width);
}
.hover-left .middle {
width: var(--other-width)
}
.hover-left .right:before {
z-index: 1;
}
.hover-left .middle:before {
z-index: 2;
}
.hover-middle .middle {
width: var(--hover-width);
}
.hover-middle .left {
width: var(--other-width);
}
.hover-middle .right {
width: var(--other-width);
}
.hover-middle .right:before {
z-index: 1;
}
.hover-middle .left:before {
z-index: 2;
}
.hover-right .right {
width: var(--hover-width);
}
.hover-right .middle {
width: var(--other-width);
}
.hover-right .left {
width: var(--other-width);
}
.hover-right .left:before {
z-index: 1;
}
.hover-right .middle:before {
z-index: 2;
}
#media(max-width:800px) {
h1 {
font-size: 2rem;
}
.button {
width: 12rem;
}
}
#media(max-height:700px) {
.button {
top: 70%;
}
}
<div class="container">
<div class="split left">
<h1>The Designer</h1>
Read More
</div>
<div class="split middle">
<h1>The Noob</h1>
Read More
</div>
<div class="split right">
<h1>The Programmer</h1>
Read More
</div>
</div>

Couple of things.
First you'll want to move the middle div when hovering on the three divs and move it back when exiting:
left.addEventListener('mouseenter', () => {
container.classList.add('hover-left');
middle.style.left = "66.6666666%";
});
left.addEventListener('mouseleave', () => {
container.classList.remove('hover-left');
middle.style.left = "33.333333%";
});
middle.addEventListener('mouseenter', () => {
container.classList.add('hover-middle');
middle.style.left = "16.65%";
});
middle.addEventListener('mouseleave', () => {
container.classList.remove('hover-middle');
middle.style.left = "33.333333%";
});
right.addEventListener('mouseenter', () => {
container.classList.add('hover-right');
middle.style.left = "16.65%";
});
right.addEventListener('mouseleave', () => {
container.classList.remove('hover-right');
middle.style.left = "33.333333%";
});
Also, you'll want to change the --hover-width to be 66.6%.
:root {
--container-bg-color: #333;
--left-bg-color: rgba(223, 39, 39, 0.7);
--left-button-hover-color: rgba(161, 11, 11, 0.3);
--middle-bg-color: #ededed;
--middle-button-hover-color: #ffba00;
--right-bg-color: rgba(43, 43, 43, 0.8);
--right-button-hover-color: rgba(92, 92, 92, 0.3);
--hover-width: 66.6666666%;
--other-width: 16.65%;
--speed: 1000ms;
}
The problem with the space between the middle div and the right div is that 33.3 + 33.3 + 33.3 = 99.9. So, you'll have to make up the .1% somewhere. So, lets close the gap. Use 33.333333 instead.
View this codepen: https://codepen.io/bpuhnk/pen/wxWKjj

Related

My pre-loader is not working as expected, Animation not work

Want to create the pre-loader page, and have reference URL "https://www.priyaty.com/".
But somehow I'm not able to create the same loader as the above link.
I'm facing an issue when I applied the few CSS but, somehow I'm not matched with the above link loader.
can anyone help me out to build the same loader?
I'm using HTML, CSS, and JavaScript
function counter() {
var count = setInterval(function() {
var c = document.getElementById("counter")
int = parseInt(c.textContent);
c.textContent = (++int).toString();
if (int == 100) {
clearInterval(count);
c.classList.add("hide");
document.getElementById("preloader").classList.add("slide-up")
}
}, 40)
}
counter();
.preloader {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #000;
z-index: 9999;
display: flex;
justify-content: center;
align-items: center;
}
.preloader .preloaderp {
font-size: 5em;
font-weight: bold;
color: rgba(255, 255, 255, .05);
position: absolute;
padding: 15px;
text-align: center;
text-transform: uppercase;
}
.preloader.slide-up {
height: 0px;
transition: .5s;
transition-delay: 1s;
font-size: 0px;
}
.counter {
font-size: 5em;
color: #fff;
font-weight: bold;
}
.counter.hide {
opacity: 0;
transition: 1s;
}
.counter::after {
content: "%";
font-size: .5em;
}
#media only screen and (max-width: 575px) {
.preloaderp {
font-size: 2em;
}
.counter {
font-size: 2em;
}
}
<div class="preloader" id="preloader">
<p class="preloaderp">Loading</p>
<div class="counter" id="counter">
0
</div>
</div>
Were you looking for this?
var counting = setInterval(function() {
var loader = document.getElementById("loader");
var currval = parseInt(loader.innerHTML);
var Width = 100 - currval;
var loadscreen = document.getElementById("loadscreen");
loader.innerHTML = ++currval;
if (currval === 100) {
clearInterval(counting);
loadscreen.style.display = "none";
}
loadscreen.style.transition = "0.1s";
loadscreen.style.width = Width + "%";
}, 10);
.loading-screen {
width: 100%;
height: 100%;
}
.loader {
font-size: 50px;
font-family: Arial;
position: fixed;
left: 45%;
z-index: 1000;
color: red;
}
.loader:after {
content: " %";
font-size: 100%;
}
.after-load {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: black;
color: white;
text-align: center;
border: none;
}
<div class="loading-screen"></div>
<div class="after-load" id="loadscreen">
<div class="loader" style="top: 50%;" id="loader">0</div>
</div>

Lazy load animation on scroll down (and remove extra javascript libraries)

I'm having an issue that I'm hoping someone decent at Javascript can help with.
I have this pen:
https://codepen.io/connecteev/pen/ewYNBe
But I want this section to show up at the BOTTOM of the webpage, and only start animating when the section becomes visible on the page (desktop or mobile).
I want to change this pen to:
load this animation only on scrolling down to the section (lazy load)
if possible, use vanilla Javascript, and remove the extraneous libraries like:
https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.2/TweenMax.min.js
https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.2/plugins/CSSRulePlugin.min.js
Code:
HTML:
<div class="content">
</div>
<div class="Container">
<ul class="BlogList">
<li class="ArticleTeaser">
<h3 class="ArticleTeaser-title">PolyNo?</h3>
<div class="ArticleTeaser-bubble"></div>
<div class="ArticleTeaser-date">November 15th, 2015</div>
</li>
<li class="ArticleTeaser">
<h3 class="ArticleTeaser-title">BoomQueries - Element Queries, Today</h3>
<div class="ArticleTeaser-bubble"></div>
<div class="ArticleTeaser-date">April 24th, 2015</div>
</li>
<li class="ArticleTeaser">
<h3 class="ArticleTeaser-title">Reference SVGs Like the Cool Kids</h3>
<div class="ArticleTeaser-bubble"></div>
<div class="ArticleTeaser-date">October 14th, 2014</div>
</li>
<li class="ArticleTeaser">
<h3 class="ArticleTeaser-title">Modifying SVG Background Fills</h3>
<div class="ArticleTeaser-bubble"></div>
<div class="ArticleTeaser-date">September 29th, 2014</div>
</li>
</ul>
</div>
CSS:
html {
height: 100%;
}
body {
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI","Roboto","Oxygen","Ubuntu","Cantarell","Open Sans","Helvetica Neue",sans-serif;
letter-spacing: 0;
font-weight: 400;
font-style: normal;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-moz-font-feature-settings: "liga" on;
color: #686868;
font-size: 15px;
line-height: 1.4;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
box-sizing: border-box;
min-height: 100%;
}
body *, body *:before, body *:after {
box-sizing: inherit;
}
.Container {
max-width: 800px;
margin: 0 auto;
padding: 0 16px;
}
.BlogList {
padding: 16px 0;
margin: 0;
list-style: none;
position: relative;
}
#media (max-width: 767px) {
.BlogList {
padding: 32px 0;
}
}
.BlogList:before {
content: '';
position: absolute;
top: 0;
left: 50%;
-webkit-transform: translateX(-50%);
transform: translateX(-50%);
background: #0177FA;
width: 8px;
height: 8px;
border-radius: 50%;
}
.BlogList:after {
content: '';
position: absolute;
top: 0;
bottom: 0;
left: 50%;
-webkit-transform: translateX(-50%);
transform: translateX(-50%);
background: #0177FA;
width: 2px;
}
.ArticleTeaser {
position: relative;
padding: 32px 0;
z-index: 2;
visibility: hidden;
}
#media (max-width: 767px) {
.ArticleTeaser {
text-align: center;
background: #fff;
border-radius: 3px;
padding: 16px;
border: 2px solid #0177FA;
}
.ArticleTeaser:first-child {
margin-top: 16px;
}
.ArticleTeaser + * {
margin-top: 32px;
}
}
#media (min-width: 768px) {
.ArticleTeaser {
display: flex;
align-items: center;
}
.ArticleTeaser:before {
opacity: 0 !important;
}
}
.ArticleTeaser:hover .ArticleTeaser-bubble:before {
background: #0177FA;
}
.ArticleTeaser:last-child:after {
content: '';
position: absolute;
bottom: -16px;
left: 50%;
-webkit-transform: translateX(-50%);
transform: translateX(-50%);
background: #0177FA;
width: 8px;
height: 8px;
border-radius: 50%;
visibility: visible;
}
#media (max-width: 767px) {
.ArticleTeaser:last-child:after {
bottom: -40px;
}
}
.ArticleTeaser a {
color: #686868;
text-decoration: none;
}
.ArticleTeaser-bubble {
width: 16px;
height: 16px;
border-radius: 50%;
background: #fff;
border: 2px solid #0177FA;
-webkit-transform-origin: 50% 50%;
transform-origin: 50% 50%;
position: relative;
z-index: 1;
}
.ArticleTeaser-bubble:before {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: #fff;
border-radius: 50%;
transition: background 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
z-index: 1;
}
#media (min-width: 768px) {
.ArticleTeaser-bubble:after {
content: '';
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
width: 32px;
height: 2px;
background: rgba(1, 119, 250, 0.25);
z-index: -1;
}
}
#media (max-width: 767px) {
.ArticleTeaser-bubble {
position: absolute;
top: 0;
left: 50% !important;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
}
.ArticleTeaser-title {
margin: 0;
}
#media (min-width: 768px) {
.ArticleTeaser-title {
margin: 0 32px 0 0;
text-align: right;
width: 200px;
}
}
#media (min-width: 768px) {
.ArticleTeaser-date {
color: #a8a8a8;
margin: 0 0 0 32px;
width: 200px;
}
}
JS:
var optimizedResize = (function() {
var callbacks = [],
running = false;
// fired on resize event
function resize() {
if (!running) {
running = true;
if (window.requestAnimationFrame) {
window.requestAnimationFrame(runCallbacks);
} else {
setTimeout(runCallbacks, 66);
}
}
}
// run the actual callbacks
function runCallbacks() {
callbacks.forEach(function(callback) {
callback();
});
running = false;
}
// adds callback to loop
function addCallback(callback) {
if (callback) {
callbacks.push(callback);
}
}
return {
// public method to add additional callback
add: function(callback) {
if (!callbacks.length) {
window.addEventListener('resize', resize);
}
addCallback(callback);
}
}
}());
var forEach = function (array, callback, scope) {
for (var i = 0; i < array.length; i++) {
callback.call(scope, i, array[i]); // passes back stuff we need
}
};
var $articles = document.querySelectorAll('.ArticleTeaser');
setTimeout( run, 500 );
// Do the dew
function run() {
forEach($articles, function(index, value) {
articleAnim(value, index);
articleHover(value);
});
}
// Individual teaser animation
function articleAnim(element, count) {
var at = new TimelineMax();
at
.set(element, {
visibility: 'visible'
})
.from(element.querySelector('.ArticleTeaser-bubble'), .5, {
scale: 0,
delay: (count * .75),
ease: Elastic.easeOut.config(1.5, 1)
}, 'article-bubble')
.from(element, .5, {
delay: (count * .75),
opacity: 0,
ease: Elastic.easeOut.config(1.5, 1)
}, 'article-bubble')
.from(element.querySelector('.ArticleTeaser-title'), .5, {
x: '25%',
opacity: 0,
ease: Elastic.easeOut.config(1.5, 1)
}, 'article-teaser')
.from(element.querySelector('.ArticleTeaser-date'), .5, {
x: '-25%',
opacity: 0,
ease: Elastic.easeOut.config(1.5, 1)
}, 'article-teaser');
}
// Hover animation
function articleHover(element) {
var $articleLink = element.querySelector('.ArticleTeaser-title a');
element.timeline = new TimelineMax({ paused: true });
element.timeline
.to(element.querySelector('.ArticleTeaser-bubble'), 0.15, {
scale: 1.25
});
$articleLink.addEventListener('mouseenter', function() {
element.timeline.play();
}, false);
$articleLink.addEventListener('mouseleave', function() {
element.timeline.reverse();
}, false);
}
// Reset transform position for article bubble on resize
optimizedResize.add(function() {
forEach($articles, function(index, value) {
if (window.matchMedia('(min-width: 768px)').matches) {
TweenMax.set(value.querySelector('.ArticleTeaser-bubble'), {
x: '0%',
y: '0%'
});
} else {
TweenMax.set(value.querySelector('.ArticleTeaser-bubble'), {
x: '-50%',
y: '-50%'
});
}
});
});
Dependant on browser support I would suggest Intersection observers if you are looking for a clean vanilla JS approach.
If IE11 is still a requirement there is a reliable polyfill available from W3C.
Hope this helps.

How to Toggle Multiple divs with defferent effect on each div

I have a multiple divs each has its own position. what I want is to toggle each div when a text inside the div is clicked I am new in Javascript so please bear with me. I know how to do it by just toggling one div like i did below.
var para = document.querySelectorAll('.wrap div p');
for (var i = 0; i < para.length; i++) {
para[i].addEventListener('click', expand);
}
function expand(e) {
if ((e.target === para[2]) && (document.querySelector('.wrap #three').style.width === '15%')) {
document.querySelector('.wrap #three').style.width = '100%';
}else{
document.querySelector('.wrap #three').style.width = '15%';
}
}
I also tried using if else statement but it just expands the div I couldn't shrink it back to its position.. I know there is an easy way to achieve this but I couldn't figure out.
var para = document.querySelectorAll('.wrap div p');
for (var i = 0; i < para.length; i++) {
para[i].addEventListener('click', expand);
}
function expand(e) {
if (e.target === para[0]) {
document.querySelector('.wrap #one').style.width = '100%';
} else if (e.target === para[1]) {
document.querySelector('.wrap #two').style.width = '100%';
} else if (e.target === para[2]) {
document.querySelector('.wrap #three').style.width = '100%';
} else if (e.target === para[3]) {
document.querySelector('.wrap #four').style.width = '100%';
} else if (e.target === para[4]) {
document.querySelector('.wrap #five').style.width = '100%';
} else if (e.target === para[5]) {
document.querySelector('.wrap #six').style.width = '100%';
} else if (e.target === para[6]) {
document.querySelector('.wrap #seven').style.width = '100%';
}
}
.wrap {
position: relative;
width: 100%;
height: 100vh;
background: white;
display: flex;
flex-direction: row;
}
.wrap div {
position: relative;
height: 100%;
overflow: hidden;
background: #fdfdfd;
transition: 0.2s ease-in;
box-shadow: 0 0 40px rgba(0, 0, 0, 0.7);
}
.wrap div:before {
content: '';
position: absolute;
width: 250px;
height: 250px;
right: -150px;
top: 27%;
background: red;
border-radius: 50%;
cursor: pointer;
}
.wrap p {
position: absolute;
top: 40%;
cursor: pointer;
transform: rotate(-90deg);
font-size: 25px;
font-weight: bold;
color: white;
font-family: 'Halvetica', sans-serif;
}
.wrap #one {
position: absolute;
width: 21%;
}
.wrap #one:before {
background: #FF1D55;
}
.wrap #one p {
right: -8px;
}
.wrap #two {
position: absolute;
width: 18%;
}
.wrap #two:before {
background: #FFE31A;
}
.wrap #two p {
right: -23px;
}
.wrap #three {
position: absolute;
width: 15%;
}
.wrap #three:before {
background: #00E2AA;
}
.wrap #three p {
right: 2px;
}
.wrap #four {
position: absolute;
width: 12%;
}
.wrap #four:before {
background: #B90CB4;
}
.wrap #four p {
right: -13px;
}
.wrap #five {
position: absolute;
width: 9%;
}
.wrap #five:before {
background: #FF3400;
}
.wrap #five p {
right: -5px;
}
.wrap #six {
position: absolute;
width: 6%;
}
.wrap #six:before {
background: #30B7E2;
}
.wrap #six p {
right: -18px;
}
.wrap #seven {
position: absolute;
width: 3%;
}
.wrap #seven:before {
background: #220054;
}
.wrap #seven p {
right: -12px;
}
<div class="wrap">
<div id="one">
<p>About</p>
</div>
<div id="two">
<p>Services</p>
</div>
<div id="three">
<p>Blog</p>
</div>
<div id="four">
<p>Follow</p>
</div>
<div id="five">
<p>Team</p>
</div>
<div id="six">
<p>Contact</p>
</div>
<div id="seven">
<p>History</p>
</div>
</div>
I hope I explain everything clearly. any help would be greatly appreciated
Use classList.add/remove instead of adding inline style through javascript.
In your code you are attaching event to p which occupy a very small area, I have added a class p so that it's background can be visible and it will be easy to click.
Also you dont need to target each element and add class to it.
In this example get the target element and it's parent and toggle class
var para = document.querySelectorAll('.wrap div p');
for (let i = 0; i < para.length; i++) {
para[i].addEventListener('click', expand);
}
function expand(e) {
if (e.target.parentNode.classList.contains('fullWidth')) {
e.target.parentNode.classList.remove('fullWidth')
} else {
e.target.parentNode.classList.add('fullWidth')
}
}
.wrap {
position: relative;
width: 100%;
height: 100vh;
background: white;
display: flex;
flex-direction: row;
}
.wrap div {
position: relative;
height: 100%;
overflow: hidden;
background: #fdfdfd;
transition: 0.2s ease-in;
box-shadow: 0 0 40px rgba(0, 0, 0, 0.7);
}
.wrap div:before {
content: '';
position: absolute;
width: 250px;
height: 250px;
right: -150px;
top: 27%;
background: red;
border-radius: 50%;
cursor: pointer;
}
.wrap p {
position: absolute;
top: 40%;
cursor: pointer;
transform: rotate(-90deg);
font-size: 25px;
font-weight: bold;
color: white;
font-family: 'Halvetica', sans-serif;
}
.wrap #one {
position: absolute;
width: 21%;
}
.wrap #one:before {
background: #FF1D55;
}
.wrap #one p {
right: -8px;
}
.wrap #two {
position: absolute;
width: 18%;
}
.wrap #two:before {
background: #FFE31A;
}
.wrap #two p {
right: -23px;
}
.wrap #three {
position: absolute;
width: 15%;
}
.wrap #three:before {
background: #00E2AA;
}
.wrap #three p {
right: 2px;
}
.wrap #four {
position: absolute;
width: 12%;
}
.wrap #four:before {
background: #B90CB4;
}
.wrap #four p {
right: -13px;
}
.wrap #five {
position: absolute;
width: 9%;
}
.wrap #five:before {
background: #FF3400;
}
.wrap #five p {
right: -5px;
}
.wrap #six {
position: absolute;
width: 6%;
}
.wrap #six:before {
background: #30B7E2;
}
.wrap #six p {
right: -18px;
}
.wrap #seven {
position: absolute;
width: 3%;
}
.wrap #seven:before {
background: #220054;
}
.wrap #seven p {
right: -12px;
}
p {
background: greenyellow
}
.fullWidth {
width: 100% !important;
}
<div class="wrap">
<div id="one">
<p>About</p>
</div>
<div id="two">
<p>Services</p>
</div>
<div id="three">
<p>Blog</p>
</div>
<div id="four">
<p>Follow</p>
</div>
<div id="five">
<p>Team</p>
</div>
<div id="six">
<p>Contact</p>
</div>
<div id="seven">
<p>History</p>
</div>
</div>

How can I make this transition smooth instead of it jumping up

I am trying to implement a notification system in my app without the use of a library. Here is a gif of the issue: https://imgur.com/oRc11dM
And here is the jsfiddle of the gif: https://jsfiddle.net/w9yk7n54/
When you click on new notification button, already displayed notifications jump up to make room for the new notification and new notification slides in. I was wondering how I could make it so that they all smoothly go up together.
The notifications wont all be the same dimensions so I cant set static values for height/etc.
Thank you!
let btn = document.querySelector('button')
let container = document.querySelector('.notifications-container')
let notif_contents = [
"<p>1</p><p>1</p><p>1</p><p>1</p>",
"<p>test</p>",
"<div><h1>testtesttest</h1><p>yoloalsdfasdf</p></div>"
]
let current = 0
btn.onclick = () => {
let notif = document.createElement('div')
notif.classList.add('notif')
notif.innerHTML = notif_contents[current]
notif.addEventListener('animationend', () => {
notif.parentElement.removeChild(notif)
})
current++
container.append(notif)
}
* {
box-sizing: border-box;
}
.container {
height: 300px;
width: 400px;
border: 1px solid black;
position: absolute;
}
.notifications-container {
position: absolute;
top: 0;
right: 0;
height: 100%;
width: 200px;
background: rgba( 0, 0, 0, 0.2);
display: flex;
flex-flow: column nowrap;
justify-content: flex-end;
overflow: hidden;
}
.notif {
position: relative;
width: 100%;
padding: 10px;
border: 1px solid black;
animation: notifAnim 5s forwards;
transition: all .2s;
background: white;
}
button {
z-index: 100;
background: lightcoral;
color: white;
border: none;
padding: 10px;
font-size: 20px;
margin: 5px;
}
#keyframes notifAnim {
0% {
transform: translateY( 100%)
}
20% {
transform: translateY( 0)
}
80% {
transform: translateY( 0)
}
100% {
transform: translateY( 100%)
}
}
<div class="container">
<button>New Notification</button>
<div class="notifications-container"></div>
</div>
Your notif container has justify-content: flex-end. This means that whenever you add a new one, the previous ones will be pushed up with the height of the new one.
The "fix" is to give each element a negative margin-top equal to its height and integrate in your current transition getting margin-top back to 0.
Example:
let btn = document.querySelector('button'),
container = document.querySelector('.notifications-container'),
notif_contents = [
"<p>1</p><p>1</p><p>1</p><p>1</p>",
"<p>test</p>",
"<div><h1>testtesttest</h1><p>yoloalsdfasdf</p></div>",
"<code>another.test()</code>",
"<strong>another</strong> <i>test</i>"
]
btn.onclick = () => {
let notif = document.createElement('div'),
index = Math.floor(Math.random() * notif_contents.length)
notif.classList.add('notif')
notif.innerHTML = notif_contents[index]
notif.addEventListener('animationend', () => {
notif.parentElement.removeChild(notif)
})
container.append(notif)
notif.style.marginTop = '-' + notif.offsetHeight + 'px'
}
* {
box-sizing: border-box;
}
.container {
height: 300px;
width: 400px;
border: 1px solid #888;
position: absolute;
}
.notifications-container {
position: absolute;
top: 0;
right: 0;
height: 100%;
width: 200px;
background: rgba( 0, 0, 0, 0.2);
display: flex;
flex-flow: column nowrap;
justify-content: flex-end;
overflow: hidden;
}
.notif {
position: relative;
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-bottom: none;
animation: notifAnim 5s forwards;
background: white;
}
button {
z-index: 100;
background: lightcoral;
color: white;
border: none;
padding: 10px;
font-size: 20px;
margin: 5px;
}
#keyframes notifAnim {
0%,
100% {
transform: translateY( 100%)
}
20%,
80% {
transform: translateY( 0);
margin-top: 0
}
}
<div class="container">
<button>New Notification</button>
<div class="notifications-container"></div>
</div>
An idea is to insert new element with a height equal to 0 and you animate the height in addition to translate. Of course, you should use max-height since height are unknown and we cannot animate to auto:
let btn = document.querySelector('button')
let container = document.querySelector('.notifications-container')
let notif_contents = [
"<p>1</p><p>1</p><p>1</p><p>1</p>",
"<p>test</p>",
"<div><h1>testtesttest</h1><p>yoloalsdfasdf</p></div>"
]
let current = 0
btn.onclick = () => {
let notif = document.createElement('div')
notif.classList.add('notif')
notif.innerHTML = notif_contents[current]
notif.addEventListener('animationend', () => {
notif.parentElement.removeChild(notif)
})
current++
container.append(notif)
}
* {
box-sizing: border-box;
}
.container {
height: 300px;
width: 400px;
border: 1px solid black;
position: absolute;
}
.notifications-container {
position: absolute;
top: 0;
right: 0;
height: 100%;
width: 200px;
background: rgba( 0, 0, 0, 0.2);
display: flex;
flex-flow: column nowrap;
justify-content: flex-end;
overflow: hidden;
}
.notif {
position: relative;
width: 100%;
padding:0 10px;
max-height:0px;
border: 1px solid black;
animation: notifAnim 5s forwards;
transition: all .2s;
background: white;
}
button {
z-index: 100;
background: lightcoral;
color: white;
border: none;
padding: 10px;
font-size: 20px;
margin: 5px;
}
#keyframes notifAnim {
0% {
transform: translateY( 100%);
max-height:0;
padding:0 10px;
}
30% {
transform: translateY( 0);
max-height:300px;
padding:10px;
}
80% {
transform: translateY( 0);
max-height:300px;
padding:10px;
}
100% {
transform: translateY( 100%);
max-height:300px;
padding:10px;
}
}
<div class="container">
<button>New Notification</button>
<div class="notifications-container"></div>
</div>

Unknown JavaScript Error - Function only runs first line of code

I have no idea why, but the function thumbsScroll only runs the first alert, and then stops. It doesn't even show the 2nd alert.
The function is supposed to hide the 'scroll' divs when the number of thumbs is less than 5.
Probably a very simple problem, but actually can't find a solution to this, and have spent a lot of time trying to find out. Is there something I'm not getting here?
var mainImg = document.getElementById("main-image");
function thumb1() {
mainImg.style.backgroundImage = "url('https://cml.sad.ukrd.com/image/394545.jpg')";
}
function thumb2() {
mainImg.style.backgroundImage = "url('https://cml.sad.ukrd.com/image/572806.jpg')";
}
function thumb3() {
mainImg.style.backgroundImage = "url('https://cml.sad.ukrd.com/image/486757.jpg')";
}
function thumb4() {
mainImg.style.backgroundImage = "url('https://cml.sad.ukrd.com/image/612357.jpg')";
}
function thumb5() {
mainImg.style.backgroundImage = "url('https://cml.sad.ukrd.com/image/612358.jpg')";
}
function thumb6() {
mainImg.style.backgroundImage = "url('https://cml.sad.ukrd.com/image/661833.jpg')";
}
function thumbsScroll() {
alert('test - function runs');
var thumbs = document.getElementByClassName('image-thumb');
var desktopThumbsScroll = document.getElementById('scroll-desktop');
var mobileThumbsScroll = document.getElementById('scroll-mobile');
alert('test alert 2 - doesnt work');
if (thumbs.length < 5) {
desktopThumbsScroll.style.display = 'none';
mobileThumbsScroll.style.display = 'none';
alert('if true')
} else {alert('if false')}
}
thumbsScroll();
/* rollovers */
#main-image {
background-image: url('https://cml.sad.ukrd.com/image/661835.jpg');
}
#thumb1 { background-image: url('https://cml.sad.ukrd.com/image/394545.jpg') }
#thumb2 { background-image: url('https://cml.sad.ukrd.com/image/572806.jpg') }
#thumb3 { background-image: url('https://cml.sad.ukrd.com/image/486757.jpg') }
#thumb4 { background-image: url('https://cml.sad.ukrd.com/image/612357.jpg') }
#thumb5 { background-image: url('https://cml.sad.ukrd.com/image/612358.jpg') }
#thumb6 { background-image: url('https://cml.sad.ukrd.com/image/661833.jpg') }
/* rollovers */
* {
margin: 0;
padding: 0;
font-family: arial;
line-height: 1.5em;
box-sizing: border-box;
}
#images-and-hook-container {
width: 100%;
height: auto;
float: left;
background: cyan;
display: flex; /* allows hook container to be full height */
}
#hook-container {
background: blue;
float: left;
width: 40%;
height: auto;
padding: 3% 0 0 3%;
}
#images-wrap {
width: 60%;
height: auto;
float: left;
position: relative;
}
#scroll-desktop {
position: absolute;
bottom: -6%;
right: 5%;
font-size: 0.5em;
text-transform: uppercase;
opacity: 0.5;
}
#scroll-desktop > span { font-size: 1.5em }
#scroll-mobile { display: none }
#main-image {
width: 79%;
float: left;
background-size: cover !important;
background-position: center center !important;
height: auto;
padding-bottom: 53.666%;
}
#image-thumbs {
width: 19%;
height: auto;
float: left;
margin-left: 2%;
overflow-y: auto !important;
overflow-x: hidden;
position: absolute;
right: 0;
height: 100%;
}
.image-thumb {
margin-bottom: 6%;
background-position: center center;
background-size: cover;
width: 100%;
height: auto;
padding-bottom: 66.666%;
}
.image-thumb:last-of-type { margin-bottom: 0 }
#media (max-width: 768px) {
body { background: red }
#images-and-hook-container {
flex-direction: column;
}
#images-wrap {
position: static;
width: 100%;
}
#scroll-desktop { display: none }
#scroll-mobile {
display: block;
background: yellow;
width: 100%;
text-align: center;
text-transform: uppercase;
font-size: 0.5em;
opacity: 0.5;
}
#scroll-mobile > span { font-size: 1.5em }
#hook-container {
width: 100%;
padding: 3% 0;
}
#main-image {
width: 100%;
padding-bottom: 66.666%;
margin-bottom: 1%;
}
#image-thumbs {
width: 100%;
margin-left: 0;
top: 0;
left: 0;
display: flex;
flex-wrap: nowrap;
overflow-x: scroll;
overflow-y: hidden !important;
}
.image-thumb {
float: left;
margin-bottom: 6px;
width: 24.333%;
padding-bottom: 16.666%;
flex: 0 0 24.333%;
margin-left: 1%;
}
.image-thumb:first-of-type { margin-left: 0 }
#aspect-ratio-wrap {
float: left;
width: 100%;
height: auto;
padding-bottom: 16.666%;
background: orange;
position: relative;
overflow-x: scroll;
overflow-y: hidden;
}
}
#media (max-width: 400px) {
#scroll-mobile { font-size: 0.25em }
#scroll-mobile > span { font-size: 1em }
}
#media (min-width: 1000px) {
#scroll-desktop {
bottom: -5%;
right: 6%;
}
}
<div id='images-and-hook-container'>
<div id="images-wrap">
<div id="main-image"></div>
<div id='aspect-ratio-wrap'>
<div id="image-thumbs">
<div class="image-thumb" id="thumb1" onmouseover="thumb1()"></div>
<div class="image-thumb" id="thumb2" onmouseover="thumb2()"></div>
<div class="image-thumb" id="thumb3" onmouseover="thumb3()"></div>
<div class="image-thumb" id="thumb4" onmouseover="thumb4()"></div>
<div class="image-thumb" id="thumb5" onmouseover="thumb5()"></div>
<div class="image-thumb" id="thumb6" onmouseover="thumb6()"></div>
</div>
</div>
<div id='scroll-desktop'>Scroll <span>↓</span></div>
</div>
<div id='scroll-mobile'>Scroll <span>→</span></div>
<div id='hook-container'>
hook container
</div>
</div>
You should definitely keep your eye on the JavaScript console. This is the first place to look when something doesn't work. The console will try to give you hints about the errors in your code.
Memorize the shortcut, the console in chrome on windows: ctrl-shift-j.
When running your provided script the console will tell you that it didn't understand getElementByClassName:
You mis-typed
getElementByClassName
it should be
getElementsByClassName
There is no a function like getElementByClassName. You can use document.getElementsByClassName('image-thumb') to achieve your goal.

Categories

Resources