0

I'm trying to get a child div (.form) with a variable height to use overflow: scroll when its contents expand too much.

The .card should be dynamic and always be the height of the window, not exceeding it.

The current problem is that when I set the scrolling div to height: 100%, it will exceed it's parent's height and bleed out of it. The (.tab) at the top is a specific height and not a %. I think this is causing the problem but it must be that specific height.

This entire card needs to be responsive as well to match the window height.

Flex can't be used since it's not supported by IE8.

* {
    margin: 0;
    padding: 0;
}

html, body {
    width: 100%;
    height: 100%;
    background-color: orange;
}

.card {
    position: relative;
    background-color: white;
    width: 320px; 
    height: 100%;
    margin: 0 auto;
}

.tab, .bottom {
    padding: 18px 16px;
    text-align: center;
    border: 1px solid black;
}

.form {
    overflow: scroll;
    height: 100%;
}

.form > * > div {
    padding: 16px;
}
<div class="card">
    <div class="tab">This is a tab</div>
    <div class="form">
        <div class="form-wrapper">
            <div><input type="text"></div>
            <div><input type="text"></div>
            <div><input type="text"></div>
            <div><input type="text"></div>
            <div><input type="text"></div>
            <div><input type="text"></div>
            <div><input type="text"></div>
            <div><input type="text"></div>
            <div><input type="text"></div>
            <div><input type="text"></div>
            <div><input type="text"></div>
            <div><input type="text"></div>
            <div><input type="text"></div>
            <div><input type="text"></div>
            <div><input type="text"></div>
            <div><input type="text"></div>
            <div><input type="text"></div>
            <div><input type="text"></div>
            <div><input type="text"></div>
            <div>this and all the input tags above this should be inside .card and a scrollable div (inside the white background)</div>
        </div>
    </div>
    <div class="bottom">This should be inside .card but outside the form. Just below the white background</div>
</div>

Edit: Some clarification

.tab and .bottom have fixed heights. The only variable height inside .card is the overflow: scroll div.

There will also be another card above this one and it may not work with certain solutions. The two cards have the same width and together, they will take up 100% vh. But I don't think this will be an issue.

JSFiddle

WeerdNoise
  • 451
  • 1
  • 4
  • 15
  • related: http://stackoverflow.com/q/33129660/3597276 – Michael Benjamin Nov 11 '15 at 20:42
  • As stated above, it should be supported by IE8. Calc and flexbox isn't supported. – WeerdNoise Nov 11 '15 at 20:46
  • @PhilipC I think Michael is just pointing out his question is asking something similar. When you say `.card` should be the viewport height, are you including `.tab`, or just `.form`? – TylerH Nov 11 '15 at 20:48
  • Ah I see. Apologies if that came out as offensive @Michael_B. `.card` is the overall parent container of everything else so `.tab` and `.form` should be inside `.card`. – WeerdNoise Nov 11 '15 at 20:51
  • No offense taken. @TylerH is correct, I was referencing a similar problem, not attempting to provide an answer. – Michael Benjamin Nov 11 '15 at 20:57
  • So `.tab` should be fixed to the top of the viewport and `.bottom` should be fixed to the bottom of the viewport, with `.form` filling up the remaining vertical space in between (with overflow scrolling)? Will there ever be more than one `.card` on the page? – MarkPlewis Nov 11 '15 at 20:59
  • Also, can `.tab` and `.bottom` have fixed heights, or do their heights have to be dynamic? – MarkPlewis Nov 11 '15 at 21:06
  • @MarkPlewis `Yes`, there is actually another card right above this one with the same dimensions. They're both going to fill the entire height of the page with `margin-bottom: 16px` between them. I figured that the other card wouldn't matter though since the `overflow: scroll.` is inside a the card but I might be wrong now that I think about it. `Yes`, `.tab` and `.bottom` have fixed heights. exactly as you see in the fiddle. – WeerdNoise Nov 11 '15 at 21:07
  • @PhilipC To get the result you want in non-CSS3/HTML5 browsers requires JavaScript. Is that okay? – Christopher Esbrandt Nov 11 '15 at 21:19
  • @ChristopherEsbrandt If it's the only way, then yeah, that'll have to do. I can't help but think that there's a pure css way of doing it but I don't know enough yet to really make a solid judgement. – WeerdNoise Nov 12 '15 at 15:21
  • @PhilipC Sadly, in CSS2/HTML4.01 there is not way to accomplish it without JavaScript. There is too much dynamic detection required. Before HTML5 and CSS3, the languages were static. They were meant to be read once and to have the page rendered. JavaScript is what allowed the dynamic manipulation of the rendered page by instructing the browser to rerender the page with the modifications it identifies. Today is turning into a busy day for me, but I'll see if I can get you something this evening. To clarify, you want both `.card` to appear on the page and both with have a `.tab` and `.footer`? – Christopher Esbrandt Nov 12 '15 at 15:28
  • You may be able to achieve the layout without JS using HTML `table` elements or CSS `table` properties. – Michael Benjamin Nov 12 '15 at 15:41
  • 1
    @Michael_B Good point. I guess I've gotten too far away from the old school design practices. I always loved templating with `table`s. I'll give it is shot in the morning. I'm afraid it's been too long of a day. – Christopher Esbrandt Nov 13 '15 at 02:51

1 Answers1

2

I'm sorry I didn't get this to you last night, but it was a long day. I took direction from Michael_B and made it work without JavaScript by using a table. This isn't a recommended method moving into the future. tables are meant to render data, not format a page (though I do miss those days).

html, body, body > table {
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
    background-color: #ffa500;
}

.card-holder {
    position: relative;
    height: 50%;
    background-color: #ffffff;
}

.card {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    overflow: auto;
}

.card > div {
    margin: 0 auto;
    width: 320px;
}

.tab, .bottom {
    padding: 18px 16px;
    text-align: center;
    border: 1px solid black;
}

.form-wrapper {
    overflow: auto;
    height: 100%;
}

.form > * > div {
    padding: 16px;
}
<table>
    <tr>
        <td class="card-holder">
            <div class="card">
                <div class="tab">This is a tab</div>
                <div class="form">
                    <div class="form-wrapper">
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div>this and all the input tags above this should be inside .card and a scrollable div (inside the white background)</div>
                    </div>
                </div>
                <div class="bottom">This should be inside .card but outside the form. Just below the white background</div>
            </div>
        </td>
    </tr>
    <tr>
        <td class="card-holder">
            <div class="card">
                <div class="tab">This is a tab</div>
                <div class="form">
                    <div class="form-wrapper">
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div><input type="text" /></div>
                        <div>this and all the input tags above this should be inside .card and a scrollable div (inside the white background)</div>
                    </div>
                </div>
                <div class="bottom">This should be inside .card but outside the form. Just below the white background</div>
            </div>
        </td>
    </tr>
</table>

I closed the input elements, also. Be aware that all elements should be closed. For those elements that don't require a separate closing tab, simply add / before you close the tag up, <input> becomes <input />. It won't prevent most browsers from properly rendering, but it's good practice because other languages are not so nice.