CSS Two Columns with Known Children Width

CSS two columns with known children width

No, it's not possible to handle this in the general case without JavaScript or a server-side language.

In some cases, you can add wrapper divs for each separate column, but some combinations of element size will make this look bad, for example: http://jsfiddle.net/suaaK/3/ - in that demo, it would probably be better if Box 6 was under Box 3. The more (and more differently sized) elements you have, the more uneven the columns can become.

See this answer for a comparison of the candidate techniques, showing that they don't work, and also showing the client-side portion of the solution involving server-side code:

  • CSS Floating Divs At Variable Heights

If you're willing to use JavaScript+jQuery, you should use jQuery Masonry.

There's also a raw JavaScript version: Vanilla Masonry

Demos:

  • http://desandro.com/demo/masonry/docs/filtering.html
  • http://desandro.com/demo/masonry/docs/animating-jquery.html
  • http://desandro.com/demo/masonry/docs/appending.html

Flexbox: how to make 2 columns (with 2 children) + 1 column markup looks like 3 columns markup?

You can use a grid-template as an alternative, but using flex should be something like this:

.container {
display: flex;
justify-content: space-between;
}

.left-container {
display: flex;
flex-direction: column;
justify-content: space-between;
width: 60vw;
}

.inner-container {
display: flex;
justify-content: space-between;
}

.block-d,
.block-a,
.block-b,
.block-c {
text-align: center;
background-color: lightgray;
}

.block-a,
.block-b {
width: 25vw;
height: 85vh;
}

.block-c {
width: 25vw;
height: 100vh;
}
<body>
<div class="container">
<div class="left-container">
<div class="block-d">
D
</div>
<div class="inner-container">
<div class="block-a">
A
</div>
<div class="block-b">
B
</div>
</div>
</div>
<div class="block-c">
C
</div>
</div>
</body>

Css3: clipping parent and two-column child: mixing balanced and non-balanced column-fill

So in short, you cannot do what you want with a pure css3 at the time of writing. The target API you desire is the CSS3 Multiple Columns. If you look through the examples within the spec you will see it was not written with the use case of mixing balanced and non-balanced (sequential) column-filling at the same time on a given element.

The spec was written to achieve either techniques at different times, thus similar (but ultimately slightly different) functionality to your request. However, we can achieve your target functionality though, with a little help from javascript! Explanation and code below Tested on Chrome 38 and FF 33 IE 11.

If you are feeling up to learning something knew, check out mutationobserver which potentially mitigates your concerns in comments (of unaware devs changing contents on the fly). It allows us to track dom changes and set classes appropriately. my first attempt worked, but not cross browser, see edit revision before the rollback.

I'm going to refer to your three requirements as states.

Overview

  • States 1 and States 2 share the same css (column-fill:auto).
  • State 3 because of the multiple columns spec requires different css rules(column-fill:balance).
  • The rules for state 3 are only required for desired functionality when states 1 and states 2 cannot contain all the text (i.e. overflow).
  • With some help from javascript we can apply the class changes for state 3 when there is overflow in states 1 and 2.
  • In reverse, if content is removed, on a change we can reapply the class for states 1 and 2
  • The css attribute column-count is the number of columns to span the given parent element. In your case, we want 2.

To achieve state 1 and state 2

Whenever you set the height of the column elements, the browser will render more columns outward when there is not enough room. The column widths are at the width of the target span. So setting the height is necessary to have the column fill sequentially (as you requested, "like column-fill:auto"). See snippet below for code, the css rules for "origState" apply to states 1 and 2.

To achieve state 3

However this state gives us a problem. Overflow when the height of the columns is set produces more columns of the same width as the original columns. Now you want it to behave like column-fill:balance with an unlimited height, that is scroll-able. This is not attainable within the css3 multiple column spec when you want to be using sequential filling (i.e. column-fill:auto). However, when no height is set within the columns and the height is set within the parent (with proper scrolling css values) we can achieve what you want. See snippet below for code, the css rules for "overFlowState" apply to state 3 notice the height was removed.

Full Solution

Now we have to bring the two target functionality requests together. You have to determine when to apply the second class to a child container, this can be done by checking for overflows on states 1 and 2. You can do this check once the element has been added to the dom/domready. (Was going to write myself, but borrowed the javascript function for checking overflows from this post). Please see code snippet for javascript.

function isOverflowed(element){    return element.scrollHeight > element.clientHeight || element.scrollWidth > element.clientWidth;}var elements = document.getElementsByClassName("origState");for(var i = 0; i < elements.length; i++){    var element = elements[i];    if(isOverflowed(element)){       element.className = "overFlowState";       i--;    }}
.parent{    overflow-x:hidden;    overflow-y:auto;    width:100%;    height:7em;}.origState{    -webkit-column-count:2;    -moz-column-count:2;    column-count:2;    -moz-column-fill:auto;    height:inherit;}.overFlowState{    -webkit-column-count:2;    -moz-column-count:2;    column-count:2;}
<div class="parent">    <div class="origState">Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.    </div></div><div class="parent">    <div class="origState">Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat         </div></div><div class="parent">    <div class="origState">Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius.    Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius.        </div></div>

How do I make this html two columns of equal width with a margin in between?

I was able to solve it:

.parent .box
{
position: relative;
width: 50%;
margin: 0em;
padding: 1em;
float: left;
font-size: 1em;
overflow: hidden;
z-index: 0;
display: block;
text-decoration: none;
box-sizing: border-box;
}

.parent .box:nth-child(odd)
{
border-right: solid 1em #ffffff;
}

.parent .box:nth-child(even)
{
border-left: solid 1em #ffffff;
}

The n-th child lets me add the spacing between them

What happens when CSS children percentage of width is more than 100%

Depends on the user agent. The spec states that user agents may choose to reflow the layout but does not define exactly how it must be done. Some of them will just automatically divide 100% by the number of cols and reflow them. Some browsers will arbitrarily narrow one or more of the colums to fit. Some will just keep them at the defined width and push excess to the next row. Basically, there is no guarantee of the behavior, so I would not even set width implicitly if you dont know the number of columns/items in advance.

You could just populate them all, then use a bit of JS to divide 100% by the number of cols and use that value to update the CSS on the fly to reflow.

Stack children vertically in left/right columns without vertical white-space

If you are allowed to use a little JS (and I assume you are since one of your trials included a jquery library) you can calculate the vertical position of each element, position each element absolutely, and at the end set the height of container if its relative positioning is important.

let leftH = 0;
let rightH = 0;
const els = document.querySelectorAll('.container > *');
els.forEach(el => {
if (el.getAttribute('class').includes('left')) {
el.style.top = leftH + 'px';
leftH += el.offsetHeight;
} else {
el.style.top = rightH + 'px';
rightH += el.offsetHeight;
}

});
document.querySelector('.container').style.height = ((leftH > rightH) ? leftH : rightH) + 'px';
.container {
width: 100vw;
position relative;
}

.container>* {
width: 50%;
border: 1px solid;
position: absolute;
}

.right {
margin-left: 50%;
}
<div class="container">
<div class="right col">R-Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum consequat odio eget felis mollis placerat. Donec consequat tincidunt nisl sit amet iaculis. In sit amet nisl purus.</div>
<div class="right col">R-Pellentesque nec tellus at tellus</div>
<div class="left col">L-Nulla viverra lorem risus, nec consectetur urna pretium sed. Vestibulum bibendum, tortor vel viverra consequat, urna purus pulvinar odio, sed rutrum justo risus in justo.</div>
<div class="right col">R-Vivamus in lacus sed dolor ullamcorper blandit non fermentum tortor.</div>
<div class="col right">R-Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum consequat odio eget felis mollis placerat. Donec consequat tincidunt nisl sit amet iaculis. In sit amet nisl purus.</div>
<div class="left col">L-Pellentesque nec tellus at tellus scelerisque rutrum ut quis nibh. Aliquam nisi nisl, finibus eu condimentum ac, pretium quis augue.</div>
<div class="left col">L-Nulla viverra lorem risus, nec consectetur urna pretium sed. Vestibulum bibendum, tortor vel viverra consequat, urna purus pulvinar odio, sed rutrum justo risus in justo.</div>
<div class="right col">R-Vivamus in lacus sed dolor ullamcorper blandit non fermentum tortor.</div>
</div>

Set css grid child element's size on the grid, without specifying what column or row it should go into

There is an alternative syntax for grid-row and grid-column that sets a span:

.grid {    display: grid;    border: solid 1px black;    grid-auto-rows: 30px;    grid-auto-columns: repeat (5, 50px);    grid-gap: 5px;}
.grid div { background-color: lightgreen;}
.wide { grid-column: span 3;}
.long { grid-row: span 3;}
<div class="grid"><div></div><div class="long">LONG</div><div class="wide">WIDE</div></div>


Related Topics



Leave a reply



Submit