Home > front end >  How to extend a div backwards?
How to extend a div backwards?

Time:12-21

Does anyone know how to extend a div 2 to the back, lowering the div 1 to the down, when clicking, in a simple way? It looks easy but with css it is not possible and with javascript it is difficult.

I want when clicking on the 2 extends back and the 1 goes down:

the extends

But instead this happens:

the div two go down

div 2 goes down.

Html and Css:

.frame {
    width: 50%;
    height: 400px;
    font: bold 70px roboto;
    color: black;
    background-color: yellow;
    float: left;

}

input:checked   .frame {
    width: 100%;

}

input{
    display: none;
}
<body >
  <input type="checkbox" id="a" />
  <label for="a" >1</label>

  <input type="checkbox" id="b" />
  <label for="b"  style="background-color: green">2</label>

  <input type="checkbox" id="c" />
  <label for="c"  style="background-color: green">3</label>

  <input type="checkbox" id="d" />
  <label for="d" >4</label>
</body>

I tried with this javascript:

Demo

CodePudding user response:

There is many tricky ways to do it with just css, one of them, is to simply use the display: flex on the parent and set the flex-direction: row-reverse but here you must change the order of the html elements.

body{
    width: 100%;
    display: flex;
    flex-direction: row-reverse;
    flex-wrap: wrap;
    margin: 0;
}

.frame {
    display: block;
    width: 50%;
    height: 100px;
    font: bold 70px roboto;
    color: black;
    background-color: yellow;

}

input:checked   .frame {
    width: 100%;

}

input{
    display: none;
}
<body >
  <input type="checkbox" id="b" />
  <label for="b"  style="background-color: green">2</label>
  
  <input type="checkbox" id="a" />
  <label for="a" >1</label>

  <input type="checkbox" id="d" />
  <label for="d" >4</label>
  
  <input type="checkbox" id="c" />
  <label for="c"  style="background-color: green">3</label>
</body>


And there is another way to do it with flex too, you can just change the order of the element:

body{
    margin: 0;
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
}

.frame {
    width: 50%;
    height: 100px;
    font: bold 70px roboto;
    color: black;
    background-color: yellow;
    order: 2;
}

#b:checked   .b {
    width: 100%;
    order: 1;

}

input{
    display: none;
}
<body >
  <input type="checkbox" id="a" />
  <label for="a" >1</label>

  <input type="checkbox" id="b" />
  <label for="b"  style="background-color: green">2</label>

  <input type="checkbox" id="c" />
  <label for="c"  style="background-color: green">3</label>

  <input type="checkbox" id="d" />
  <label for="d" >4</label>
</body>

but here you need to set t logic for everyone you will add.

I hope I managed to help, any more explanation let me know.

CodePudding user response:

Nice question. Yep, it does not have pure-css solution, unfortunately...

Fully agree with previous comment regarding to "swapping" strategy via "order" css property. It's definitely less code and more performant then "physically moving" html elements in DOM

Also, "display: grid" is always better then flex for multi-dimensional layouts (2-column in our case)

Supposing that initial requirement expects that any "even cell" should behave as "2", I see full solution like this:

const el_cells = document.querySelectorAll('.wrapper .cell');

el_cells.forEach((el_clicked, index) => {
    const el_prev = index > 0 ? el_cells[index - 1] : null;

    el_clicked.addEventListener('click', () => {
        // checking if element was already expanded
        const expanding = !el_clicked.classList.contains('active')

        // restoring initial cells state
        el_cells.forEach((el, i) => {
            el.classList.remove('active');
            el.style.order = i   1;
        });

        if (expanding) {
            // resizing selected cell
            el_clicked.classList.add('active');

            // swapping 'even' cell with previous one (f.e. 2 with 1, 4 with 3, etc...)
            if (index % 2 === 1) {
                el_clicked.style.order--;
                el_prev.style.order  ;
            }
        }
    })
})
/* some not very important global styles */
* {
    margin: 0;
    padding: 0;
    font-size: 40px;
    font-weight: bold;
}

/* our yellow-green grid */
.wrapper {
    display: grid;
    grid-template-columns: 1fr 1fr;
}

.wrapper .cell {
    height: 100px;
    background: yellow;
}

.wrapper .cell.green {
    background: green;
}

.wrapper .cell.active {
    grid-column: span 2;
}
<div >
    <div >1</div>
    <div >2</div>
    <div >3</div>
    <div >4</div>
    <div >5</div>
    <div >6</div>
    <div >7</div>
    <div >8</div>
</div>

Improved this example a bit to make expanded cells to collapse on click :)

  • Related