Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Building adjustable css grid

Tags:

html

css

grid

I am trying to build "adjustable" css grid. I am making my blog and i want my news to be displayed in "blocks" and that they me placed like this : http://pokit.org/get/img/1dfa7b74c6be5bee6c92b886e0b8270b.jpg

And not like this what i did made here

Here is my code.
HTML

<div id="wrapper">
    <div class="d_1">1</div>
    <div class="d_2">2</div>
    <div class="d_3">3</div>
    <div class="d_4">4</div>
    <div class="d_5">5</div>
    <div class="d_6">6</div>

</div>

CSS

#wrapper{
    width:200px;

}
#wrapper div{
    background-color:lightgray;
    width:50px;

    float:left;
    margin:0px 5px 5px 0px;
}
.d_1{
    height:60px;
}
.d_2{
    height:30px;
}
.d_3{
    height:33px;
}
.d_4{
    height:70px;
}
.d_5{
    height:60px;
}
.d_6{
    height:40px;
}
like image 685
Riki Avatar asked Dec 02 '25 16:12

Riki


1 Answers

I suppose that is not possible to obtain the desired result simply using one of the known layout modes (flexbox, grid-layout, inline, ...) nor using CSS columns. Every solution will lead to an unwanted result.

But you can obtain the result using a combination of CSS grid-layout and Javascipt code.

This is the wrapper CSS style block:

#wrapper{
    width: 200px; /* CSS grid-layout will expand contained divs to cover this size */
    display: grid;
    grid-template-columns: 1fr 1fr 1fr; /* "1fr" for each column */
    grid-column-gap: 10px;
    grid-row-gap: 5px;
}

And this is the Javascript code (add it after #wrapper is closed):

"strict mode";
Array.prototype.max = function() {
    return Math.max.apply(null, this);
};
function compute_gaps(a) {
    let max = a.max();
    return a.map(function(el) {
        return el - max;
    });
}
function compose_gaps(a, b) {
    return b.map(function(el, i) {
        return a[i] + el;
    });
}
var counter = 0;
var columns = 3; // number of columns
var gaps = [];
var heights = [];
for (let el of document.querySelectorAll("#wrapper > div")) {
    let colIdx = counter % columns;
    if (counter % columns === 0) {
        //compute gaps
        if (counter) gaps.push(compute_gaps(heights));
        if (gaps.length > 1) {
        gaps[gaps.length - 1] = compose_gaps(
            gaps[gaps.length - 1],
            gaps[gaps.length - 2]
        );
        }
        heights = [];
    }
    if (gaps.length) {
        el.style.marginTop = gaps[Math.floor(counter / columns - 1)][colIdx];
    }
    heights.push(el.offsetHeight); // apply gap as margin
    counter++;
}

Tested the code in a little more complex situation and worked in this way.

The code computes, in each row, gaps between the highest block and the others in the row (compute_gaps); after that, applied the gap as a CSS margin-top. Gaps are summed with the previous ones (compose_gaps).

I hope this answers your question.

like image 178
bubbakk Avatar answered Dec 04 '25 08:12

bubbakk