I need the menu items to look like they are now (like in iOS), but so far I have two big problems.
First, when I try to click on one of the links, it's not possible because of my linear-gradient. And second, when I click the down arrow to explore other menu items, all the gradient does not work.
How can I make it work properly?
I have also made a codepen for this
document.querySelectorAll('.slide').forEach(function (next) {
next.addEventListener('click', function () {
var container = this.parentElement.querySelector('.select');
sideScroll(container, 'bottom', 20, 25, 15);
});
});
document.querySelectorAll('.slideBack').forEach(function (back) {
back.addEventListener('click', function () {
var container = this.parentElement.querySelector('.select');
sideScroll(container, 'top', 20, 25, 15);
});
});
function sideScroll(element, direction, speed, distance, step) {
scrollAmount = 0;
var slideTimer = setInterval(function () {
if (direction == 'top') {
element.scrollTop -= step;
} else {
element.scrollTop += step;
}
scrollAmount += step;
if (scrollAmount >= distance) {
window.clearInterval(slideTimer);
}
}, speed);
}
* {
background: #80acdc;
}
.larger {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.larger .select {
width: 240px;
height: 270px;
display: flex;
flex-direction: column;
text-align: center;
overflow-y: hidden;
-ms-overflow-style: scroll;
scrollbar-width: none;
position: relative;
}
.larger .select::after {
content: '';
position: absolute;
display: block;
width: 100%;
height: 100%;
top: 0;
left: 0;
background-image: linear-gradient(#80acdc, transparent, #80acdc);
}
.larger .select a {
color: white;
margin: 3.5px 0;
}
.larger .select a:first-child {
margin-top: 0;
}
.larger #slide {
position: absolute;
left: 47%;
bottom: 38px;
color: #fff;
font-size: 15px;
cursor: pointer;
}
.larger #slideBack {
position: absolute;
top: 38px;
left: 47%;
color: #fff;
font-size: 15px;
cursor: pointer;
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css">
<div class="container">
<div class="row">
<div class="col-lg-3">
<div class="larger">
<div class="select">
Action Lorem
Test Text
Action Lorem
Test Text
Action Lorem
Test Text
Action Lorem
Test Text
Action Lorem
Test Text
Action Lorem
Test Text
Action Lorem
Test Text
Action Lorem
Test Text
</div>
<i id="slideBack" class="slideBack fas fa-chevron-up"></i>
<i id="slide" class="slide fas fa-chevron-down"></i>
</div>
</div>
</div>
</div>
For the gradient to allow interaction with the underling elements you can use pointer-events: none
Your gradient is absolute positioned with top: 0 so it goes together with the scroll. In order to fix this you can set the position of the gradient to fixed (but then it will be stretched to the sizes of the vewport). The better way would be to wrap the list of the options with another container so the scroll won't influence the gradient position.. Something like this:
<div class="select-wrap">
<div class="select">
...
</div>
</div>
.larger .select-wrap {
width: 240px;
height: 270px;
}
.larger .select-wrap .select {
height: 100%;
display: flex;
flex-direction: column;
text-align: center;
overflow-y: hidden;
-ms-overflow-style: scroll;
scrollbar-width: none;
position: relative;
}
.larger .select-wrap::after {
content: '';
position: absolute;
display: block;
width: 100%;
height: 100%;
top: 0;
left: 0;
background-image: linear-gradient(#80acdc, transparent, #80acdc);
pointer-events: none; /* this allows for the mouse clicks go through */
}
document.querySelectorAll('.slide').forEach(function(next) {
next.addEventListener('click', function() {
var container = this.parentElement.querySelector('.select');
sideScroll(container, 'bottom', 20, 25, 15);
});
});
document.querySelectorAll('.slideBack').forEach(function(back) {
back.addEventListener('click', function() {
var container = this.parentElement.querySelector('.select');
sideScroll(container, 'top', 20, 25, 15);
});
});
function sideScroll(element, direction, speed, distance, step) {
scrollAmount = 0;
var slideTimer = setInterval(function() {
if (direction == 'top') {
element.scrollTop -= step;
} else {
element.scrollTop += step;
}
scrollAmount += step;
if (scrollAmount >= distance) {
window.clearInterval(slideTimer);
}
}, speed);
}
* {
background: #80acdc;
}
.larger {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.larger .select-wrap {
width: 240px;
height: 270px;
}
.larger .select-wrap .select {
height: 100%;
display: flex;
flex-direction: column;
text-align: center;
overflow-y: hidden;
-ms-overflow-style: scroll;
scrollbar-width: none;
position: relative;
}
.larger .select-wrap::after {
content: '';
position: absolute;
display: block;
width: 100%;
height: 100%;
top: 0;
left: 0;
background-image: linear-gradient(#80acdc, transparent, #80acdc);
pointer-events: none;
}
.larger .select a {
color: white;
margin: 3.5px 0;
}
.larger .select a:first-child {
margin-top: 0;
}
.larger #slide {
position: absolute;
left: 47%;
bottom: 38px;
color: #fff;
font-size: 15px;
cursor: pointer;
}
.larger #slideBack {
position: absolute;
top: 38px;
left: 47%;
color: #fff;
font-size: 15px;
cursor: pointer;
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css">
<div class="container">
<div class="row">
<div class="col-lg-3">
<div class="larger">
<div class="select-wrap">
<div class="select">
Action Lorem
Test Text
Action Lorem
Test Text
Action Lorem
Test Text
Action Lorem
Test Text
Action Lorem
Test Text
Action Lorem
Test Text
Action Lorem
Test Text
Action Lorem
Test Text
</div>
</div>
<i id="slideBack" class="slideBack fas fa-chevron-up"></i>
<i id="slide" class="slide fas fa-chevron-down"></i>
</div>
</div>
</div>
</div>
Related
So, I am currently building a website with HTML, CSS, and VanillaJS and the hamburger icon for the mobile menu does not work, because although I set it to a fixed position, when I am checking the responsivity of the screen on different device screen widths by decreasing the width itself the icon slips away and it just moves towards the left side of the page.
Is there any way to prevent this from happening?
//PICTURES
First, the hamicon can be seen
But as I start decreasing the width of the screen it disappears
//HERE IS MY HTML CODE
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="gallery.css">
<title>Eckert Művek Galéria</title>
</head>
<body>
<div class="floating-btn show-btn" aria-label="up button" role="button">
<img src="assets/svg_files/chevron-up-solid.svg" alt="up img" />
</div>
<header>
<nav>
<div class="logo">
<img class="header-logo" src="assets/icons/114533_321471.png" alt="">
</div>
<ul id="desktop-menu">
<li class="nav-item">Főoldal</li>
<li class="nav-item">Rólunk</li>
<li class="nav-item">Szolgáltatások</li>
<li class="nav-item">Miért mi?</li>
<li class="nav-item">Galéria</li>
<li class="nav-item">Kapcsolatok</li>
</ul>
<!--HAMBURGER ICON-->
<div class="header-right-gap">
<button class="hamburger" aria-label="hamburger button">
<div class="line line-1"></div>
<div class="line line-2"></div>
<div class="line line-3"></div>
</button>
</div>
</nav>
<!--MOBILE MENU-->
<div class="mobile-menu">
<ul class="m-menu">
<li >Főoldal</li>
<li >Rólunk</li>
<li >Szolgáltatások</li>
<li >Miért mi?</li>
<li >Galéria</li>
<li >Kapcsolat</li>
</ul>
</div>
</header>
<main class="carousel-container">
<div class="carousel-images">
<img src="assets\images\pavebrick\buckgrey.jpg" alt="img-1">
<img src="assets\images\pavebrick\colorful.jpg" alt="img-2">
<img src="assets\images\pavebrick\greybigplace.jpg" alt="img-3">
<img src="assets\images\pavebrick\colbig.jpg" alt="img-4">
<img src="assets\images\pavebrick\wheelgrey.jpg" alt="img-5">
<img src="assets\images\pavebrick\yardrock.jpg" alt="img-6">
</div>
<div class= "btn-container">
<div class="btn btn-left">
<img src="assets/svg_files/arrow-left-solid.svg" alt="left-arrow">
</div>
<div class="btn btn-right">
<img src="assets/svg_files/arrow-right-solid.svg" alt="right-arrow">
</div>
</div>
</main>
<footer>
<div class="footer-container">
<div class="footer-top">
<nav>
<ul>
<li>Főoldal</li>
<li>Rólunk</li>
<li>Szolgáltatások</li>
<li>Miért mi?</li>
<li>Galéria</li>
<li>Kapcsolatok</li>
</ul>
</nav>
<div class="text-container">
<h4>Ttitle-1</h4>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit.
Dicta modi laborum quibusdam quis natus debitis qui dolor
voluptatibus ab sit, cum saepe enim unde doloribus veniam
numquam perspiciatis optio impedit.</p>
</div>
<div class="text-container">
<h4>Ttitle-1</h4>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit.
Dicta modi laborum quibusdam quis natus debitis qui dolor
voluptatibus ab sit, cum saepe enim unde doloribus veniam
numquam perspiciatis optio impedit.</p>
</div>
</nav>
</div>
<!--Social media icons-->
<div class="social-media-icons">
<div class="sm-container" id="insta">
<div class="sm-icon">
</div>
</div>
<div class="sm-container" id="github">
<div class="sm-icon">
</div>
</div>
<div class="sm-container" id="facebook">
<div class="sm-icon">
</div>
</div>
<div class="sm-container" id="linkedin">
<div class="sm-icon">
</div>
</div>
</div>
<!--Social media icons-->
<div class="footer-bottom">
<p>© Eckert Művek Kft. Minden jog fenntartva.</p>
</div>
</div>
</footer>
<script src="gallery.js"></script>
</body>
</html>
//AND HERE IS MY CSS CODE
/CSS RESET/
*, *::after, *::before { box-sizing: border-box; margin: 0; padding: 0; }
:root { --font-size: 18px; --bg-color-flt-btn: yellow; }
body { width: 100%; height: 100%; }
.floating-btn { position: fixed; bottom: 3.5vh; right: 0; width: 50px; height: 50px; z-index: 100; background-color: var(--bg-color-flt-btn); border-radius: 50%; padding: 10px; box-shadow: 0 0 5px hsla(0, 0%, 0%, hsla(0,0%,0%,0.5)); cursor: pointer; margin-right: 1rem; border: 1px solid #000; }
.show-btn { display: block; }
a { text-decoration: none; color: inherit; }
/HEADER STYLE/
header { width: 100%; height: 120px; background-color: black; color: white; display: flex; align-items: center; position: fixed; top: 0; left: 0; z-index: 10; }
/Srcollbar/
::-webkit-scrollbar{ width: 15px; background: #000; }
::-webkit-scrollbar-thumb { background: yellow; border-radius: 10px; border: 1px solid black; }
::-webkit-scrollbar-thumb:active { background: orangered; }
nav, .footer-container { width: min(90%, 1200px); display: flex; margin-inline: auto; position: relative;
}
nav { justify-content: space-between; /display: flex; flex-direction: flex-end; font-size: 30px;/
}
.nav-item a { color: var(--clr-nav-item-main); list-style: none; text-transform: uppercase; font-size: 20px; font-weight: bold; height: 100%; text-decoration: none; position: relative; margin: .5em .8em; padding: 10px;
}
/újonnan adtam hozzá 2023.01.12./ /nav a { position: relative; z-index: 1; justify-content: space-evenly; height: 100%; }/
nav ul { display: flex; gap: 1rem; width: 100%; justify-content: center; margin-top: 3.5rem;
/*margin-top: 2rem;*/
}
nav ul li { text-transform: uppercase; list-style: none;
}
.nav-item a::before, .nav-item a::after { content: ''; height: 14px; width: 14px; position: absolute; transition: all .35s ease; opacity: 0; }
nav a::before { content: ''; right: 0; top: 0; border-top: 3px solid #ffed4b; border-right: 3px solid #fdcd3b; transform: translate(-100%, 50%); /-100%, 50%/ }
.nav-item a:after { content: ''; left: 0; bottom: 0; border-bottom: 3px solid #fdcd3b; border-left: 3px solid #ffed4b; transform: translate(100%, -50%); /100%, -50%/ }
.nav-item a:hover:before, .nav-item a:hover:after{ transform: translate(0,0); opacity: 1; }
nav ul li a:hover { color: yellow; }
/Logo/
.logo img { position: absolute; width: 150px; height: 90px; margin-top: -2rem; margin-left: 70rem; left: 0; top: 0; }
/CAROUSEL SSTYLE/ /ha négy képünk van akkor ez 200 vw lesz/
.carousel-container { position: relative; width: 100%; height: 100vh; overflow: hidden;
}
`
/*transform: translateX(-200vw);*/
.carousel-images { transition: all 0.8s ease; width: 600vw; /700-zal és 800-zal is működik/ display: flex; height: 100%;
}
.carousel-images img { width: 100vw; height: 100%; object-fit: cover; }
.btn-container { position: absolute; display: flex; width: 100px; justify-content: space-between; bottom: 10vh; left: calc(50% - 75px); }
.btn { width: 40px; height: 40px; border: 2px solid #000; background-color: #fff; padding: 10px; border-radius: 10px;
}
.btn:hover { cursor: pointer; }
.btn img { width: 100%; height: 100%; }
/FOOTER STYLE/
footer { width: 100%; background-color: #000; padding-block: 4rem; color: white; }
.footer-container { flex-direction: column;
}
.footer-container nav ul { flex-direction: column; }
.footer-top { width: 100%; display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem;
}
.footer-bottom { margin-top: 3rem; text-align: center;
}
/SOCIAL MEDIA ICONS/
.social-media-icons { width: 100%; display: flex; justify-content: center; align-items: center; flex-direction: row;
}
.sm-container { display: flex; justify-content: center; flex-direction: row; gap: 2rem; padding:1rem; border: 1px black; }
.fa { border-radius: 50%; }
.fa-instagram { background: #125688; color: white; padding: 1rem;
}
.fa-github { background: white; color: black; padding: 1rem;
}
.fa-facebook { background: #4267B2; color: white; padding: 1rem; }
.fa-linkedin { background: #3B5998; color: white; padding: 1rem; }
/MOBILE MENU/ .mobile-menu { display: none; }
.mobile-menu { display: flex; width: 100%; /.line a szülő tehát 40px a width/ height: calc(100vh - 80px); align-items: center; justify-content: center; position: absolute; top: 80px; left: 0; background-color: black; transform: translate(-100%); transition: all 0.4s ease; z-index: 100; }
.mobile-menu-on { display: flex; /**/ transform: translate(0); }
.m-menu { display: flex; flex-direction: column; gap: 2rem; text-align: center; font-size: 1.4rem; list-style: none; }
/hamburger icon/
.hamburger { display: none; position: fixed; width: 50px; height: 50px; border: none; background-color: transparent; margin-left: -60rem; margin-top: -2rem;
/* margin-left: -4rem; margin-top: -1.5rem;*/
}
.hamburger:hover { border: 6px solid; border-color: yellow; width: 43px; /margin-left: 4px; transform: scale(1.2);/ } .hamburger:hover .line.line-1 { /display: none;/ transform: rotate(45deg) translateY(7.5px); background-color: yellow;
}
.hamburger:hover .line.line-2 {
display: none;
}
.hamburger:hover .line.line-3 {
/*display: none;*/
transform: rotate(-45deg) translateY(-7.5px);
background-color: yellow;
}
.line {
transition: all .4s ease;
width: 40px;
height: 5px;
background-color: white;
margin-block: 5px;
border-radius: 10px;
}
/RESPONSIVE VERSION/
#media (max-width: 1200px) {
.hamburger { display: block; }
#desktop-menu { display: none; }
}
#media (max-width: 900px) {
footer nav ul {
flex-direction: column;
}
footer nav ul li a { font-size: 15px; padding: 15px; } }
#media (max-width: 750px) { .footer-container { display: flex; flex-wrap: wrap; }
footer nav ul li a { font-size: 10px; padding: 15px; }
.text-container p { font-size: 10px; } }
#media (max-width: 600px) {
}
//AND MY JS CODE
// MOBILE MENU
const header = document.querySelector('header')
const btn = document.querySelector('.hamburger')
const menu = document.querySelector('.mobile-menu')
const line1 = document.querySelector('.line-1')
const line2 = document.querySelector('.line-2')
const line3 = document.querySelector('.line-3')
/*let navUl = docuemnt.querySelector('ul')*/
// FLOATING BUTTON
const floatingBtn = document.querySelector('.floating-btn');
window.addEventListener('scroll', ()=> {
if (document.documentElement.scrollTop > 400) {
floatingBtn.classList.add('show-btn')
} else {
floatingBtn.classList.remove('show-btn')
}
})
floatingBtn.addEventListener('click', () => {
document.documentElement.scrollTop = 0
})
//SCROLLING EFFECT
window.addEventListener('scroll', () => {
if (document.documentElement.scrollTop > 100) {
header.style.display = 'none'
} else {
header.style.display = 'block'
// navUl.style.marginTop = '32px'
}
})
btn.addEventListener('click', () => {
menu.classList.toggle('mobile-menu-on')
line1.classList.toggle('line-1-on')
line2.classList.toggle('line-2-on')
line3.classList.toggle('line-3-on')
})
//CAROUSEL
const btnLeft = document.querySelector('.btn-left');
const btnRight = document.querySelector('.btn-right');
const images = document.querySelector('.carousel-images');
let index = 0; // első kép
// képek mozgásának automatizálása (slide effect)
setInterval(()=> {
//slide(1) vagy függvényt teesszük csak be az alsó 5 sor helyett
if (index === 5) {
index = 0;
} else {
index++
}
images.style.transform = `translateX(-${100*index}vw)`
}, 5000)
console.log('.carousel-images')
const slide = (direction) => {
if (direction === 'left') {
if (index === 0) {
index = 5;
} else {
index--
}
} else if (direction === 'right') {
if (index === 5) {
index = 0;
} else {
index++
}
}
images.style.transform = `translateX(-${100*index}vw)`
}
btnLeft.addEventListener('click', () => {
//slide('left') vagy -1
if (index === 0) {
index = 5;
} else {
index--
}
images.style.transform = `translateX(-${100*index}vw)`
})
// ha az index 2 (4. elem) de az nincs, akkor ugrik vissza az első képre
btnRight.addEventListener('click', () => {
//slide('right') 1
if (index === 5) {
index = 0;
} else {
index++
}
images.style.transform = `translateX(-${100*index}vw)`
})
document.querySelector('#contact-form').addEventListener('submit', (e) => {
e.preventDefault();
e.target.elements.name.value = '';
e.target.elements.email.value = '';
e.target.elements.message.value = '';
});
Well, originally the hamicon was placed on the right side of the header. Since I have changed it, this kind of problem has arisen somewhy. I am still a beginner, but it is not the first time I am doing this, but still, I was unable to detect the source of the problem.
If somebody could give me some hints I would appreciate it!
Thank you very much in advance!
I made a div slider with arrows, each div is set to a min-width of 60px.
The code works just fine, except, when I navigate with the arrow either to the left or to the right, it stops at the last item. I want it to loop (as in endlessly). Instead of stopping at the last item.
let rightArrow = document.getElementById('right')
rightArrow.onclick = function() {
let container = document.getElementById('box')
sideScroll(container, 'right', 25, 80, 10)
}
let leftArrow = document.getElementById('left')
leftArrow.onclick = function() {
let container = document.getElementById('box')
sideScroll(container, 'left', 25, 80, 10)
}
function sideScroll(element, direction, speed, distance, step) {
// body...
scrollAmount = 0
let slideTimer = setInterval(function() {
// body...
if (direction == 'left') {
element.scrollLeft -= step
} else {
element.scrollLeft += step
}
scrollAmount += step
if (scrollAmount >= distance) {
window.clearInterval(slideTimer)
}
}, speed)
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-color: #efefef;
width: 100%;
height: 100vh;
background-image: radial-gradient(circle, #2196f3, #3f51b5);
font-family: 'Nirmala UI';
display: grid;
place-items: center;
}
div.main {
position: relative;
background-color: #fff;
border-radius: 10px;
}
div.main div.item_div {
width: 300px;
overflow: auto;
display: flex;
}
div.main div.item_div::-webkit-scrollbar {
display: none;
}
div.main div.item_div div.item {
min-width: 60px;
min-height: 60px;
border-radius: 10px;
background-color: grey;
display: grid;
place-items: center;
font-size: 40px;
text-transform: uppercase;
scroll-behavior: smooth;
user-select: none;
}
div.main div.item_div div.item:not(:last-child) {
margin-right: 20px;
}
div.arrow {
position: absolute;
width: 40px;
height: 40px;
background-color: #f0f0f0;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
top: 50%;
transform: translateY(-50%);
}
div#left {
left: -60px;
}
div#right {
right: -60px;
}
div.arrow span {
font-size: 20px;
user-select: none;
}
div.arrow:hover {
cursor: pointer;
}
<div class="main">
<div class="item_div" id="box">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
<div class="item">10</div>
</div>
<div class="arrow" id="left"><span>❮</span></div>
<div class="arrow" id="right"><span>❯</span></div>
</div>
Can anyone help me out? Please?
You can you scrollLeft to check the position of scrollbar and move the bar to the start or end accordingly.
I have highlighted the changes I made to the code using comments
let rightArrow = document.getElementById('right')
rightArrow.onclick = function() {
let container = document.getElementById('box')
//check if the scrollbar is located at the end and reset it to starting position
if (container.scrollLeft == container.scrollWidth - container.offsetWidth) {
sideScroll(container, 'left', 10, container.scrollWidth, 20)
} else {
sideScroll(container, 'right', 25, 80, 10)
}
}
let leftArrow = document.getElementById('left')
leftArrow.onclick = function() {
let container = document.getElementById('box')
//check if the scrollbar is located at the start and reset it to ending position
if (container.scrollLeft == 0) {
sideScroll(container, 'right', 10, container.scrollWidth, 20)
} else {
sideScroll(container, 'left', 25, 80, 10)
}
}
function sideScroll(element, direction, speed, distance, step) {
// body...
scrollAmount = 0
let slideTimer = setInterval(function() {
// body...
if (direction == 'left') {
element.scrollLeft -= step
} else {
element.scrollLeft += step
}
scrollAmount += step
if (scrollAmount >= distance) {
window.clearInterval(slideTimer)
}
}, speed)
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-color: #efefef;
width: 100%;
height: 100vh;
background-image: radial-gradient(circle, #2196f3, #3f51b5);
font-family: 'Nirmala UI';
display: grid;
place-items: center;
}
div.main {
position: relative;
background-color: #fff;
border-radius: 10px;
}
div.main div.item_div {
width: 300px;
overflow: auto;
display: flex;
}
div.main div.item_div::-webkit-scrollbar {
display: none;
}
div.main div.item_div div.item {
min-width: 60px;
min-height: 60px;
border-radius: 10px;
background-color: grey;
display: grid;
place-items: center;
font-size: 40px;
text-transform: uppercase;
scroll-behavior: smooth;
user-select: none;
}
div.main div.item_div div.item:not(:last-child) {
margin-right: 20px;
}
div.arrow {
position: absolute;
width: 40px;
height: 40px;
background-color: #f0f0f0;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
top: 50%;
transform: translateY(-50%);
}
div#left {
left: -60px;
}
div#right {
right: -60px;
}
div.arrow span {
font-size: 20px;
user-select: none;
}
div.arrow:hover {
cursor: pointer;
}
<div class="main">
<div class="item_div" id="box">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
<div class="item">10</div>
</div>
<div class="arrow" id="left"><span>❮</span></div>
<div class="arrow" id="right"><span>❯</span></div>
</div>
I've a code that does parallax outline scrolling, so when you scroll the page with a black background, the white text moves horizontally (which is positioned behind the image) along with the red text which is over the image.
This is how it looks like:
I understand the scrolling javascript code but what I don't get is that why the red text is at the boundary of the image? And if it's positioned above the image then why it's only showing the text under the image boundary only and not outside it just like the white one (which is positioned backward)
I'm a backend developer and I'm new to frontend so struggling a bit here. Here's my code...
Index.html :
html,
body {
margin: 0;
padding: 0;
width: 100%;
min-height: 2000px;
overflow-x: hidden;
font-family: "Monument Extended", Arial, Helvetica, sans-serif;
background: #0f0f0f;
}
.container {
max-width: 600px;
margin: 200px auto;
width: 100%;
padding: 10px 0px;
position: relative;
}
.image-container {
padding-bottom: 100%;
background: black;
position: relative;
overflow: hidden;
z-index: 1;
background-image: url("hero-img.jpeg");
background-size: cover;
background-position: center;
}
.text {
color: white;
margin: 0;
font-size: 64px;
width: 100%;
text-align: center;
position: absolute;
top: 50%;
left: -50%;
transform: translateY(-50%);
z-index: 0;
text-transform: uppercase;
white-space: nowrap;
}
.text.text-dark {
color: red;
}
.text span {
position: relative;
display: block;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Parallax Text On Scroll</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="smooth-scroll-wrapper">
<div class="content">
<div class="container">
<div class="image-container">
<h2 class="text text-dark">
<span class="parallax-title">
the red text here
</span>
</h2>
</div>
<h2 class="text">
<span class="parallax-title">
the white text here
</span>
</h2>
</div>
</div>
</div>
<script>
let atScroll = false;
let parallaxTitle = document.querySelectorAll(".parallax-title");
const scrollProgress = () => {
atScroll = true;
};
const raf = () => {
if (atScroll) {
parallaxTitle.forEach((element, index) => {
element.style.transform = "translateX(" + window.scrollY / 12 + "%)";
});
atScroll = false;
}
requestAnimationFrame(raf);
};
requestAnimationFrame(raf);
window.addEventListener("scroll", scrollProgress);
</script>
</body>
</html>
You need to commented highlight css property on class .image-container{overflow: hidden; z-index: 1;} and increase top:50% to top:70% on class .text.text-dark{top: 70%;}
Note: Check on Full page
let atScroll = false;
let parallaxTitle = document.querySelectorAll(".parallax-title");
const scrollProgress = () => {
atScroll = true;
};
const raf = () => {
if (atScroll) {
parallaxTitle.forEach((element, index) => {
element.style.transform = "translateX(" + window.scrollY / 12 + "%)";
});
atScroll = false;
}
requestAnimationFrame(raf);
};
requestAnimationFrame(raf);
window.addEventListener("scroll", scrollProgress);
html,
body {
margin: 0;
padding: 0;
width: 100%;
min-height: 2000px;
overflow-x: hidden;
font-family: "Monument Extended", Arial, Helvetica, sans-serif;
background: #0f0f0f;
}
.container {
max-width: 600px;
margin: 200px auto;
width: 100%;
padding: 10px 0px;
position: relative;
}
.image-container {
padding-bottom: 100%;
background: black;
position: relative;
/* overflow: hidden; */
/* z-index: 1; */
background-image: url("https://i.stack.imgur.com/fcbpv.jpg?s=48&g=1");
background-size: cover;
background-position: center;
}
.text {
color: white;
margin: 0;
font-size: 64px;
width: 100%;
text-align: center;
position: absolute;
top: 50%;
left: -50%;
transform: translateY(-50%);
z-index: 0;
text-transform: uppercase;
white-space: nowrap;
}
.text.text-dark {
color: red;
top: 70%;
}
.text span {
position: relative;
display: block;
}
<div class="smooth-scroll-wrapper">
<div class="content">
<div class="container">
<div class="image-container">
<h2 class="text text-dark">
<span class="parallax-title">
the red text here
</span>
</h2>
</div>
<h2 class="text">
<span class="parallax-title">
the white text here
</span>
</h2>
</div>
</div>
</div>
I am making a website using only JavaScript, HTML, and CSS (no Bootstrap or jQuery).
I have used JavaScript to get the details of the cakes onto the page, as shown with the code below.
Now, I am looking to create a button "View recipes" to view each cake using a modal.
Currently, the button appears outside of the box. I'm still pretty new to this and would appreciate any help on how to add in a button that opens a modal that displays different recipes for each box generated from the cakeData instances.
The code below for each button and modal is hardcoded in HTML. I would like to refactor the HTML code for the button over to recipes.js where it can be associated with the cakeData instances. I'm trying to condense the code down so I'm not copying and pasting code in HTML page, as I want to put 10+ cakes as the website progresses.
// recipes.js
"use strict";
function buildCake(cake) {
const article = document.createElement('article');
article.classList.add('cake');
const h4 = document.createElement('h4');
h4.textContent = cake.name;
article.appendChild(h4);
const p = document.createElement('p');
p.textContent = cake.description;
article.appendChild(p);
const image = document.createElement('img');
image.src = cake.img;
article.appendChild(image);
return article;
}
const cakeData = [{
name: "Chocolate Cake",
img: "../img/chocolate-cake.jpg",
description: "Gooey chocolate cake",
button: ""
},
{
name: "Chocolate Drip Cake",
img: "../img/drip.jpg",
description: "Chocolate layered sponge cake"
},
{
name: "Victoria Sponge Cake",
img: "../img/VSCake.jpg",
description: "Airy sponge cake"
},
{
name: "Fondant Cake",
img: "../img/Aishteru.jpg",
description: "Airy sponge cake with fondant"
}
]
cakeData.forEach(loadCake);
function loadCake(cake) {
const mycake = buildCake(cake);
cakes.appendChild(mycake);
}
document.getElementById('cakes').appendChild(cake);
document.addEventListener('click', function(e) {
e = e || window.event;
var target = e.target || e.srcElement;
if (target.hasAttribute('data-toggle') && target.getAttribute('data-toggle') == 'modal') {
if (target.hasAttribute('data-target')) {
var m_ID = target.getAttribute('data-target');
document.getElementById(m_ID).classList.add('open');
e.preventDefault();
}
}
// Close modal window with 'data-dismiss' attribute or when the backdrop is clicked
if ((target.hasAttribute('data-dismiss') && target.getAttribute('data-dismiss') == 'modal') || target.classList.contains('modal')) {
var modal = document.querySelector('[class="modal open"]');
modal.classList.remove('open');
e.preventDefault();
}
}, false);
// scripts.js
"use-strict";
function toggleNav() {
document.getElementById("sideNav").classList.toggle('open');
}
closeNav.addEventListener('click', toggleNav);
openNav.addEventListener('click', toggleNav);
body {
background-color: #FF7E41;
font-family: sans-serif;
margin: 0;
}
h1 {
color: blanchedalmond;
font-size: 40px;
text-align: center;
padding: 30px;
}
nav {
display: flex;
flex-direction: column;
align-items: stretch;
text-align: center;
height: 100%;
width: 100%;
top: 0;
/* Stay at the top */
left: -100%;
position: fixed;
z-index: 1;
/* Stay on top */
background-color: #FF9765;
overflow-x: hidden;
transition: 2s;
opacity: 0.5;
padding: 2px;
}
nav .menu,
.menu1 {
text-align: right;
}
nav.open {
left: 0;
cursor: pointer;
font-size: 40px;
align-content: right;
opacity: 1;
}
nav a,
.menu,
.menu1 {
padding: 0.25em 0.5em;
text-decoration: none;
font-size: 25px;
color: rgb(0, 0, 0);
display: block;
transition: 2s;
}
.menu {
top: 0;
}
a {
transition: 2s ease;
padding: 2px;
}
main {
width: 85% padding: 0px 30px;
}
/* recipes.html styles */
.cake-grid {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-evenly;
align-items: center;
align-content: center;
padding: 0;
margin: 0;
}
article.cake {
border: 5px solid blanchedalmond;
padding: 10px;
width: 50%;
}
img {
width: 150px;
height: 175px;
}
/* Popup Box */
.modal {
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
display: none;
overflow: auto;
background-color: #000000;
background-color: rgba(0, 0, 0, 0.7);
z-index: 9999;
}
.modal-window {
position: relative;
background-color: #FFFFFF;
width: 50%;
margin: 10% auto;
padding: 20px;
}
.modal-window.small {
width: 30%;
}
.modal-window.large {
width: 75%;
}
.close {
position: absolute;
top: 0;
right: 0;
color: rgba(0, 0, 0, 0.3);
height: 30px;
width: 30px;
font-size: 30px;
line-height: 30px;
text-align: center;
}
.close:hover,
.close:focus {
color: #000000;
cursor: pointer;
}
.open {
display: block;
}
.btn {
background-color: blanchedalmond;
border: none;
color: black;
padding: 10px;
text-align: right;
cursor: pointer;
}
<header>
<span class="menu" id="openNav">☰</span>
<nav id="sideNav">
<span class="menu1" id="closeNav">×</span>
Home
Recipes
Ingredients
About
</nav>
<h1>Recipes</h1>
</header>
<main>
<section id="cakes" class="cake-grid">
<article id="cake">
<p>
<button data-target="simpleModal_1" data-toggle="modal" class="btn">View Recipe</button>
</p>
<div id="simpleModal_1" class="modal">
<div class="modal-window">
<h3>Chocolate cake</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</div>
</div>
<p>
<button data-target="simpleModal_2" data-toggle="modal" class="btn">View Recipe</button>
</p>
<div id="simpleModal_2" class="modal">
<div class="modal-window">
<h3>Victoria sponge cake</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</div>
</div>
</article>
</section>
You have to target the .btn class. This class tells the document where to position the button. Of course, there are different ways to put the buttons inside the box. I would recommend reading this guide about CSS positioning. https://developer.mozilla.org/en-US/docs/Web/CSS/position.
// recipes.js
"use strict";
function buildCake(cake) {
const article = document.createElement('article');
article.classList.add('cake');
const h4 = document.createElement('h4');
h4.textContent = cake.name;
article.appendChild(h4);
const p = document.createElement('p');
p.textContent = cake.description;
article.appendChild(p);
const image = document.createElement('img');
image.src = cake.img;
article.appendChild(image);
return article;
}
const cakeData = [{
name: "Chocolate Cake",
img: "../img/chocolate-cake.jpg",
description: "Gooey chocolate cake",
button: ""
},
{
name: "Chocolate Drip Cake",
img: "../img/drip.jpg",
description: "Chocolate layered sponge cake"
},
{
name: "Victoria Sponge Cake",
img: "../img/VSCake.jpg",
description: "Airy sponge cake"
},
{
name: "Fondant Cake",
img: "../img/Aishteru.jpg",
description: "Airy sponge cake with fondant"
}
]
cakeData.forEach(loadCake);
function loadCake(cake) {
const mycake = buildCake(cake);
cakes.appendChild(mycake);
}
document.getElementById('cakes').appendChild(cake);
document.addEventListener('click', function(e) {
e = e || window.event;
var target = e.target || e.srcElement;
if (target.hasAttribute('data-toggle') && target.getAttribute('data-toggle') == 'modal') {
if (target.hasAttribute('data-target')) {
var m_ID = target.getAttribute('data-target');
document.getElementById(m_ID).classList.add('open');
e.preventDefault();
}
}
// Close modal window with 'data-dismiss' attribute or when the backdrop is clicked
if ((target.hasAttribute('data-dismiss') && target.getAttribute('data-dismiss') == 'modal') || target.classList.contains('modal')) {
var modal = document.querySelector('[class="modal open"]');
modal.classList.remove('open');
e.preventDefault();
}
}, false);
// scripts.js
"use-strict";
function toggleNav() {
document.getElementById("sideNav").classList.toggle('open');
}
closeNav.addEventListener('click', toggleNav);
openNav.addEventListener('click', toggleNav);
body {
background-color: #FF7E41;
font-family: sans-serif;
margin: 0;
}
h1 {
color: blanchedalmond;
font-size: 40px;
text-align: center;
padding: 30px;
}
nav {
display: flex;
flex-direction: column;
align-items: stretch;
text-align: center;
height: 100%;
width: 100%;
top: 0;
/* Stay at the top */
left: -100%;
position: fixed;
z-index: 1;
/* Stay on top */
background-color: #FF9765;
overflow-x: hidden;
transition: 2s;
opacity: 0.5;
padding: 2px;
}
nav .menu,
.menu1 {
text-align: right;
}
nav.open {
left: 0;
cursor: pointer;
font-size: 40px;
align-content: right;
opacity: 1;
}
nav a,
.menu,
.menu1 {
padding: 0.25em 0.5em;
text-decoration: none;
font-size: 25px;
color: rgb(0, 0, 0);
display: block;
transition: 2s;
}
.menu {
top: 0;
}
a {
transition: 2s ease;
padding: 2px;
}
main {
width: 85% padding: 0px 30px;
}
/* recipes.html styles */
.cake-grid {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-evenly;
align-items: center;
align-content: center;
padding: 0;
margin: 0;
}
article.cake {
border: 5px solid blanchedalmond;
padding: 10px;
width: 50%;
}
img {
width: 150px;
height: 175px;
}
/* Popup Box */
.modal {
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
display: none;
overflow: auto;
background-color: #000000;
background-color: rgba(0, 0, 0, 0.7);
z-index: 9999;
}
.modal-window {
position: relative;
background-color: #FFFFFF;
width: 50%;
margin: 10% auto;
padding: 20px;
}
.modal-window.small {
width: 30%;
}
.modal-window.large {
width: 75%;
}
.close {
position: absolute;
top: 0;
right: 0;
color: rgba(0, 0, 0, 0.3);
height: 30px;
width: 30px;
font-size: 30px;
line-height: 30px;
text-align: center;
}
.close:hover,
.close:focus {
color: #000000;
cursor: pointer;
}
.open {
display: block;
}
.btn {
position: relative;
left: -280px;
top: 100px;
background-color: blanchedalmond;
border: none;
color: black;
padding: 10px;
text-align: right;
cursor: pointer;
}
<header>
<span class="menu" id="openNav">☰</span>
<nav id="sideNav">
<span class="menu1" id="closeNav">×</span>
Home
Recipes
Ingredients
About
</nav>
<h1>Recipes</h1>
</header>
<main>
<section id="cakes" class="cake-grid">
<article id="cake">
<p>
<button data-target="simpleModal_1" data-toggle="modal" class="btn">View Recipe</button>
</p>
<div id="simpleModal_1" class="modal">
<div class="modal-window">
<h3>Chocolate cake</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</div>
</div>
<p>
<button data-target="simpleModal_2" data-toggle="modal" class="btn">View Recipe</button>
</p>
<div id="simpleModal_2" class="modal">
<div class="modal-window">
<h3>Victoria sponge cake</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</div>
</div>
</article>
</section>
I placed a negative z-index property on my image section to prevent it from overlapping the navigation bar, which caused the hyperlinks to not function properly. After I fixed that problem, I realized that my left and right buttons for my slideshow would not work. Any help enabling the buttons to work even with a negative z-index? All the code that I have pasted below is necessary.
HTML
<div id="container">
<header>
<h1><b>Seattle</b>&Metropolitan</h1>
<nav>
<ul>
<li>About</li>
<li>Buildings</li>
<li id="contact">Contact Us</li>
</ul>
</nav>
</header>
</div>
<div class="image-section">
<img src="img/seattleskyline.jpg" alt="Seattle Skyline" id="center-image" />
<div id="caption"><div id="caption-text">A panoramic view of 1201 Third Avenue at night</div></div>
<button id="sliderLeft" onclick="left();"></button>
<button id="sliderRight" onclick="right();"></button>
</div>
<br><br>
<div class="content">
Seattle's history can be traced back to the 1850s, when pioneers and natives started building a great city filled with a diverse culure, beautiful scenery, and a vibrant enviornment. The metropolitan area of Seattle now is a high-tech hub, in which four Fortune 500 companies reside: <b>Amazon.com (#49)</b>, <b>Starbucks (#208)</b>, <b>Nordstrom (#227)</b>, and <b>Expeditors International (#428)</b>.
</div>
CSS
#charset "utf-8";
#container
{
width: 75%;
margin-left: auto;
margin-right: auto;
}
header h1
{
font-size: 38px;
float: left;
font-weight: 100;
}
header nav ul
{
list-style-type: none;
margin: 0;
vertical-align: middle;
line-height: normal;
float: right;
z-index: 999;
}
header nav ul li
{
line-height: 105px;
display: inline;
padding: 45px;
font-size: 22px;
font-weight: 100;
}
header nav ul li a
{
color: black;
text-decoration: none;
}
#center-image
{
width: 100%;
height: 480px;
}
#contact
{
padding-right: 0;
}
.image-section
{
margin-left: auto;
margin-right: auto;
width: 75%;
position: relative;
text-align: center;
}
.image-section #caption
{
position: absolute;
display: none;
bottom: 4px;
width: 100%;
text-align: center;
color: white;
background: #474747;
height: 50px;
line-height: 50px;
opacity: 0.8;
font-size: 20px;
}
.image-section button
{
outline: 0;
}
.image-section #sliderLeft
{
position: absolute;
display: none;
width: 25px;
height: 100px;
top: 50%;
margin-bottom: 50px;
left: 0;
opacity: 0.7;
filter: alpha(opacity=70);
border: 0;
}
.image-section #sliderRight
{
position: absolute;
display: none;
width: 25px;
height: 100px;
top: 50%;
margin-bottom: 50px;
right: 0;
opacity: 0.7;
filter: alpha(opacity=70);
border: 0;
}
JS
var images = ["img/seattleskyline.jpg", "img/spaceneedle.jpg", "img/ferriswheel.jpg"]
var captions = ["A panoramic view of 1201 Third Avenue at night", "The Seattle's landmark Space Needle", "The Iconic Great Wheel"]
var index = 0;
function left() {
index -= 2;
if (index < 0) {
index = images.length;
}
changeImage();
}
function right() {
changeImage();
}
function changeImage() {
index++;
if (index > images.length - 1) {
index = 0;
}
var targetImage = document.getElementById("center-image");
var caption = document.getElementById("caption-text");
$("#center-image").fadeOut(1000, function() {
targetImage.src = images[index];
$("#center-image").fadeIn(1000);
});
$("#caption-text").fadeOut(1000, function() {
caption.innerHTML = captions[index];
$("#caption-text").fadeIn(1000);
});
}
$(document).ready(function() {
$("#sliderRight").fadeIn(1000);
$("#sliderLeft").fadeIn(1000);
$("#caption").fadeIn(1000);
setInterval(changeImage, 7000);
});
z-index take effect when position is relative or absolute so if you want use it with your css
add position: relative; as following so z-indexs take effect
header nav ul
{
position: relative;
z-index: 9999;
}
.image-section
{
position: relative;
}
.image-section #sliderLeft
{
z-index: 999;
}
.image-section #sliderRight
z-index: 999;
}
Correct CodePen
Change your CSS for header nav ul to :
header nav ul
{
list-style-type: none;
margin: 0;
vertical-align: middle;
line-height: normal;
float: right;
z-index: 999;
position: relative; /* add this */
}
Working jSfiddle