1

I'm trying to make a carousel/slider with React + Javascript from scratch. I have thought that would be good to have two layers. One of them over the other. The upper layer would content the window where we can see the elements of the layer which is at the bottom.

The upper layer

  • id is #window-container
  • has only 3 columns.(The central column will be the window of the slider. The other two columns will be hidden. The borders of each grid are painted with a color.)

The bottom layer

  • id is #slider-container.
  • has 4 columns but can get 10, 20, 100 or infinitum columns. The background of each column has a different color.

I want the width of the columns of the upper layer and bottom layers to be equals, but right now they are not.

How can I make them equal no matter how many columns are in the bottom layer?


You can check my development here:

body {
    margin: 0px;
    padding: 0px;
    overflow-x: hidden;
}
  
h1 {
    font-family: Arial, Helvetica, sans-serif;
    width: 100%;
    text-align: center;
}
  
/*****************************************************/
/******************** Container **********************/
/*****************************************************/
  
.container {
    position: relative;
    border: 3px solid black;
    height: 300px;
    width: 100%;
    z-index: 0;
}
  
/*****************************************************/
/***************** Slider Container ******************/
/*****************************************************/
.slider-container {
    position: absolute;
    box-sizing: border-box;
    /*background-color: yellow;*/
    height: 100%;
    z-index: 1;
}
  
/*****************************************************/
/*************** Window Container ********************/
/*****************************************************/
  
.window-container {
    position: absolute;
    box-sizing: border-box;
    padding: 10px;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-gap: 10px;
    height: 100%;
    width: 100%;
    z-index: 100;
}
  
.left {
    border: 1px solid green;
    grid-column: 1;
}
  
.right {
    border: 1px solid red;
    grid-column: 3;
}
  
#window {
    grid-column: 2;
    border: 1px solid #000000;
}
<!DOCTYPE html>
<html>
    <header>
        <link rel="stylesheet" href="./css/styles.css">
    </header>
    <body>
        <div>
            <h1>Slider Scandiweb</h1>
            <div class = "container">
                <div class = "slider-container"></div>
                <div class = "window-container">
                    <div class = "left"></div>
                    <div id="window"></div>
                    <div class = "right"></div>
                </div>
            </div>
        </div>    
    </body>
    <script type="text/javascript">
        let e = document.querySelector("#window");
        //Set slider-container
        let elements = 10;
        let gap = 10;
        let sc = document.querySelector(".slider-container");
        //sc.style.backgroundColor = "red";
        sc.style.width = e.clientWidth * elements + (elements + 1) * gap + "px";
        sc.style.padding = "10px";
        sc.style.display = "grid";
        sc.style.gridTemplateColumns = "repeat(" + elements + ", 1fr)";
        sc.style.gap = "10px";
        //sc.style.height = "100%";
        //Creations of elements
        for (let i = 0; i < elements; i++) {
          let div = document.createElement("div");
          div.style.backgroundColor = "#" + Math.floor(Math.random()*16777215).toString(16);;
          sc.appendChild(div);
        }      
    </script>
</html>
José Carlos
  • 2,850
  • 12
  • 59
  • 95
  • Questions seeking code help must include the shortest code necessary to reproduce it **in the question itself** preferably in a **Stack Snippet**. Although you have provided a link, if it was to become invalid, your question would be of no value to other future SO users with the same problem. See [**Something in my website/example doesn't work can I just paste a link**](http://meta.stackoverflow.com/questions/254428/something-in-my-web-site-or-project-doesnt-work-can-i-just-paste-a-link-to-it). – Paulie_D Jan 21 '21 at 17:23
  • Why do they have to be equal? Wouldn't it be easier to have the down layer also be three columns wide and put all the images in the middle layer? But then you wouldn't even need the middle down layer. – Gh05d Jan 27 '21 at 16:19
  • Above layer has only three layers, being middle layer a window where I have set an event listening of swaping. The bottom layer is a layer with n-elements, it is bigger than the above layer. Each time there is a swap to left or right, I move the bottom layer to left or right. I need all the layers which are inside of the bottom layer have the same width than the middle layer which is in the above layer. Right now, the layers in the bottom are slightly displaced to the left – José Carlos Jan 27 '21 at 16:37

1 Answers1

2

It seems that the width of .slider-container needs to be increased by elements and then it aligns as expected with .window-container:

sc.style.width = e.clientWidth * elements + (elements + 1) * gap + elements + "px";

body {
    margin: 0px;
    padding: 0px;
    overflow-x: hidden;
}
  
h1 {
    font-family: Arial, Helvetica, sans-serif;
    width: 100%;
    text-align: center;
}
  
/*****************************************************/
/******************** Container **********************/
/*****************************************************/
  
.container {
    position: relative;
    border: 3px solid black;
    height: 300px;
    width: 100%;
    z-index: 0;
}
  
/*****************************************************/
/***************** Slider Container ******************/
/*****************************************************/
.slider-container {
    position: absolute;
    box-sizing: border-box;
    /*background-color: yellow;*/
    height: 100%;
    z-index: 1;
}
  
/*****************************************************/
/*************** Window Container ********************/
/*****************************************************/
  
.window-container {
    position: absolute;
    box-sizing: border-box;
    padding: 10px;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-gap: 10px;
    height: 100%;
    width: 100%;
    z-index: 100;
}
  
.left {
    border: 1px solid green;
    grid-column: 1;
}
  
.right {
    border: 1px solid red;
    grid-column: 3;
}
  
#window {
    grid-column: 2;
    border: 1px solid #000000;
}
<!DOCTYPE html>
<html>
    <header>
        <link rel="stylesheet" href="./css/styles.css">
    </header>
    <body>
        <div>
            <h1>Slider Scandiweb</h1>
            <div class = "container">
                <div class = "slider-container"></div>
                <div class = "window-container">
                    <div class = "left"></div>
                    <div id="window"></div>
                    <div class = "right"></div>
                </div>
            </div>
        </div>    
    </body>
    <script type="text/javascript">
        let e = document.querySelector("#window");
        //Set slider-container
        let elements = 10;
        let gap = 10;
        let sc = document.querySelector(".slider-container");
        //sc.style.backgroundColor = "red";
        sc.style.width = e.clientWidth * elements + (elements + 1) * gap + elements + "px";
        sc.style.padding = "10px";
        sc.style.display = "grid";
        sc.style.gridTemplateColumns = "repeat(" + elements + ", 1fr)";
        sc.style.gap = "10px";
        //sc.style.height = "100%";
        //Creations of elements
        for (let i = 0; i < elements; i++) {
          let div = document.createElement("div");
          div.style.backgroundColor = "#" + Math.floor(Math.random()*16777215).toString(16);;
          sc.appendChild(div);
        }      
    </script>
</html>

However, that is still not ideal, because it sets the width based on e.clientWidth, so it would not be responsive. Setting it as follows also solves this issue:

sc.style.width = "calc(" + elements * 100/3 + "% - 20px)";

body {
    margin: 0px;
    padding: 0px;
    overflow-x: hidden;
}
  
h1 {
    font-family: Arial, Helvetica, sans-serif;
    width: 100%;
    text-align: center;
}
  
/*****************************************************/
/******************** Container **********************/
/*****************************************************/
  
.container {
    position: relative;
    border: 3px solid black;
    height: 300px;
    width: 100%;
    z-index: 0;
}
  
/*****************************************************/
/***************** Slider Container ******************/
/*****************************************************/
.slider-container {
    position: absolute;
    box-sizing: border-box;
    /*background-color: yellow;*/
    height: 100%;
    z-index: 1;
}
  
/*****************************************************/
/*************** Window Container ********************/
/*****************************************************/
  
.window-container {
    position: absolute;
    box-sizing: border-box;
    padding: 10px;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-gap: 10px;
    height: 100%;
    width: 100%;
    z-index: 100;
}
  
.left {
    border: 1px solid green;
    grid-column: 1;
}
  
.right {
    border: 1px solid red;
    grid-column: 3;
}
  
#window {
    grid-column: 2;
    border: 1px solid #000000;
}
<!DOCTYPE html>
<html>
    <header>
        <link rel="stylesheet" href="./css/styles.css">
    </header>
    <body>
        <div>
            <h1>Slider Scandiweb</h1>
            <div class = "container">
                <div class = "slider-container"></div>
                <div class = "window-container">
                    <div class = "left"></div>
                    <div id="window"></div>
                    <div class = "right"></div>
                </div>
            </div>
        </div>    
    </body>
    <script type="text/javascript">
        let e = document.querySelector("#window");
        //Set slider-container
        let elements = 10;
        let gap = 10;
        let sc = document.querySelector(".slider-container");
        //sc.style.backgroundColor = "red";
        sc.style.width = "calc(" + elements * 100/3 + "% - 20px)";
        sc.style.padding = "10px";
        sc.style.display = "grid";
        sc.style.gridTemplateColumns = "repeat(" + elements + ", 1fr)";
        sc.style.gap = "10px";
        //sc.style.height = "100%";
        //Creations of elements
        for (let i = 0; i < elements; i++) {
          let div = document.createElement("div");
          div.style.backgroundColor = "#" + Math.floor(Math.random()*16777215).toString(16);;
          sc.appendChild(div);
        }      
    </script>
</html>
sbgib
  • 5,580
  • 3
  • 19
  • 26