[javascript] flow 2 columns of text automatically with CSS

I have the code similar to the following:

<p>This is paragraph 1. Lorem ipsum ... </p>
<p>This is paragraph 2. Lorem ipsum ... </p>
<p>This is paragraph 3. Lorem ipsum ... </p>
<p>This is paragraph 4. Lorem ipsum ... </p>
<p>This is paragraph 5. Lorem ipsum ... </p>
<p>This is paragraph 6. Lorem ipsum ... </p>

I'd like to, without markup if possible, cause this text to flow into two columns (1-3 on the left, 4-6 on the right). The reason for my hesitation to add a column using a <div> is that this text is entered by the client via a WYSIWYG editor, so any elements I inject are likely to be killed later or inexplicably.

This question is related to javascript html css two-columns

The answer is


Automatically floating two columns next to eachother is not currently possible only with CSS/HTML. Two ways to achieve this:

Method 1: When there's no continous text, just lots of non-related paragraphs:

Float all paragraphs to the left, give them half the width of the containing element and if possible set a fixed height.

<div id="container">
  <p>This is paragraph 1. Lorem ipsum ... </p>
  <p>This is paragraph 2. Lorem ipsum ... </p>
  <p>This is paragraph 3. Lorem ipsum ... </p>
  <p>This is paragraph 4. Lorem ipsum ... </p>
  <p>This is paragraph 5. Lorem ipsum ... </p>
  <p>This is paragraph 6. Lorem ipsum ... </p>
</div>

#container { width: 600px; }
#container p { float: left; width: 300px; /* possibly also height: 300px; */ }

You can also insert clearer-divs between paragraphs to avoid having to use a fixed height. If you want two columns, add a clearer-div between two-and-two paragraphs. This will align the top of the two next paragraphs, making it look more tidy. Example:

<div id="container">
  <p>This is paragraph 1. Lorem ipsum ... </p>
  <p>This is paragraph 2. Lorem ipsum ... </p>
  <div class="clear"></div>
  <p>This is paragraph 3. Lorem ipsum ... </p>
  <p>This is paragraph 4. Lorem ipsum ... </p>
  <div class="clear"></div>
  <p>This is paragraph 5. Lorem ipsum ... </p>
  <p>This is paragraph 6. Lorem ipsum ... </p>
</div>

/* in addition to the above CSS */
.clear { clear: both; height: 0; }

Method 2: When the text is continous

More advanced, but it can be done.

<div id="container">
  <div class="contentColumn">
    <p>This is paragraph 1. Lorem ipsum ... </p>
    <p>This is paragraph 2. Lorem ipsum ... </p>
    <p>This is paragraph 3. Lorem ipsum ... </p>
  </div>
  <div class="contentColumn">
    <p>This is paragraph 4. Lorem ipsum ... </p>
    <p>This is paragraph 5. Lorem ipsum ... </p>
    <p>This is paragraph 6. Lorem ipsum ... </p>
  </div>
</div>

.contentColumn { width: 300px; float: left; }
#container { width: 600px; }

When it comes to the ease of use: none of these are really easy for a non-technical client. You might attempt to explain to him/her how to do this properly, and tell him/her why. Learning very basic HTML is not a bad idea anyways, if the client is going to be updating the web pages via a WYSIWYG-editor in the future.

Or you could try to implement some Javascript-solution that counts the total number of paragraphs, splits them in two and creates columns. This will also degrade gracefully for those who have JavaScript disabled. A third option is to have all this splitting-into-columns-action happen serverside if this is an option.

(Method 3: CSS3 Multi-column Layout Module)

You might read about the CSS3 way of doing it, but it's not really practical for a production website. Not yet, at least.


Not an expert here, but this is what I did and it worked

<html>
<style>
/*Style your div container, must specify height*/
.content {width:1000px; height:210px; margin:20px auto; font-size:16px;}
/*Style the p tag inside your div container with half the with of your container, and float left*/
.content p {width:490px; margin-right:10px; float:left;}
</style>

<body>
<!--Put your text inside a div with a class-->
<div class="content">
            <h1>Title</h1>
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus gravida laoreet lectus. Pellentesque ultrices consequat placerat. Etiam luctus euismod tempus. In sed eros dignissim tortor faucibus dapibus ut non neque. Ut ante odio, luctus eu pharetra vitae, consequat sit amet nunc. Aenean dolor felis, fringilla sagittis hendrerit vel, egestas eget eros. Mauris suscipit bibendum massa, nec mattis lorem dignissim sit amet. </p>
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer eget dolor neque. Phasellus tellus odio, egestas ut blandit sed, egestas sit amet velit. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae;</p>
</div>     
</body>
</html>

Once the text inside the <p> tags has reached the height of the container div, the other text will flow to the right of the container.


Below I have created both a static and dynamic approach at columnizing paragraphs. The code is pretty much self-documented.

Foreward

Below, you will find the following methods for creating columns:

  1. Static (2-columns)
  2. Dynamic w/ JavaScript + CSS (n-columns)
  3. Dynamic w/ JavaScript + CSS3 (n-columns)

Static (2-columns)

This is a simple 2 column layout. Based on Glennular's 1st answer.

_x000D_
_x000D_
$(document).ready(function () {_x000D_
    var columns = 2;_x000D_
    var size = $("#data > p").size();_x000D_
    var half = size / columns;_x000D_
    $(".col50 > p").each(function (index) {_x000D_
        if (index >= half) {_x000D_
            $(this).appendTo(".col50:eq(1)");_x000D_
        }_x000D_
    });_x000D_
});
_x000D_
.col50 {_x000D_
    display: inline-block;_x000D_
    vertical-align: top;_x000D_
    width: 48.2%;_x000D_
    margin: 0;_x000D_
}
_x000D_
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>_x000D_
<div id="data" class="col50">_x000D_
    <!-- data Start -->_x000D_
    <p>This is paragraph 1. Lorem ipsum ...</p>_x000D_
    <p>This is paragraph 2. Lorem ipsum ...</p>_x000D_
    <p>This is paragraph 3. Lorem ipsum ...</p>_x000D_
    <p>This is paragraph 4. Lorem ipsum ...</p>_x000D_
    <p>This is paragraph 5. Lorem ipsum ...</p>_x000D_
    <p>This is paragraph 6. Lorem ipsum ...</p>_x000D_
    <p>This is paragraph 7. Lorem ipsum ...</p>_x000D_
    <p>This is paragraph 8. Lorem ipsum ...</p>_x000D_
    <p>This is paragraph 9. Lorem ipsum ...</p>_x000D_
    <p>This is paragraph 10. Lorem ipsum ...</p>_x000D_
    <p>This is paragraph 11. Lorem ipsum ...</p>_x000D_
    <!-- data End-->_x000D_
</div>_x000D_
<div class="col50"></div>
_x000D_
_x000D_
_x000D_

Dynamic w/ JavaScript + CSS (n-columns)

With this approach, I essentially detect if the block needs to be converted to columns. The format is col-{n}. n is the number of columns you want to create.

_x000D_
_x000D_
$(document).ready(function () {_x000D_
    splitByColumns('col-', 4);_x000D_
});_x000D_
_x000D_
function splitByColumns(prefix, gap) {_x000D_
    $('[class^="' + prefix + '"]').each(function(index, el) {_x000D_
        var me = $(this);_x000D_
        var count = me.attr("class").split(' ').filter(function(className) {_x000D_
            return className.indexOf(prefix) === 0;_x000D_
        }).reduce(function(result, value) {_x000D_
            return Math.max(parseInt(value.replace(prefix, '')), result);_x000D_
        }, 0);_x000D_
        var paragraphs = me.find('p').get();_x000D_
        me.empty(); // We now have a copy of the children, we can clear the element._x000D_
        var size = paragraphs.length;_x000D_
        var percent = 1 / count;_x000D_
        var width = (percent * 100 - (gap / count || percent)).toFixed(2) + '%';_x000D_
        var limit = Math.round(size / count);_x000D_
        var incr = 0;_x000D_
        var gutter = gap / 2 + 'px';_x000D_
        for (var col = 0; col < count; col++) {_x000D_
            var colDiv = $('<div>').addClass('col').css({ width: width });_x000D_
            var css = {};_x000D_
            if (col > -1 && col < count -1) css['margin-right'] = gutter;_x000D_
            if (col > 0 && col < count)     css['margin-left'] = gutter;_x000D_
            colDiv.css(css);_x000D_
            for (var line = 0; line < limit && incr < size; line++) {_x000D_
                colDiv.append(paragraphs[incr++]);_x000D_
            }_x000D_
            me.append(colDiv);_x000D_
        }_x000D_
    });_x000D_
}
_x000D_
.col {_x000D_
    display: inline-block;_x000D_
    vertical-align: top;_x000D_
    margin: 0;_x000D_
}
_x000D_
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>_x000D_
<div id="data" class="col-6">_x000D_
    <!-- data Start -->_x000D_
    <p>This is paragraph 1. Lorem ipsum ...</p>_x000D_
    <p>This is paragraph 2. Lorem ipsum ...</p>_x000D_
    <p>This is paragraph 3. Lorem ipsum ...</p>_x000D_
    <p>This is paragraph 4. Lorem ipsum ...</p>_x000D_
    <p>This is paragraph 5. Lorem ipsum ...</p>_x000D_
    <p>This is paragraph 6. Lorem ipsum ...</p>_x000D_
    <p>This is paragraph 7. Lorem ipsum ...</p>_x000D_
    <p>This is paragraph 8. Lorem ipsum ...</p>_x000D_
    <p>This is paragraph 9. Lorem ipsum ...</p>_x000D_
    <p>This is paragraph 10. Lorem ipsum ...</p>_x000D_
    <p>This is paragraph 11. Lorem ipsum ...</p>_x000D_
    <!-- data End-->_x000D_
</div>
_x000D_
_x000D_
_x000D_

Dynamic w/ JavaScript + CSS3 (n-columns)

This has been derived from on Glennular's 2nd answer. It uses the column-count and column-gap CSS3 rules.

_x000D_
_x000D_
$(document).ready(function () {_x000D_
    splitByColumns('col-', '4px');_x000D_
});_x000D_
_x000D_
function splitByColumns(prefix, gap) {_x000D_
    var vendors = [ '', '-moz', '-webkit-' ];_x000D_
    var getColumnCount = function(el) {_x000D_
        return el.attr("class").split(' ').filter(function(className) {_x000D_
            return className.indexOf(prefix) === 0;_x000D_
        }).reduce(function(result, value) {_x000D_
            return Math.max(parseInt(value.replace(prefix, '')), result);_x000D_
        }, 0);_x000D_
    }_x000D_
    $('[class^="' + prefix + '"]').each(function(index, el) {_x000D_
        var me = $(this);_x000D_
        var count = getColumnCount(me);_x000D_
        var css = {};_x000D_
        $.each(vendors, function(idx, vendor) {_x000D_
            css[vendor + 'column-count'] = count;_x000D_
            css[vendor + 'column-gap'] = gap;_x000D_
        });_x000D_
        me.css(css);_x000D_
    });_x000D_
}
_x000D_
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>_x000D_
<div id="data" class="col-3">_x000D_
    <!-- data Start -->_x000D_
    <p>This is paragraph 1. Lorem ipsum ...</p>_x000D_
    <p>This is paragraph 2. Lorem ipsum ...</p>_x000D_
    <p>This is paragraph 3. Lorem ipsum ...</p>_x000D_
    <p>This is paragraph 4. Lorem ipsum ...</p>_x000D_
    <p>This is paragraph 5. Lorem ipsum ...</p>_x000D_
    <p>This is paragraph 6. Lorem ipsum ...</p>_x000D_
    <p>This is paragraph 7. Lorem ipsum ...</p>_x000D_
    <p>This is paragraph 8. Lorem ipsum ...</p>_x000D_
    <p>This is paragraph 9. Lorem ipsum ...</p>_x000D_
    <p>This is paragraph 10. Lorem ipsum ...</p>_x000D_
    <p>This is paragraph 11. Lorem ipsum ...</p>_x000D_
    <!-- data End-->_x000D_
</div>
_x000D_
_x000D_
_x000D_


Maybe a slightly tighter version? My use case is outputting college majors given a json array of majors (data).

var count_data      = data.length;

$.each( data, function( index ){
    var column = ( index < count_data/2 ) ? 1 : 2;
    $("#column"+column).append(this.name+'<br/>');
});

<div id="majors_view" class="span12 pull-left">

  <div class="row-fluid">
    <div class="span5" id="column1"> </div>
    <div class="span5 offset1" id="column2"> </div>
  </div>

</div>

Here is an example of a simple Two-column class:

.two-col {
       -moz-column-count: 2;
       -moz-column-gap: 20px;
       -webkit-column-count: 2;
       -webkit-column-gap: 20px;
}

Of which you would apply to a block of text like so:

<p class="two-col">Text</p>

Use CSS3

.container {
   -webkit-column-count: 2;
      -moz-column-count: 2;
           column-count: 2;

   -webkit-column-gap: 20px;
      -moz-column-gap: 20px;
           column-gap: 20px;
}

Browser Support

  • Chrome 4.0+ (-webkit-)
  • IE 10.0+
  • Firefox 2.0+ (-moz-)
  • Safari 3.1+ (-webkit-)
  • Opera 15.0+ (-webkit-)

This solution will split into two columns and divide the content half in one line half in the other. This comes in handy if you are working with data that gets loaded into the first column, and want it to flow evenly every time. :). You can play with the amount that gets put into the first col. This will work with lists as well.

Enjoy.

<html>
<head>
<title>great script for dividing things into cols</title>



    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js"></script>
    <script>
$(document).ready(function(){

var count=$('.firstcol span').length;
var selectedIndex =$('.firstcol span').eq(count/2-1);
var selectIndexafter=selectedIndex.nextAll();


if (count>1)
{
selectIndexafter.appendTo('.secondcol');
}

 });

</script>
<style>
body{font-family:arial;}
.firstcol{float:left;padding-left:100px;}
.secondcol{float:left;color:blue;position:relative;top:-20;px;padding-left:100px;}
.secondcol h3 {font-size:18px;font-weight:normal;color:grey}
span{}
</style>

</head>
<body>

<div class="firstcol">

<span>1</span><br />
<span>2</span><br />
<span>3</span><br />
<span>4</span><br />
<span>5</span><br />
<span>6</span><br />
<span>7</span><br />
<span>8</span><br />
<span>9</span><br />
<span>10</span><br />
<!--<span>11</span><br />
<span>12</span><br />
<span>13</span><br />
<span>14</span><br />
<span>15</span><br />
<span>16</span><br />
<span>17</span><br />
<span>18</span><br />
<span>19</span><br />
<span>20</span><br />
<span>21</span><br />
<span>22</span><br />
<span>23</span><br />
<span>24</span><br />
<span>25</span><br />-->
</div>


<div class="secondcol">


</div>


</body>

</html>

Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to html

Embed ruby within URL : Middleman Blog Please help me convert this script to a simple image slider Generating a list of pages (not posts) without the index file Why there is this "clear" class before footer? Is it possible to change the content HTML5 alert messages? Getting all files in directory with ajax DevTools failed to load SourceMap: Could not load content for chrome-extension How to set width of mat-table column in angular? How to open a link in new tab using angular? ERROR Error: Uncaught (in promise), Cannot match any routes. URL Segment

Examples related to css

need to add a class to an element Using Lato fonts in my css (@font-face) Please help me convert this script to a simple image slider Why there is this "clear" class before footer? How to set width of mat-table column in angular? Center content vertically on Vuetify bootstrap 4 file input doesn't show the file name Bootstrap 4: responsive sidebar menu to top navbar Stylesheet not loaded because of MIME-type Force flex item to span full row width

Examples related to two-columns

flow 2 columns of text automatically with CSS