James Thorpe
James Thorpe

Reputation: 56

shrink middle div horizontally on browser resize

I have a 3 column layout which I'm creating using inline-block divs. The left and right columns are fixed widths but the inner column is to hold dynamic content and should expand horizontally as required by it's content width.

That's easy enough... the tricky part is that when the browser window is smaller (horizontally) than the width of the left, right and expanded middle divs, I would like the middle div to scroll and the side columns to stay fixed. In other words, the middle div's size should shrink and grow with window resize but should not grow beyond the available space.

Simply laying out the divs looks like this https://jsfiddle.net/xzjp5xef/1/

HTML:

<div id="container">
   <div id="lcol">
      left
   </div>
   <div id="midcol">
      <div id="spacer">
         150px spacer
      </div>
   </div>
   <div id="rightcol">
      right
   </div>
</div>

CSS:

div {
    height:200px;
    border-style:solid;
    display: inline-block;
    border-width: 1px;
    vertical-align: top;
}
#container{
    white-space: nowrap;
}
#lcol {
    background-color:blue;
    width: 100px;    
}
#midcol {
    background-color: yellow;
    overflow-x: auto;
}
#spacer {
    min-width: 150px;
    margin: 10px;
    height: 20px;
}
#rightcol {
    background-color: red;
    width:100px;
}

The point of the "spacer" div is to represent the dynamic content which in this case I've fixed to 150px plus padding. So in this case I want the divs to lay out the way they do in the above fiddle, but then when the window is shrunk horizontally, I want the middle div to scroll and the left and right divs to remain fully visible.

That fails because then the window gets a scroll bar but the middle panel remains the same width and the right hand div disappears into the scrolled region.

My next attempt was using absolute positioning https://jsfiddle.net/n4zrLqh2/ I fixed the left div to the left and the right div to the right and set the middle div's right and left properties. This is a neat trick which allows the middle div to stretch and take up all available space. This works nicely but doesn't create the effect I'm after when the window is big - because I don't want the middle column to expand further than is necessary to contain its content.

In the end I've solved this with javascript but would much prefer a CSS solution.

Edit: To help others see what I'm trying to achieve, here's the complete javascript solution (which I'd prefer to achieve with pure CSS):

HTML:

<div id="lcol">left</div>
<div id="midcol">
    <div id="spacer">150px spacer</div>
</div>
<div id="rightcol">right</div>

CSS:

div {
    height:200px;
    display: inline-block;
    vertical-align: top;
    margin: 0px;
    float:left;
}
body {
    white-space: nowrap;
    margin:0px;
    max-height: 200px;
}
#lcol {
    background-color:blue;
    width: 100px;
}
#midcol {
    background-color: yellow;
    overflow-x: auto;
}
#spacer {
    min-width: 150px;
    height: 20px;
    background-color: gray;
    margin: 5px;
}
#rightcol {
    background-color: red;
    width:100px;
}

JAVASCRIPT (with jquery)

function adjustSizes() {
    // Sizes of middle divs are dynamic. Adjust once
    // built or whenever the viewport resizes
    //
    var $leftDiv = $('#lcol')
    var $milddleDiv = $('#midcol');
    var $rightDiv = $('#rightcol');

    // 1. Resize middle div to available viewport space
    var maxBodyWidth = $(window).innerWidth() - ($leftDiv.outerWidth() + $rightDiv.outerWidth());
    $milddleDiv.css('maxWidth', maxBodyWidth);

}

$(window).resize(function () {
    adjustSizes();
});

And the fiddle: https://jsfiddle.net/bjmekkgj/2/

Upvotes: 1

Views: 2946

Answers (4)

manpreet
manpreet

Reputation: 675

I think setting max-width of spacer will solve your problem in case content increases.
Set max-width to calc(100vw - 200px) if all margin and padding are 0. Otherwise adjust the value 200px taking margin, padding into account.

I have created a plunker. Please check if it solves your issue. Try checking after running plunker in spearate window
http://plnkr.co/edit/WG9v0MyiD2hiaZrOA3Yw?p=preview

Upvotes: 4

BCDeWitt
BCDeWitt

Reputation: 4773

For the one example you provided, since the left and right columns are positioned absolutely, you should take up the space somehow. I used padding on the middle column, then nested a "content" block inside that represents the visible part of the middle column. Then, I put overflow-x: auto; on the new content block and set a max-width on the overall container to force the new block to shrink.

(In previous edits, I was attempting to do this same thing but with floats instead of absolutely positioned divs)

* { margin: 0px; padding: 0px; }

#container {
    box-sizing: border-box;
    display: inline-block;
    position: relative;
    max-width: 100%;
    border: 1px solid black;
    height: 200px;
}

.column {
    box-sizing: border-box;
    height: 100%;
}

#left {
    position: absolute;
    left: 0px;
    top: 0px;
    bottom: 0px;
    width: 100px;
    border-right: 1px solid black;
    background: blue;
}

#mid {
    border: none;
    padding: 0px 100px;
}
#mid > .content {
    box-sizing: border-box;
    background-color: yellow;
    overflow-x: auto;
    height: 100%;
}

#spacer {
    width: 150px;
    height: 20px;
}

#right {
    position: absolute;
    right: 0px;
    top: 0px;
    bottom: 0px;
    width: 100px;
    border-left: 1px solid black;
    background: red;
}
<div id="container">
    <div id="left" class="column">
        left
    </div>
    <div id="mid" class="column">
        <div class="content">
            <div id="spacer">
                150px spacer
            </div>
        </div>
    </div>
    <div id="right" class="column">
        right
    </div>
</div>

...and in JSFiddle form

Upvotes: 1

Caleb Kleveter
Caleb Kleveter

Reputation: 11494

Try setting the middle div to have a max width with a percentage so it will get thinner with the screen size:

.midcol { 
  max-width: 25%; 
}

I put a value for the max-width in there for an example, but you can change the value.

Upvotes: 0

Paulie_D
Paulie_D

Reputation: 115288

flexbox can do that.

div {
  border-style: solid;
  border-width: 1px;
}
#container {
  height: 200px;
  display: flex;
}
#lcol {
  background-color: blue;
  width: 100px;
}
#midcol {
  background-color: yellow;
  flex: 1;
  overflow-x: auto;
}
#rightcol {
  background-color: red;
  width: 100px;
}
<div id="container">
  <div id="lcol">
    left
  </div>
  <div id="midcol">
  </div>
  <div id="rightcol">
    right
  </div>
</div>

JSfiddle Demo (showing overflow effect).

Support is IE10 and up.

Upvotes: 0

Related Questions