4

In my document there is a parent div of fixed height and a two-column child div.

<div id="parent">
    <div id="child">Text</div>
</div>

Using just CSS3, I'm trying to get the child's two-column layout work hand in hand with the parent's overflow clipping in the following way:

  1. When the child contains little text, it should not balance the two columns, i.e. it should behave like column-fill: auto

    non-balanced column fill with little text

  2. if the first column would extend out of the parent's bottom, the child's text should wrap over into the second column

    enter image description here

  3. However, when the amount of the child's text exceeds the parent box capacity, the child's columns should be balanced and the parent should clip the child box, with vertical scrollbars on the right.

    enter image description here

Community
  • 1
  • 1
wnrph
  • 3,293
  • 4
  • 26
  • 38
  • 3
    Can you post a fiddle containing your code, or at least your code? – Mathew Thompson Nov 09 '14 at 17:47
  • Well, it's basically like I've said: parent div and child div. There is no CSS yet (that's what I'm asking for). – wnrph Nov 09 '14 at 17:51
  • 1
    Without some JS involvement AFAIK it's not possible... but looking forward to some pure CSS3 solutions... P.S: strange design, to force the user to scroll back-to-top to continue reading the second column... IMHO columns are better seen as in newspapers: as a whole. – Roko C. Buljan Nov 09 '14 at 18:16
  • 1
    Agreed. But that's what the customer likes to see. – wnrph Nov 09 '14 at 18:18
  • If you were paying someone to build you a house but told the contractor you didn't want any windows or doors, wouldn't you expect him to tell you that's not a good idea... even though that's what you *really really* want? – Ryan Wheale Nov 14 '14 at 16:46
  • @Ryan not if I'm a freelancing architect and the contractor has a couple of senior architects who decide that this is what they actually want. – wnrph Nov 15 '14 at 08:28

1 Answers1

3

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>

Conclusion

The issue at hand is that overflow of the contents of columns are supposed to generate more columns, when there is a height set. We can obtain the scrolling region with the parent as expected by removing the column height in the css. We can bring the two together by swapping classnames with a little help from javascript.

Community
  • 1
  • 1
Arthur Weborg
  • 8,280
  • 5
  • 30
  • 67
  • This solution does not adapt to changes on the childs content, right? – wnrph Nov 12 '14 at 16:50
  • As is, that is correct, however the javascript snippet could be wrapped around and triggered by changes to the content, defaulting to the `origState` on content changes and checking with the new content for an overflow. If an overflow was found, setting the class to `overFlowState` (similar to what it is currently doing onload). Would you like me to update my answer to do so? – Arthur Weborg Nov 12 '14 at 17:18
  • It'd be really nice in your case if css had a psuedo-class for overflows, similar to `:hover` and `:active`, but that functionality unfortunately doesn't exist. – Arthur Weborg Nov 12 '14 at 17:19
  • 2
    Why this hasn't got a +1 yet ? @artistoex you should upvote it too, maybe it's not your final solution, but it's better than what you had, and a lot of effort seems to be put in it – Andrea Ligios Nov 14 '14 at 15:17
  • @AndreaLigios Couldn't agree more .. Here goes my upvote – vals Nov 14 '14 at 21:56
  • 1
    @Art +1 You've put an impressive amout of effort into this answer. I guess it's the best answer available. My main concern about this solution is about sustainability. This will become part of a pretty large code base. In a couple of years, not everyone involved will be aware that you can't freely modify some elements. And I wonder if the overflow detection part will still work then. If not purely CSS3, I'm at least looking for a solution which can be applied now and never being cared about again. This is why I've hesitated to award the bounty. – wnrph Nov 15 '14 at 08:44
  • @artistoex That's understandable. I gave it some thought and looked into css3 `css-regions`, `dynamic-css` (which is more about css for varying screen resolutions), `psuedo-classes` and `psuedo-elements` -- I ran into pitfalls with all of them requiring a little help from javascript, I think `css3 multiple columns` is the way to go, closest to a pure css solution as the spec currently stands. I have an idea that caters to your concern of modification -- I'll give it a go later this weekend/when I have some more time and modify my proposed solution if it works (also clear some wording up) – Arthur Weborg Nov 15 '14 at 19:09
  • Eh, unfortunately my attempt was a little to buggy, wasn't working cross browser... attempted to make use of DOM4 mutationobserver api to hook into content changes... rolled answer back, but you are welcome to check out the answers revision history if you want to poke around at it more. – Arthur Weborg Nov 17 '14 at 04:00