Search code examples
javascripthtmlcssflexboxcss-grid

How do I line up elements when using css-grid and flexbox?


The buttons in the bottom row of the calculator (picture below) do not line up with the buttons above.

The red div is using css grid and the green one is using flexbox. I set the margin for all of those divs as 5px, but the green one is misaligned from the red margins. I've also tried setting the gap using flex and grid's built in methods, but that resulted in nearly the same thing.

How can I change the css such that the buttons in the bottom row are aligned with the buttons above them?

Current output

const add = function(a, b) {
    return a+b;
}

const subtract = function(a, b) {
    return a-b;
}

const multiply = function(a, b) {
    return a*b;
}

const divide= function(a, b) {
    return a/b;
}

const operate = function(operator, a, b) {
    if (operator === add || operator === subtract || operator === multiply || operator === divide) {
        return operator(a, b);
    }
   else {
        return;
    }
}


let maindiv = document.createElement("div");
maindiv.id = "main";
document.body.append(maindiv);

let textboxdiv = document.createElement("div");
textboxdiv.id = "textbox";
// maindiv.append(textdiv);

let topdiv = document.createElement("div");
topdiv.id = "topdiv";
maindiv.append(topdiv);

let middlediv = document.createElement("div");
middlediv.id = "middlediv";
maindiv.append(middlediv);

let bottomdiv = document.createElement("div");
bottomdiv.id = "bottomdiv";
maindiv.append(bottomdiv);


let buttons = [];
let divs_top= [];
let divs_middle = [];
let divs_bottom = [];


let top_labels = ["Clear", "Enter"];
let middle_labels = ["1", "2", "3", "+", "4", "5", "6", "-", "7", "8", "9", "*"];
let bottom_labels = ["0", "/"];

function makeButtonsFromList (list, div, divs, buttons) {
    for (let i = 0; i < list.length; i++) {
        buttons[i] = document.createElement("button");
        buttons[i].id = "x"+list[i];
        buttons[i].textContent = list[i];
        divs[i] = document.createElement("div");
        divs[i].id = "x"+list[i];
        divs[i].appendChild(buttons[i]);
        div.appendChild(divs[i]);
    }
}

makeButtonsFromList(top_labels, topdiv, divs_top, buttons);
makeButtonsFromList(middle_labels, middlediv, divs_middle, buttons);
makeButtonsFromList(bottom_labels, bottomdiv, divs_bottom, buttons);

divs_bottom[1].id = "x";
body {
    background-color: black;
    
}


button {
    color: black;

    width: 100%;
    height: 100%;
    
    /*
    width: 75px;
    height: 75px;
    */

}


#main {
    display: flex;
    flex-direction: column;
    margin: 0 auto;

    width: 760px;
    height: 470px;

}

#topdiv>div, #middlediv>div, #bottomdiv>div {
    margin: 5px;
    height: 50px;
}

#topdiv{
    display: flex;
    /* border: solid 1px yellow; */
    
}
#topdiv > div {
    flex: 1;
}

#middlediv{
    border: solid 1px red;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    /*
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    flex-grow: 2;
    justify-content:space-evenly;
    */
}

#middlediv > div {
    height: 50px;


}

#bottomdiv{
    border: solid 1px green;
    display: flex;
   
}

#x0 {
    flex: 3;
}

#x {
    flex: 1;

}
<!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">
    <title>See you Calcu-later</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <script src="js.js"></script>
    
</body>
</html>


Solution

  • I thought about this a bit and I refactored your code to make it much less complex. We don't have to worry about top, middle, bottom, etc. We can just render all the buttons and their div parents directly into the #main div. Then we can use a grid-template-area to render them exactly how we want.

    Here's a quick preview of the CSS. See the full snippet below for the full implementation. I think you'll find it to be a much more efficient way to accomplish your goal.

    #main {
            display: grid;
            width: 760px;
            height: 470px;
            row-gap: 10px;
            column-gap: 10px;
            grid-template-columns: repeat(4, 1fr);
            grid-template-rows: auto;
            grid-template-areas:
                "xClear xClear xEnter xEnter"
                "none none none none"
                "none none none none"
                "none none none none"
                "x0 x0 x0 slash";  
          }
          
        .xClear{
            grid-area: xClear;
        }
        
        .xEnter{
            grid-area: xEnter;
        }
        
        .x0{
            grid-area: x0;
         }
    
         .x/{
            grid-area: slash;
         }
    

    const add = function(a, b) {
        return a+b;
    }
    
    const subtract = function(a, b) {
        return a-b;
    }
    
    const multiply = function(a, b) {
        return a*b;
    }
    
    const divide= function(a, b) {
        return a/b;
    }
    
    const operate = function(operator, a, b) {
        if (operator === add || operator === subtract || operator === multiply || operator === divide) {
            return operator(a, b);
        }
       else {
            return;
        }
    }
    
    
    let maindiv = document.createElement("div");
    maindiv.id = "main";
    document.body.append(maindiv);
    
    let textboxdiv = document.createElement("div");
    textboxdiv.id = "textbox";
    
    let buttons = [];
    let divs =[];
    let labels = ["Clear", "Enter", "1", "2", "3", "+", "4", "5", "6", "-", "7", "8", "9", "*", "0", "/"];
    
    function makeButtonsFromList (list, divs, buttons) {
        for (let i = 0; i < list.length; i++) {
            buttons[i] = document.createElement("button");
            buttons[i].id = "x"+list[i];
            buttons[i].textContent = list[i];
            divs[i] = document.createElement("div");
            divs[i].classList.add("x"+list[i]);
            divs[i].appendChild(buttons[i]);
            maindiv.appendChild(divs[i]);
        }
    }
    
    makeButtonsFromList(labels, divs, buttons);
    body {
        background-color: black;
    }
    
    button {
        color: black;
        width: 100%;
        height: 100%;   
    }
    
    #main {
            display: grid;
            width: 760px;
            height: 470px;
            row-gap: 10px;
            column-gap: 10px;
            grid-template-columns: repeat(4, 1fr);
            grid-template-rows: auto;
            grid-template-areas:
                "xClear xClear xEnter xEnter"
                "none none none none"
                "none none none none"
                "none none none none"
                "x0 x0 x0 slash";  
          }
          
        .xClear{
            grid-area: xClear;
        }
        
        .xEnter{
            grid-area: xEnter;
        }
        
        .x0{
            grid-area: x0;
            }
         .x/{
            grid-area: slash;
            }
        
        
    <!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">
        <title>See you Calcu-later</title>
        <link rel="stylesheet" href="style.css">
    </head>
    <body>
        <script src="js.js"></script>
        
    </body>
    </html>