If I have more than one image in a div wrapper. I want to add overlay on image when user hover over the image. I am trying to do using code shown below.
for(var i=0; i<document.getElementsByTagName('img').length; i++) {
document.getElementsByTagName('img')[i].addEventListener('mouseover', function(event){
let elementExists = document.getElementById('wrapper');
let Center = document.createElement('div');
let Text = document.createElement('div');
if (!elementExists) {
let Wrapper = document.createElement('div');
let parentElement = event.currentTarget.parentElement;
Wrapper.classList.add('Wrapper');
Wrapper.id = 'wrapper';
Center.classList.add('Center');
Text.innerHTML = "Sample text";
parentElement.appendChild(Wrapper);
Wrapper.appendChild(Center);
Center.appendChild(Text);
Wrapper.addEventListener('mouseout', function(event){
if (document.getElementById('wrapper')) {
document.getElementById('wrapper').remove();
}
});
}
});
}
.col-md-6 {
width: 375px;
height: 211px;
margin: 20px;
position: relative;
}
.Wrapper {
display: table;
position: absolute;
background-color: rgba(0, 0, 0, 0.5);
height: 100% !important;
width: 100%;
text-align: center;
z-index: 1000;
font-family: arial;
color: #fff;
top: 0;
}
.Center {
display: table-cell;
vertical-align: middle;
}
<div class="col-md-6">
<a href="#">
<img src="https://www.blog.google/static/blog/images/google-200x200.7714256da16f.png" />
</a>
<a href="#">
<img src="https://www.blog.google/static/blog/images/google-200x200.7714256da16f.png" />
</a>
</div>
Every time I hover on first image, code just works fine. But when I hover on 2nd image it adds overlay on 1st image only.(It should add overlay on second image) I tried to debug the code and let parentElement = event.currentTarget.parentElement; is showing the a href only.
NOTE: I came to know its because I am giving position: absolute to Wrapper. I only want to make changes in JavaScript file and at max to css.
Please let me know if you found error in the code.
It's simply a css problem. Just add this to what you currently have:
a {
position: relative;
display: inline-block;
}
.Wrapper {
display: inline-block;
left: 0;
}
.Center {
display: flex;
justify-content: center;
flex-direction: column;
text-align: center;
height: 100%;
}
Also I removed the final Text div and added its text to the Center div, as it triggered the mouseout event and made it flicker.
for(var i=0; i<document.getElementsByTagName('img').length; i++) {
document.getElementsByTagName('img')[i].addEventListener('mouseover', function(event){
let elementExists = document.getElementById('wrapper');
let Center = document.createElement('div');
if (!elementExists) {
let Wrapper = document.createElement('div');
let parentElement = event.currentTarget.parentElement;
Wrapper.classList.add('Wrapper');
Wrapper.id = 'wrapper';
Center.classList.add('Center');
Center.innerHTML = "Sample text";
parentElement.appendChild(Wrapper);
Wrapper.appendChild(Center);
Wrapper.addEventListener('mouseout', function(event){
if (document.getElementById('wrapper')) {
document.getElementById('wrapper').remove();
}
});
}
});
}
.col-md-6 {
width: 375px;
height: 211px;
margin: 20px;
position: relative;
}
a {
position: relative;
display: inline-block;
}
.Wrapper {
display: inline-block;
left: 0;
position: absolute;
background-color: rgba(0, 0, 0, 0.5);
height: 100% !important;
width: 100%;
text-align: center;
z-index: 1000;
font-family: arial;
color: #fff;
top: 0;
}
.Center {
display: flex;
justify-content: center;
flex-direction: column;
text-align: center;
height: 100%;
}
<div class="col-md-6">
<a href="#">
<img src="https://www.blog.google/static/blog/images/google-200x200.7714256da16f.png" />
</a>
<a href="#">
<img src="https://www.blog.google/static/blog/images/google-200x200.7714256da16f.png" />
</a>
</div>
Related
I can't figure out why I'm getting this little bit of green when the window is an odd number of pixels wide. I think it has something to do with sub-pixel rendering, but I'm just not sure where the green is coming from. It's just the 2nd div too which is weird.
I have some script that is animating the BG of this div. I'm sure this is part of the issue, but I can't figure out why it's only happening to my 2nd div.
I tried to manually set the width of this div, but I was hoping it would be responsive and scale with the window size.
let currentStage = 1
function performAction(selectedStage) {
currentStage = selectedStage
let stages = document.body.getElementsByClassName('stage-flow-item')
let stageLines = document.body.getElementsByClassName('stage-flow-line')
console.log("selectedStage: " + selectedStage)
for (let stage of stages) {
if (stage.id > currentStage) {
stage.classList.remove('completed')
stage.classList.add('active')
} else {
stage.classList.remove('active')
stage.classList.add('completed')
}
}
for (let stageLine of stageLines) {
if (stageLine.id > currentStage) {
stageLine.classList.remove('lineCompleted')
stageLine.classList.add('lineActive')
} else {
stageLine.classList.remove('lineActive')
stageLine.classList.add('lineCompleted')
}
}
}
.stage-flow-container {
display: flex;
justify-content: space-between;
align-items: center;
height: 70px;
padding: 0 30px;
}
.stage-flow-item {
width: 70px;
height: 70px;
min-width: 70px;
border-radius: 50%;
background-color: #ddd;
display: flex;
justify-content: center;
align-items: center;
font-size: 18px;
color: #fff;
cursor: pointer;
}
.stage-flow-item.active {
background-color: #ddd;
}
.stage-flow-item.completed {
background-color: #6ab04c;
}
.stage-flow-line {
width: calc(100vw);
height: 6px;
background-color: #ddd;
/* default color */
background: linear-gradient(to left, #ddd 50%, #6ab04c 50%) right;
position: relative;
background-size: 200%;
transition: .5s ease-out;
}
.stage-flow-line.lineCompleted {
background-position: left;
background-color: #6ab04c;
}
.stage-flow-line.lineActive {
background-position: right;
background-color: #ddd;
}
<div class="stage-flow-container">
<div id=1 class="stage-flow-item" onclick="performAction(1)">1</div>
<div id=1 class="stage-flow-line"></div>
<div id=2 class="stage-flow-item" onclick="performAction(2)">2</div>
<div id=2 class="stage-flow-line"></div>
<div id=3 class="stage-flow-item" onclick="performAction(3)">3</div>
</div>
I'm not sure if this is on the right track, but I'd eliminate the odd 100vw width on the connectors and instead make them flex. I'd then remove the 200% background size multiplier. By setting the gradient points to 100% the problem is gone. I really don't know if this covers your use case, though.
I converted from background gradient to a pseudo-element solution for the color transition. I think it's simpler. You'd probably have to use CSS animations (as opposed to simple transitions) to make it work otherwise. Of course, you could apply the same principle to the stage items as well, implementing a delay to crate a consistent animation across the item and the line.
Note that duplicated ID values are invalid in HTML. They must be unique. I've refactored to use data attributes instead and an event listener instead of inline JavaScript.
const stageEls = document.querySelectorAll('.stage-flow-item')
const lineEls = document.querySelectorAll('.stage-flow-line')
let currentStage = 1
stageEls.forEach(el => {
el.addEventListener('click', () => {
performAction(el.dataset.stage)
})
})
function performAction(selectedStage) {
currentStage = selectedStage
for (let el of stageEls) {
if (el.dataset.stage > currentStage) {
el.classList.remove('completed')
el.classList.add('active')
} else {
el.classList.remove('active')
el.classList.add('completed')
}
}
for (let el of lineEls) {
if (el.dataset.stage > currentStage) {
el.classList.remove('lineCompleted')
el.classList.add('lineActive')
} else {
el.classList.remove('lineActive')
el.classList.add('lineCompleted')
}
}
}
.stage-flow-container {
display: flex;
align-items: center;
height: 70px;
padding: 0 30px;
}
.stage-flow-item {
width: 70px;
height: 70px;
min-width: 70px;
border-radius: 50%;
background-color: #ddd;
display: flex;
justify-content: center;
align-items: center;
font-size: 18px;
color: #fff;
cursor: pointer;
}
.stage-flow-item.active {
background-color: #ddd;
}
.stage-flow-item.completed {
background-color: #6ab04c;
}
.stage-flow-line {
flex: 1;
height: 6px;
background: #ddd;
position: relative;
}
.stage-flow-line::after {
position: absolute;
content: '';
top: 0;
left: 0;
width: 0;
height: 100%;
background: #6ab04c;
transition: all 0.5s ease-out;
}
.stage-flow-line.lineCompleted::after {
width: 100%;
}
<div class="stage-flow-container">
<div data-stage=1 class="stage-flow-item">1</div>
<div data-stage=1 class="stage-flow-line"></div>
<div data-stage=2 class="stage-flow-item">2</div>
<div data-stage=2 class="stage-flow-line"></div>
<div data-stage=3 class="stage-flow-item">3</div>
</div>
I'm trying to make it so that when you click on the button with the class .booking__button, the block scrolls up under the header. Position should not change, only scroll. This is done so that the search results of the booking module, which, would be visible to the user. I found the code that does the scrolling, but it works with the exact number, now 100px, but you understand that this distance will be different for everyone, depending on the height of the screen.
document.querySelector('.booking__button').addEventListener('click', () => {
window.scrollTo(0, 100);
});
body {
margin: 0;
}
.header {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 60px;
background: #002164;
}
.hero {
min-height: calc(100vh - 100px);
background: #fff;
}
.booking__module {
display: flex;
justify-content: center;
align-items: center;
background: #BC0B3C;
}
.booking__search {
height: 600px;
background: #ccc;
}
.booking__button {
height: 20px;
margin: 40px;
}
.others {
height: 200vh;
}
<header class="header"></header>
<main class="hero"></main>
<section class="booking">
<div class="booking__module">
<button class="booking__button">booking</button>
</div>
<div class="booking__search"></div>
</section>
<section class="others"></section>
One approach is below, with explanatory comments in the code. Note that while I changed the background-color of the <header> element, that's simply to visualise the functionality and is not at all required:
// we pass a reference to the Event Object ('evt') to the function:
document.querySelector('.booking__button').addEventListener('click', (evt) => {
// we retrieve the closest ancestor <section> element of the element
// to which the event-handler is bound, and retrieve the 'top' property
// of its bounding-client rect:
let {top} = evt.currentTarget.closest('section').getBoundingClientRect();
// we then scroll to that value:
window.scrollTo(0, top);
});
body {
margin: 0;
}
.header {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 60px;
/*background: #002164;*/
background-color: hsl(200deg 70% 70% / 0.4);
}
.hero {
min-height: calc(100vh - 100px);
background: #fff;
}
.booking__module {
display: flex;
justify-content: center;
align-items: center;
background: #BC0B3C;
}
.booking__search {
height: 600px;
background: #ccc;
}
.booking__button {
height: 20px;
margin: 40px;
}
.others {
height: 200vh;
}
<header class="header"></header>
<main class="hero"></main>
<section class="booking">
<div class="booking__module">
<button class="booking__button">booking</button>
</div>
<div class="booking__search"></div>
</section>
<section class="others"></section>
JS Fiddle demo.
References:
Element.closest().
Element.getBoundingClientRect().
Event.
Event.currentTarget.
EventTarget.addEventListener().
Window.scrollTo.
I created a simple carousel using HTML, CSS, and Javascript.
Clicking the left button shows the previous slide and the right one shows the next slide.
But my concern is that slide change is not working correctly
when clicking the next button: After the final slide, it won't go to the first slide again.
when clicking the previous button: After the first slide, it won't go again to last the slide again.
So please review my code and let me know my error.
let right = document.querySelector('.nxt');
let left = document.querySelector('.pre');
let slids = document.querySelector('.slids');
let first = document.querySelector('.first');
let scond = document.querySelector('.scond');
let third = document.querySelector('.third');
let fouth = document.querySelector('.fouth');
let slidesArray=[first,scond,third,fouth];
let index= 0;
let activeSlide= slidesArray[index].classList.add('active');
left.addEventListener('click',()=>{
if (++index > 0) {
slidesArray[index].classList.add('active');
}
});
right.addEventListener('click',()=>{
if (index > 0) {
slidesArray[index].classList.add('deactive');
slidesArray[--index].classList.add('active');
}
});
body{
display: flex;
justify-content: center;
align-items: center;
}
.slids>*{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50% ,-50%);
width: 400px;
height: 350px;
font-size: 50px;
font-weight: 600;
display: grid;
place-items: center;
border-radius: 20px;
box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;
visibility: hidden;
}
.active{
visibility: visible;
}
.first{
background-color: #F7EC09;
}
.scond{
background-color: #3EC70B;
}
.third{
background-color: #3B44F6;
}
.fouth{
background-color: #A149FA;
}
.btn{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50% ,-50%);
display: flex;
gap: 450px;
}
.nxt, .pre{
font-size: 100px;
font-weight: 700;
background: none;
border: none;
cursor: pointer;
}
<body>
<div class="slids">
<div class="first">1</div>
<div class="scond">2</div>
<div class="third">3</div>
<div class="fouth">4</div>
</div>
<div class="btn">
<button class="nxt"><</button>
<button class="pre">></button>
</div>
A chained ternary expression can be used to determine the new index number in a single line:
to = to >= size ? 0 : to < 0 ? size - 1 : to;
Details are commented in example
// Reference the buttons
let next = document.querySelector('.next');
let prev = document.querySelector('.prev');
/*
Collect all div.slide into an array
Define the array's size
Define a number value outside of the function
*/
let slides = [...document.querySelectorAll('.slide')];
let size = slides.length;
let index = 0;
// Bind click event to button.prev
prev.onclick = event => move(index - 1);
// Bind click event to button.next
next.onclick = event => move(index + 1);
/*
Pass newest index number
Ternary expression:
If the given number is greater than or equal to size of the array...
...return 0...
...If the given number is less than 0...
...return last index of array...
...otherwise return the given number
Toggle the current .slide.active and new .slide
Assign index as the given number
*/
function move(to) {
to = to >= size ? 0 : to < 0 ? size - 1 : to;
slides[index].classList.toggle("active");
slides[to].classList.toggle("active");
index = to;
}
html {
font: 300 3vmin/1 Consolas;
}
body {
display: flex;
justify-content: center;
align-items: center;
}
main {
display: flex;
justify-content: center;
align-items: center;
position: relative;
max-width: max-content;
min-height: 100vh;
}
.slides {
display: flex;
justify-content: center;
align-items: center;
position: relative;
width: 420px;
height: 400px;
overflow: hidden;
}
.slide {
display: grid;
place-items: center;
position: absolute;
top: 50%;
left: 50%;
width: 400px;
height: 350px;
border-radius: 20px;
font-size: 50px;
font-weight: 600;
box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;
visibility: hidden;
transform: translate(-50%, -50%);
}
.active {
visibility: visible;
}
.slide:first-of-type {
background-color: #F7EC09;
}
.slide:nth-of-type(2) {
background-color: #3EC70B;
}
.slide:nth-of-type(3) {
background-color: #3B44F6;
}
.slide:nth-of-type(4) {
background-color: #A149FA;
}
.ctrl {
display: flex;
justify-content: space-between;
position: absolute;
top: 45%;
left: 45%;
width: 150%;
transform: translate(-50%, -50%);
}
.next,
.prev {
border: none;
font-size: 100px;
font-weight: 700;
background: none;
cursor: pointer;
}
<main>
<section class="slides">
<div class="slide active">1</div>
<div class="slide">2</div>
<div class="slide">3</div>
<div class="slide">4</div>
</section>
<menu class="ctrl">
<button class="prev"><</button>
<button class="next">></button>
</menu>
</main>
You need to reset the index of the slide when you click next and reach to maximum slide you need to reset index to 0 to return to first slide, also when you click prev and you in the first slide, you need to reset index to 3 to return the last slide.
let right = document.querySelector(".nxt");
let left = document.querySelector(".pre");
let slids = document.querySelector(".slids");
let first = document.querySelector(".first");
let scond = document.querySelector(".scond");
let third = document.querySelector(".third");
let fouth = document.querySelector(".fouth");
const elementsArr = [first, scond, third, fouth];
let slidesArray = [first, scond, third, fouth];
let index = 0;
let activeSlide = slidesArray[index].classList.add("active");
left.addEventListener("click", () => {
if (index === 3) {
index = -1;
}
index++;
resetActiveElements()
});
right.addEventListener("click", () => {
if (index === 0) index = 4;
index--;
resetActiveElements()
});
const resetActiveElements = () => {
elementsArr.forEach((element, i) => {
if (index === i) {
element.classList.add("active");
} else {
element.classList.remove("active");
}
});
}
body{
display: flex;
justify-content: center;
align-items: center;
}
.slids>*{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50% ,-50%);
width: 400px;
height: 350px;
font-size: 50px;
font-weight: 600;
display: grid;
place-items: center;
border-radius: 20px;
box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;
visibility: hidden;
}
.active{
visibility: visible;
}
.first{
background-color: #F7EC09;
}
.scond{
background-color: #3EC70B;
}
.third{
background-color: #3B44F6;
}
.fouth{
background-color: #A149FA;
}
.btn{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50% ,-50%);
display: flex;
gap: 450px;
}
.nxt, .pre{
font-size: 100px;
font-weight: 700;
background: none;
border: none;
cursor: pointer;
}
<body>
<div class="slids">
<div class="first">1</div>
<div class="scond">2</div>
<div class="third">3</div>
<div class="fouth">4</div>
</div>
<div class="btn">
<button class="nxt"><</button>
<button class="pre">></button>
</div>
/* <div class="btn">
<button class="pre"><</button>
<button class="nxt">></button>
</div> */
let right = document.querySelector('.nxt');
let left = document.querySelector('.pre');
let slids = document.querySelector('.slids');
let first = document.querySelector('.first');
let scond = document.querySelector('.scond');
let third = document.querySelector('.third');
let fouth = document.querySelector('.fouth');
let slidesArray = [first, scond, third, fouth];
let index = 0;
let activeSlide = slidesArray[index].classList.add('active');
left.addEventListener('click', () => {
slidesArray[index].classList.remove('active');
if (index == 0) {
index = 3;
slidesArray[index].classList.add('active');
} else {
index--;
slidesArray[index].classList.add('active');
}
});
right.addEventListener('click', () => {
slidesArray[index].classList.remove('active');
if (index == 3) {
index = 0;
slidesArray[index].classList.add('active');
} else {
index++;
slidesArray[index].classList.add('active');
}
});
whole code
With Javascript I want to remove all current Elements on the Screen exept the text and it's CSS styles. My end goal is that I can essentially exchange the text "Bubble" with "Bounce" and still have the same CSS styling in the end. But as I also need to remove ALL Elements from the screen to run the next code I need to clear out the body and CSS entirely. This leads to my Problem. I dont know how to either get the same CSS styling back after clearing it out nor how to exclude the CSS Styling from the clearing. Can anybody help?
document.getElementById("text").innerHTML = "Bubble";
document.addEventListener("click", next);
function next() {
document.head.innerHTML = " ";
document.getElementById("text").innerHTML = "Bounce";
}
section {
width: 100%;
height: 100vh;
overflow: hidden;
background: #1F69FA;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
content {
min-width: 100%;
max-width: 100%;
margin-left: auto;
margin-right: auto;
text-align: center;
position: absolute;
left: 0;
right: 0
}
section h2 {
font-size: 10em;
color: #333;
margin: 0 auto;
text-align: center;
font-family: consolas;
}
<section>
<div class="content">
<h2 id="text"></h2>
</div>
</section>
If you really need to call document.head.innerHTML = " "; this is one way to do it :
I created a function called add_css() which adds the CSS (which is now stored in a variable) in a style tag in the head of document.
Also your CSS had a typo (content instead of .content)
document.getElementById("text").innerHTML = "Bubble";
const css_to_keep = `section {
width: 100%;
height: 100vh;
overflow: hidden;
background: #1F69FA;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.content {
min-width: 100%;
max-width: 100%;
margin-left: auto;
margin-right: auto;
text-align: center;
position: absolute;
left: 0;
right: 0
}
section h2 {
font-size: 10em;
color: #333;
margin: 0 auto;
text-align: center;
font-family: consolas;
}`;
document.addEventListener("click", next);
add_css();
function next() {
document.head.innerHTML = " ";
add_css();
document.getElementById("text").innerHTML = "Bounce";
}
function add_css(){
const style_elem = document.createElement('style');
document.head.appendChild(style_elem);
style_elem.type = 'text/css';
style_elem.appendChild(document.createTextNode(css_to_keep));
}
<section>
<div class="content">
<h2 id="text"></h2>
</div>
</section>
You don't need to "remove" anything - just replace the innerHTML of the document body with a new updated section.
// A function that returns a string
// (See template strings below)
function createSection(text) {
return `
<section>
<div class="content">
<h2 id="text">${text}</h2>
</div>
</section>
`;
}
document.body.innerHTML = createSection('Bubble');
document.addEventListener('click', next);
// Replace the body HTML with the new section
function next() {
document.body.innerHTML = createSection('Bounce');
}
section{width:100%;height:100vh;overflow:hidden;background:#1f69fa;display:flex;justify-content:center;align-items:center;flex-direction:column}content{min-width:100%;max-width:100%;margin-left:auto;margin-right:auto;text-align:center;position:absolute;left:0;right:0}section h2{font-size:10em;color:#333;margin:0 auto;text-align:center;font-family:consolas}
Additional documentation
Template/string literals
This question already has answers here:
Flex elements ignore percent padding in Firefox
(4 answers)
Closed 4 years ago.
In my example code, please click on the Generate Content button in order to understand the issue.
Once you click on the button, you can see all of the flex items(.each-result) generate. They are almost completely wrapped by the div/flexbox (.result-container), indicated by the blue dotted border. If I remove the margins from flex-items, it fits perfectly into the div. However, when I add the margins, the parent div (ie. the flexbox) doesn't expand to it's full width; it remains the same width as when there was no margin.
Is there anyway to change this so that the div expands when adding margin?
const leftArrow = document.querySelector('#left-arrow');
const rightArrow = document.querySelector('#right-arrow');
const rootDiv = document.querySelector('#root');
const generateButton = document.querySelector("#button-generate");
var navMargin = '';
let rootContainerWidth = window.getComputedStyle(rootDiv, null).getPropertyValue("width");
console.log(`Window size onload: ${rootContainerWidth}`);
window.addEventListener('resize', () => {
rootContainerWidth = window.getComputedStyle(rootDiv, null).getPropertyValue("width");
console.log(`The new window size is ${rootContainerWidth}`);
})
//This code basically generates the content within the div
generateButton.addEventListener("click", () => {
for (let i = 0; i < 10; i++) {
const newDiv = document.createElement("div");
newDiv.classList.add("each-result");
newDiv.appendChild(addImg("https://uk.usembassy.gov/wp-content/uploads/sites/16/please_read_icon_150x150.jpg"));
rootDiv.appendChild(newDiv);
}
rootDiv.firstElementChild.classList.add('nav-margin');
navMargin = document.querySelector('.nav-margin');
});
//These enable the arrow to scroll through the dynamically generated content
// function navArrow () {
// leftArrow.addEventListener('click', () => {
// });
// rightArrow.addEventListener('click', () => {
// if ()
// });
// }
//Simple function to create and image element with the src attribute set in one line
function addImg(url) {
const newImg = document.createElement("img");
newImg.setAttribute("src", url);
return newImg;
}
html, body {
height: 100%;
}
button {
position: relative;
z-index: 1
width: auto;
height: 50px;
}
.container {
display: flex;
justify-content: center;
position: relative;
top: 15%;
z-index: 0
}
.each-result {
height: 150px;
width: 150px;
border: 3px dotted red;
margin: 0 1%;
}
img {
height: 100%;
width: auto;
}
.nav-arrows {
display: flex;
justify-content: space-between;
width: 100%;
height: auto;
position: absolute;
background: clear;
pointer-events: none;
}
#left-arrow, #right-arrow {
pointer-events: auto;
}
#root-container {
display: flex;
align-items: center;
border: 1px solid black;
height: 200px;
position: relative;
flex-flow: row no-wrap;
/* overflow: hidden; */
width: 100%;
}
.result-container {
display: flex;
border: 2px blue dotted;
}
<script src="https://use.fontawesome.com/releases/v5.0.6/js/all.js"></script>
<div class="container">
<div class="nav-arrows">
<button id="left-arrow"><i class="fas fa-arrow-alt-circle-left"></i>
</button>
<button id="right-arrow"> <i class="fas fa-arrow-alt-circle-right"></i>
</button>
</div>
<div id="root-container">
<div id="root" class="result-container">
</div>
</div>
</div>
<button id="button-generate">Generate Content</button>
If the margin can be a fixed value (instead of a percent), we can calc() the width of the element to account for the margin. For example, if we wanted a margin of 20px we'd do the following on the .each-result elements:
.each-result {
width: calc(10% + 20px);
margin: 0 20px;
}
Here's the working demo:
const leftArrow = document.querySelector('#left-arrow');
const rightArrow = document.querySelector('#right-arrow');
const rootDiv = document.querySelector('#root');
const generateButton = document.querySelector("#button-generate");
var navMargin = '';
let rootContainerWidth = window.getComputedStyle(rootDiv, null).getPropertyValue("width");
console.log(`Window size onload: ${rootContainerWidth}`);
window.addEventListener('resize', () => {
rootContainerWidth = window.getComputedStyle(rootDiv, null).getPropertyValue("width");
console.log(`The new window size is ${rootContainerWidth}`);
})
//This code basically generates the content within the div
generateButton.addEventListener("click", () => {
for (let i = 0; i < 10; i++) {
const newDiv = document.createElement("div");
newDiv.classList.add("each-result");
newDiv.appendChild(addImg("https://uk.usembassy.gov/wp-content/uploads/sites/16/please_read_icon_150x150.jpg"));
rootDiv.appendChild(newDiv);
}
rootDiv.firstElementChild.classList.add('nav-margin');
navMargin = document.querySelector('.nav-margin');
});
//These enable the arrow to scroll through the dynamically generated content
// function navArrow () {
// leftArrow.addEventListener('click', () => {
// });
// rightArrow.addEventListener('click', () => {
// if ()
// });
// }
//Simple function to create and image element with the src attribute set in one line
function addImg(url) {
const newImg = document.createElement("img");
newImg.setAttribute("src", url);
return newImg;
}
html, body {
height: 100%;
}
button {
position: relative;
z-index: 1
width: auto;
height: 50px;
}
.container {
display: flex;
justify-content: center;
position: relative;
top: 15%;
z-index: 0
}
.each-result {
height: 150px;
width: calc(10% + 20px);
margin: 0 20px;
border: 3px dotted red;
}
img {
height: 100%;
width: auto;
}
.nav-arrows {
display: flex;
justify-content: space-between;
width: 100%;
height: auto;
position: absolute;
background: clear;
pointer-events: none;
}
#left-arrow, #right-arrow {
pointer-events: auto;
}
#root-container {
display: flex;
align-items: center;
border: 1px solid black;
height: 200px;
position: relative;
flex-flow: row no-wrap;
/* overflow: hidden; */
width: 100%;
}
.result-container {
display: flex;
border: 2px blue dotted;
}
<script src="https://use.fontawesome.com/releases/v5.0.6/js/all.js"></script>
<div class="container">
<div class="nav-arrows">
<button id="left-arrow"><i class="fas fa-arrow-alt-circle-left"></i>
</button>
<button id="right-arrow"> <i class="fas fa-arrow-alt-circle-right"></i>
</button>
</div>
<div id="root-container">
<div id="root" class="result-container">
</div>
</div>
</div>
<button id="button-generate">Generate Content</button>