Inside my VueJS 3 app I want to stack a collection of divs on top of each other forming two columns. The divs are numbered and their order should be preserved vertically. In other words: when reading the div numbers from top to bottom, it should read: 1, 2, 3, 4, 5 ...
See this codepen for a graphic illustration of the desired outcome.
Or see the code below.
<!DOCTYPE html>
<html lang="en">
<head>
<style>
.boxes {
width: 640px;
background-color: rgb(210, 166, 252);
overflow: auto;
}
.box {
width: 300px;
background-color: blueviolet;
margin: 10px;
padding: 16px;
box-sizing: border-box;
}
.left {
float: left;
clear: left;
}
.right {
float: right;
clear: right;
}
h3 {
text-align: center;
margin: 0;
}
</style>
</head>
<body>
<div class="boxes">
<div class="box left"><h3>1.</h3> Lorem ipsum dolor sit amet consectetur adipisicing elit. Praesentium, blanditiis unde ab ullam nesciunt deleniti vitae, temporibus deserunt vel qui reprehenderit eveniet quas sapiente corrupti fuga eum sint ducimus aspernatur aliquid tenetur velit quaerat. Culpa perferendis error, ad a nesciunt voluptatibus laborum maiores dolor, dolorum maxime assumenda quam odit atque.</div>
<div class="box right"><h3>2.</h3> Lorem ipsum dolor sit amet consectetur, adipisicing elit. Quos soluta beatae ipsam assumenda nihil dolor, ratione a quas vitae perferendis doloribus perspiciatis iure! Aliquam, ut.</div>
<div class="box right"><h3>3.</h3> Lorem ipsum dolor sit amet consectetur adipisicing elit. Laudantium quasi cupiditate doloremque saepe sed, nisi et nostrum at, illo est ipsa doloribus nulla soluta consequuntur ullam sapiente debitis quam. Odio?</div>
<div class="box left"><h3>4.</h3> Lorem ipsum dolor, sit amet consectetur adipisicing elit. Dolorum aspernatur et, voluptas dolores quidem quasi. Lorem ipsum dolor, sit amet consectetur adipisicing elit. Nam eveniet earum, perferendis quasi blanditiis veritatis nobis vel modi excepturi molestias, sint debitis dolor aspernatur inventore repellendus ullam libero non dolores in sed, quas illo incidunt nulla magni! Neque, optio delectus! Lorem ipsum, dolor sit amet consectetur adipisicing elit. Omnis eos doloribus aliquam sapiente assumenda? Incidunt, vero fugiat. Qui excepturi ratione, labore pariatur saepe nobis a quibusdam ad incidunt, eius iusto!</div>
<div class="box right"><h3>5.</h3> Lorem ipsum, dolor sit amet consectetur adipisicing elit. Soluta neque distinctio recusandae eveniet necessitatibus sint magni omnis dolorem voluptatibus dolore repellat adipisci, blanditiis doloremque reiciendis harum voluptas incidunt fugit dolores ipsam placeat expedita debitis. Dignissimos reprehenderit quia totam, debitis aperiam sed iure.</div>
<div class="box right"><h3>6.</h3> Lorem ipsum dolor sit amet consectetur, adipisicing elit. Accusantium saepe a eum pariatur officiis adipisci eligendi, minus ipsam.</div>
<div class="box left"><h3>7.</h3> Lorem ipsum dolor sit amet consectetur adipisicing elit. Quasi quisquam earum dicta ipsum repellendus voluptate animi quis ea eaque enim culpa reprehenderit beatae, deserunt ab consequuntur ratione libero?</div>
<div class="box right"><h3>8.</h3> Lorem ipsum dolor, sit amet consectetur adipisicing elit. Dolorum aspernatur et, voluptas dolores quidem quasi.</div>
<div class="box left"><h3>9.</h3> Lorem ipsum, dolor sit amet consectetur adipisicing elit. Soluta neque distinctio recusandae eveniet necessitatibus sint magni omnis dolorem voluptatibus dolore repellat adipisci, blanditiis doloremque reiciendis harum voluptas incidunt fugit dolores ipsam placeat expedita debitis. Dignissimos reprehenderit quia totam, debitis aperiam sed iure.</div>
<div class="box right"><h3>10.</h3> Lorem ipsum dolor, sit amet consectetur adipisicing elit. Dolorum aspernatur et, voluptas dolores quidem quasi.</div>
<div class="box right"><h3>11.</h3> Lorem ipsum dolor, sit amet consectetur adipisicing elit. Dolorum aspernatur et, voluptas dolores quidem quasi.</div>
</div>
</body>
</html>
To get to right order of my divs I manually assigned .left or .right to each div. I would like to automate this process.
Inside my Vue app a v-for loops over an array with the content of all divs. In the example above left the Vue part out, to keep the example code simpler.
What I have tried already:
I have tried messing around with dynamically assigned classes in Vue and using $refs to measure the height of each column during run-time, but I couldn't make it work.
A vanilla JS apporach might be a solution, but I would like to know how to do this the Vue way, preferably.
Thanks.
I don't want to leave any loose ends in this Stack Overflow post, so I'll share the code I ended up using in Vue.
I took a slightly different approach in this VueJS solution, compared to the Vanilla JS solution I posted. For each box I compared the height of the bottom of the previous box and the one before that AFTER all the boxes have been created. Instead of checking the height of the bottom of the container of the boxes DURING the iterative creation process of the boxes.
See Codepen or code below.
<!DOCTYPE html>
<html lang="en">
<head>
<style>
#boxes {
width: 640px;
background-color: rgb(210, 166, 252);
overflow: auto;
}
.box {
width: 300px;
background-color: blueviolet;
margin: 10px;
padding: 16px;
box-sizing: border-box;
}
.left {
float: left;
clear: left;
}
.right {
float: right;
clear: right;
}
</style>
</head>
<body>
<div id="app">
<div id="boxes" ref="boxes">
<div v-for="box in boxes" class="box">
{{ box.name }}
</div>
</div>
</div>
<script src="https://unpkg.com/vue@3"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
Vue.createApp({
data () {
return {
boxes: [
{id: 0, name: '1. Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello'},
{id: 1, name: '2. Hello Hello Hello Hello Hello Hello Hello Hello Hello'},
{id: 2, name: '3. Hello Hello Hello Hello Hello Hello Hello'},
{id: 3, name: '4. Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello'},
{id: 4, name: '5. Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello'},
{id: 5, name: '6. Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello'},
{id: 6, name: '7. Hello Hello Hello Hello Hello Hello Hello Hello Hello'},
{id: 7, name: '8. Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello'},
{id: 8, name: '9. Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello '},
{id: 9, name: '10. Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello'}
]
}
},
mounted () {
let allBoxes = document.querySelectorAll('.box')
let firstBox = allBoxes[0]
firstBox.classList.add('left')
let secondBox = allBoxes[1]
secondBox.classList.add('right')
for (let i = 2; i < allBoxes.length; i++) {
let previousPrevious = allBoxes[i-2]
let previous = allBoxes[i-1]
let heightOfPreviousPrevious = previousPrevious.getBoundingClientRect().bottom
let heightOfPrevious = previous.getBoundingClientRect().bottom
let sideOfPrevious = null
let switchedSide = null
if ( previous.classList.contains('right') ) {
sideOfPrevious = 'right'
switchedSide = 'left'
}
else if ( previous.classList.contains('left') ) {
sideOfPrevious = 'left'
switchedSide = 'right'
}
if (heightOfPrevious < heightOfPreviousPrevious) {
allBoxes[i].classList.add(sideOfPrevious)
}
else {
allBoxes[i].classList.add(switchedSide)
}
}
}
})
.mount('#app')
</script>
</body>
</html>