-3

I have an HTML page with content organized into two columns, like this:

<div class="col" style="width:50%;float:left;">
   <div class="section" name="introduction">
      bla bla bla
   </div>
   <div class="section" name="games">
      bla bla bla bla bla bla
   </div>
   <div class="section" name="license">
      bla bla bla bla bla bla bla
   </div>
</div>
<div class="col" style="width:50%;float:right;">
   <div class="section" name="about">
      bla bla bla bla bla
   </div>
   <div class="section" name="contactus">
      bla bla bla bla bla
   </div>
   <div class="section" name="etc">
      bla bla
   </div>
</div>

Where "col" stands for column. Pretty basic stuff.

As you can see, the sections, which make up the columns, are not of equal length. That is, there is more text in section two than section one. For this reason, section two will be taller than section one if the browser window is small enough.

What I want to accomplish is, after the columns have loaded, I want to divide the sections amongst the columns so that the columns are as close as possible to equal height. So, if the column on the left is taller compared to the one on the right, the function will move the appropriate amount of sections from the left column to the right column.

But if the browser window is big enough that the text does not have to wrap, because each section is, in this example, quite a short piece of text, nothing needs to happen. They're all the same height.

I also want to be able to call this function more than once if more content is added to a section/the window is resized.

Here is some Javascript code I have tried:

function sections() {
// collect the height of every section.
sectionheightarray0 = new Array();
sectionheightarray1 = new Array();
for(i=0;i<document.getElementsByClassName("section").length;i++){
sectionheightarray1[i]=document.getElementsByClassName("section")[i].clientHeight;
}
Array.prototype.sum = function() {
var count=0;
for (i=this.length;i--;) {
count+=this[i];
}
return count;
}
// using the height of each of the sections, check if the right side is longer than the left, and if so, make the left side longer by moving a section into the left column.
while (sectionheightarray0.sum()<sectionheightarray1.sum()) {
sectionheightarray0.push(sectionheightarray1.shift());
}
// by default, the left side is always longer than the right. Uncomment to not always have the left side be longer depending on the height
// if (sectionheightarray0.sum()-sectionheightarray1.sum()>(sectionheightarray0.sum()-sectionheightarray0[sectionheightarray0.length-1])-(sectionheightarray1.sum()+sectionheightarray0[sectionheightarray0.length-1])) {
// sectionheightarray1.push(sectionheightarray0.pop());
// }
// swap the sections here.
if (document.getElementById("col1").getElementsByClassName("section").length<sectionheightarray0.length) {
while (document.getElementById("col1").getElementsByClassName("section").length!=sectionheightarray0.length) {
document.getElementById("col1").appendChild(document.getElementById("col2").getElementsByClassName("section")[0]);
}
} else {
if (document.getElementById("col2").getElementsByClassName("section").length<sectionheightarray1.length) {
while (document.getElementById("col2").getElementsByClassName("section").length!=sectionheightarray1.length) {
document.getElementById("col2").insertBefore(document.getElementById("col1").getElementsByClassName("section")[(document.getElementById("col1").getElementsByClassName("section").length-1)], document.getElementById("col2").getElementsByClassName("section")[0]);
}
}
}
sectionheightarray0 = [];
sectionheightarray1 = [];
}
sections();
// if the ser resizes the viewport, repeat the process.
window.onresize=sections;

Surprisingly it does work to some extent, but as you can see, it isn't a very clean solution. It takes up a lot of space and I was hoping for a cleaner and smaller, perhaps more official solution. Cross browser is obviously preferred.

I know the Columnizer JQuery script exists for this purpose, but I would like to be able to do this without the use of JQuery. Partly that's because I find JQuery to be quite confusing, but mainly it is because I don't use JQuery anywhere else on my site, so I would only be calling it for this one purpose - which seems overkill for such a simple task. Javascript or CSS solutions are fine. Any ideas? Thanks in advance.

tomysshadow
  • 870
  • 1
  • 8
  • 23
  • What have you tried so far? Show us the JavaScript you've attempted to write and what went wrong with it. – Sparky Aug 30 '14 at 04:30
  • @undefined, while this is poorly written question deserving of its down-votes and ultimate closure, it is not a duplicate of the one you've chosen. The OP also wants content to automatically move from one column to the other as needed. – Sparky Aug 30 '14 at 04:44
  • @Sparky Yes, you are right. I'll re-open the question. – Ram Aug 30 '14 at 04:50
  • I added a Javascript code example of what I tried, though it isn't very pretty. That's kind of why I asked in the first place. I hope my edits to the question will help you to understand what I want as my final goal. – tomysshadow Aug 30 '14 at 20:13

3 Answers3

2

You could use a single wrapper and the column CSS properties: DEMO

.col {
  column-count:2;
  column-width:50%;
  column-fill:balance;
  /* whatever */
  width:500px;
  margin:auto;
  border:solid;
}
/* Demo purpose : check behavior adding some content via hover */
.col .hover {
  display:none;
}
.col:hover .hover {
  display:block;
}
G-Cyrillus
  • 101,410
  • 14
  • 105
  • 129
  • 1
    This is closest to the answer I was looking for, but not all the way there. I found a property called break-inside. Setting it to "avoid" on the section class does what I want. You can also use display:inline-block for old browsers. And there is a nice polyfill for other browser support https://github.com/BetleyWhitehorne/CSS3MultiColumn – tomysshadow Aug 31 '14 at 04:49
0

Following is one of the ways to achieve this:

HTML markup:

<div class="wrapper">
    <div class="col">...</div>
    <div class="col">...</div>
</div>

CSS:

.wrapper{
    display:table;
    height:100%;
    width:100%;
}
.col{
    display:table-cell;
    vertical-align:top;
}

See DEMO here.

codingrose
  • 15,563
  • 11
  • 39
  • 58
  • 2
    I think your demo misses this part of the question, _"if the column on the left is long compared to the one on the right, the function will **move the appropriate amount of sections from the left column to the right** column."_ – Sparky Aug 30 '14 at 04:37
-1

I'll write pseudo code mixed in with jQuery since I completely forgot standard javascript syntax.

var leftCols = $("#left").length;    // you can use getElementById instead 
var rightCols = $("#right").length;
var threshold = 3;
var dif = leftCols - rightCols; // or vise versa, you can do different cases
var i = 0;
if (dif >= threshold) {
   $.each("#left", function(this){
     dif = leftCols - rightCols;
     if (dif < threshold) {
       break;
     }
     else {
       // append right div
       $("#right").append(this);
       // remove the element from the left div
       this.remove();
     }
   });
}

This is just something quick I jotted down, it's not supposed to work. It's just a pseudo code you can work with if you're stuck with ideas of how to approach the problem.

zsawaf
  • 1,921
  • 16
  • 24
  • btw threshold just represents the maximum distance you can tolerate. Also I don't know why you're refraining from using jQuery, it makes your life 10 times easier. – zsawaf Aug 30 '14 at 05:23