CSS 100% width but avoid scrollbar - css

This is probably a variation on something that has been solved dozens of times but CSS really makes me feel like a fool.
I am trying to build a widget that can be positioned and sized in a variety of ways. It's a pretty simple layout - fixed-height header, fixed-height footer, and a body that takes up the remaining space. The overall width and height varies. The content of the body needs to scroll. I have the overall container, header, footer, and body sizing ok.
But what I want is for the body to scroll when it needs to WITHOUT shrinking content to the left when the scrollbar appears. That is, I want the body to be as wide as it can MINUS the scrollbar that would be there iF it needed to scroll, so that when it DOES need to scroll there is no shrink. In effect, I want this:
| - - - unknown width - - -|
+--------------------------+
| content |*|
| might |*|
| scroll |*|
+--------------------------+
I want the content that might scroll to be as wide as it can MINUS the potential scrollbar width (|*| region).
What I have now is something like this:
<div id="content" style="position: absolute; overflow-y: auto; width: 100%">
<div id="scrollContent" style="???">
</div>
</div>
I have tried margins, padding, even %-widths for the inner-most div and all 'do the shift' thing. I also need this to work in FF3, IE7/8 and (fantasy?) IE6.

Use overflow: scroll instead of overflow: auto - that'll force a scrollbar to always appear.

The answer by Mattias Ottosson to another question offers a crucial piece of information - the vw units are based on the viewport width including the scrollbar, while percentages will be based on the available width which doesn't include the space taken up by the scrollbar. In other words, for an element taking up the full width of the page, the width of the scroll bar can represented as calc(100vw - 100%)
If we have a top-level element taking up 100% of the available width, then we can use this to control what changes size when the scrollbar becomes visible. Let's say our goal layout is something like this:
.app {
display: grid;
grid-template-columns: 1fr 50vh 1fr;
}
Where we want the middle column to be 50% as wide as the viewport height and the rest of the width divided between the left and right column. If we used that, then the addition of a scrollbar means that the horizontal space lost to the scrollbar (about 15px on chrome) is taken out of the width of the left and right columns equally. This can cause an ugly shift when a ui change causes the scrollbar to appear while the main content in the grid remains the same or similar. See the first snippet below.
We can use the calculated width of the scrollbar to instead only shrink the right column:
.app {
display: grid;
grid-template-columns: calc((100vw - 50vh)/2) 50vh calc(100% - (50vh + 100vw)/2);
}
See the second snippet below. Unfortunately this means the fr units can't be used and the width of the columns must be specified a little more manually. In this case the width of the left column is half of the viewport width minus the 50vh taken up by the center column. The width of the right column is the space remaining from the available width (100% rather than 100vw) after subtracting the combined width of the left and center columns. This is clearer in the formula:
calc(100% - ((100vw - 50vh)/2) - (50vh))
which reduces to the one above
First snippet, ugly jump when scrollbar appears
$('button').click(() => {
$('.footer').toggle()
})
body, html {
height: 100%;
width: 100%;
padding: 0;
margin: 0;
overflow: auto;
font-family: 'Archivo', sans-serif ;
}
.app {
margin: auto;
display: grid;
grid-template-columns: 1fr 50vh 1fr;
text-align: center;
height: 100%;
width: calc(100% - 10px);
}
.left-column, .center-column, .right-column {
padding: 10px;
min-height: 50vh;
border: 1px solid black;
}
.left-column {
border-right: none;
background-color:#def;
}
.center-column {
background-color:#e1ebbd;
}
.right-column {
text-align: left;
border-left: none;
background: #fb1;
}
.footer {
grid-column: 1 / span 3;
height: 2000px;
background: #753;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<div class="app">
<div class="left-column">
Left
</div>
<div class="center-column">
Center
<script src="https://code.jquery.com/jquery-3.1.0.js"></script><br>
<button>Toggle footer</button>
</div>
<div class="right-column">
Right
</div>
<div class="footer">
</div>
</div>
</body>
</html>
second snippet, right column shrinks when scrollbar appears
$('button').click(() => {
$('.footer').toggle()
})
body, html {
height: 100%;
width: 100%;
padding: 0;
margin: 0;
overflow: auto;
font-family: 'Archivo', sans-serif ;
}
.app {
margin: auto;
display: grid;
grid-template-columns: calc((100vw - 50vh)/2) 50vh calc(100% - (50vh + 100vw)/2);
text-align: center;
height: 100%;
width: calc(100% - 10px);
}
.left-column, .center-column, .right-column {
padding: 10px;
min-height: 50vh;
border: 1px solid black;
}
.left-column {
border-right: none;
background-color:#def;
}
.center-column {
background-color:#e1ebbd;
}
.right-column {
text-align: left;
border-left: none;
background: #fb1;
}
.footer {
grid-column: 1 / span 3;
height: 2000px;
background: #753;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<div class="app">
<div class="left-column">
Left
</div>
<div class="center-column">
Center
<script src="https://code.jquery.com/jquery-3.1.0.js"></script><br>
<button>Toggle footer</button>
</div>
<div class="right-column">
Right
</div>
<div class="footer">
</div>
</div>
</body>
</html>

The only way you can "get" and use the scrollbar-width with pure CSS is to actually have the scrollbar be there. Now, we don't want to force the scrollbar be visible all the time, so what we have to do is this:
Make a container for all of the website's content that always has the scrollbar shown, and hide it. It's surprisingly simple!
I've created a Fiddle. Here it is as a snippet:
/* The trick: */
html {
overflow-x: hidden;
}
body {
margin: 0;
width: 100vw;
}
body > * {
overflow-y: scroll;
margin-right: -100px;
padding-right: 100px;
}
/* Other styling: */
body {
font-family: sans-serif;
user-select: none;
--color: rgb(255 191 191);
}
header {
position: sticky;
top: 0;
z-index: 1;
--color: rgb(191 191 255);
}
body > * > div {
background-color: var(--color);
border: 3px solid;
margin: 10px;
padding: 10px 20px;
font-size: 20px;
font-weight: bold;
}
label::before {
position: relative;
content: '';
display: inline-block;
width: 1em;
height: 1em;
margin: 0 10px;
top: .2em;
border: 1px solid;
border-radius: .1em;
}
input:checked + label::before {
background-color: var(--color);
box-shadow: inset 0 0 0 1px #FFF;
}
input {
display: none;
}
input:not(:checked) ~ div {
display: none;
}
input ~ div {
height: 200vh;
}
<header>
<div>I am sticky!</div>
</header>
<main>
<div>Hello world!</div>
<input id="foo-2" type="checkbox" />
<label for="foo-2">Click me</label>
<div>Let's scroll</div>
</main>
The trick is giving the containing elements a negative margin and positive padding to the right. The offset used for these two properties can exceed the scrollbar-width, so making it 100px is plenty — I can't imagine any browser or website having scrollbars wider than 20px, let alone 100px.
By the way: The reason I'm applying these styles to every direct child of body, instead of having a single #container element, is because otherwise position: sticky wouldn't work. To have that feature work on an element, it can only have one anscestor with scrolling capabilities.
html contains #container contains sticky element -> does not work
html contains sticky container -> does work

Why not displaying always the scrollbars, even when there is no need to scroll?
You can achieve this by setting overflow:scroll; to the container.

Add another wrapper inside the element that will have the overflow:auto style and set it to about 18px narrower. The scrollbar should appear in that 18px gap.

I had a problem that is similar that I used the below solution for, I am not sure if this can be a solution to what you want to do, but it could be.
I had a div that resized to content automatically, and then the scroll was added, shrinking the inside, so that the table in it wrapped text, instead of making the container that much wider. The unwanted effect is seen in the below Old example, if the textarea is resized downward and the scroll appears.
My ugly solution was to add a div inside the overflow-y:auto-div, that had display:inline-block, and to add yet another small inline-block div after it, that was 19 pixels wide (reserved for scrollbar) and a pixel high. That little div would appear beside the real div when the browser resized the div to the content, and when the scrollbar appear, the small div is pushed down under the real div, and the real div keeps it's with. It will cause a one pixel bottom "margin", but hopefully not a problem. When no scrollbar ppears, there is 19 pixel of unused space beside the real div, as described in the Question.
(The outermost div is just there to replicate my setup/problem.)
Old:
<div style="display:inline-block">
<div style="max-height:120px; overflow-y:auto; border:1px solid gray">
<table border=1><tr>
<td>I do not</td><td>want this to</td>
<td>add breaks in the text.</td>
</tr></table>
<textarea rows=3 cols=15>Resize me down</textarea>
</div>
</div>
<br>
New:
<div style="display:inline-block">
<div style="max-height:150px;overflow-y:auto; border:1px solid gray">
<div style="display:inline-block">
<table border=1><tr>
<td>I do not</td><td>want this to</td>
<td>add breaks in the text.</td>
</tr></table>
<textarea rows=3 cols=15>Resize me down</textarea>
</div>
<div style="display:inline-block; width:19px; height:1px"></div>
</div>
</div>
<br>

I know that you want achieve this with CSS only, but I am giving a jQuery solution in case someone might find help.
Using jQuery, you can get the scrollbar size and then apply a margin to the container.
Something like this:
var checkScrollBars = function(){
var b = $('body');
var normalw = 0;
var scrollw = 0;
if(b.prop('scrollHeight')>b.height()){
normalw = window.innerWidth;
scrollw = normalw - b.width();
$('#container').css({marginRight:'-'+scrollw+'px'});
}
}
The above code snippet will add a margin if the height of all the content is greater than the container height.
We can also remove the horizontal scrollbar if it isn't needed:
body{
overflow-x:hidden;
}

You can do it with using this css on the content element: `calc(100% - 15px)`.
// calc(100% - the width we want to give on right hand side of content)
Please read below to check how will it work.
Definitely the most easy and less messy way to fix it using the overflow:scroll.
But if you do not want to show the scroll when it is not required then you should use the width in with respect to viewport (vw) instead of using 100%. As scrollbar comes in the viewport width, if we are aware about the width of scrollbar then we can accomplish our task using the below formula. Here i am setting the content width as viewport width minus the width of the scrollbar(let say 15px).
You need to provide width as: calc(100% - 15px). You can provide width in %, em etc.
The best would be if you override the width of scrollbar like below and then use that width value in your formula to subtract.
/* width */
::-webkit-scrollbar {
width: 10px;
}
#content {
width: calc(100% - 10px).
}
Note: Custom scrollbars are not supported in Firefox or in Edge, prior version 79. And this CSS only works in webkit browsers, so it might not work in IE.
So you can use 20px of maximim width to subtract becasue scrollbar can never take width more than 20px. Please find below the working code.
.scroll {
height: 100px;
overflow: auto;
border: 1px solid black;
width: 75%;
}
.zui-table {
width: calc(100% - 10px);
border: solid 1px #DDEEEE;
border-collapse: collapse;
border-spacing: 0;
font: normal 13px Arial, sans-serif;
}
.zui-table thead th {
background-color: #DDEFEF;
border: solid 1px #DDEEEE;
color: #336B6B;
padding: 10px;
text-align: left;
text-shadow: 1px 1px 1px #fff;
}
.zui-table tbody td {
border: solid 1px #DDEEEE;
color: #333;
padding: 10px;
text-shadow: 1px 1px 1px #fff;
}
<div class="scroll">
<table class="zui-table">
<thead>
<tr>
<th>Name</th>
<th>Position</th>
<th>Height</th>
<th>Born</th>
<th>Salary</th>
</tr>
</thead>
<tbody>
<tr>
<td>DeMarcus Cousins</td>
<td>C</td>
<td>6'11"</td>
<td>08-13-1990</td>
<td>$4,917,000</td>
</tr>
<tr>
<td>Isaiah Thomas</td>
<td>PG</td>
<td>5'9"</td>
<td>02-07-1989</td>
<td>$473,604</td>
</tr>
<tr>
<td>Ben McLemore</td>
<td>SG</td>
<td>6'5"</td>
<td>02-11-1993</td>
<td>$2,895,960</td>
</tr>
<tr>
<td>Marcus Thornton</td>
<td>SG</td>
<td>6'4"</td>
<td>05-05-1987</td>
<td>$7,000,000</td>
</tr>
<tr>
<td>Jason Thompson</td>
<td>PF</td>
<td>6'11"</td>
<td>06-21-1986</td>
<td>$3,001,000</td>
</tr>
</tbody>
</table>
</div>

I had a similar scenario where I had a grid - heading row and actual data rows below it. The Data rows may be too much and get scrollbar, which will cause the cells in the rows to missalign from the cells in the heading row.
I solved this by using position:absolute on the right column in the rows, which contains a couple of buttons. Don't know if this will be applicable to your case, but it was perfect for mine.
Here is an example:
function toggleMoreRows() {
document.getElementById('grid-body').classList.toggle('more-rows');
}
body {
font-size: 13px;
font-family: Arial, Verdana, sans-serif;
}
.grid-heading {
width: 500px;
background: #CCC;
font-weight: bold;
}
.grid-body {
width: 500px;
max-height: 200px;
overflow-y: auto;
overflow-x: hidden;
}
.row {
height: 32px;
display: flex;
align-items: stretch;
position: relative;
}
.row.hidden {
display: none;
}
.more-rows .row.hidden {
display: flex;
}
.cell {
width: 100px;
display: flex;
align-items: center;
justify-content: center;
}
.cell.actions {
width: 200px;
height: 100%;
justify-content: space-around;
position: absolute;
left: 300px;
top: 0;
}
<p><button onClick="toggleMoreRows()">Toggle more rows</button></p>
<div class="row grid-heading">
<div class="cell">First name</div>
<div class="cell">Last name</div>
<div class="cell">Age</div>
<div class="cell actions">Actions</div>
</div>
<div class="grid-body" id="grid-body">
<div class="row">
<div class="cell">Asdf</div>
<div class="cell">Asdf</div>
<div class="cell">12</div>
<div class="cell actions">
<button>Edit</button>
<button>Delete</button>
</div>
</div>
<div class="row">
<div class="cell">Asdf</div>
<div class="cell">Asdf</div>
<div class="cell">12</div>
<div class="cell actions">
<button>Edit</button>
<button>Delete</button>
</div>
</div>
<div class="row">
<div class="cell">Asdf</div>
<div class="cell">Asdf</div>
<div class="cell">12</div>
<div class="cell actions">
<button>Edit</button>
<button>Delete</button>
</div>
</div>
<div class="row">
<div class="cell">Asdf</div>
<div class="cell">Asdf</div>
<div class="cell">12</div>
<div class="cell actions">
<button>Edit</button>
<button>Delete</button>
</div>
</div>
<div class="row hidden">
<div class="cell">Asdf</div>
<div class="cell">Asdf</div>
<div class="cell">12</div>
<div class="cell actions">
<button>Edit</button>
<button>Delete</button>
</div>
</div>
<div class="row hidden">
<div class="cell">Asdf</div>
<div class="cell">Asdf</div>
<div class="cell">12</div>
<div class="cell actions">
<button>Edit</button>
<button>Delete</button>
</div>
</div>
<div class="row hidden">
<div class="cell">Asdf</div>
<div class="cell">Asdf</div>
<div class="cell">12</div>
<div class="cell actions">
<button>Edit</button>
<button>Delete</button>
</div>
</div>
<div class="row hidden">
<div class="cell">Asdf</div>
<div class="cell">Asdf</div>
<div class="cell">12</div>
<div class="cell actions">
<button>Edit</button>
<button>Delete</button>
</div>
</div>
<div class="row">
<div class="cell">Asdf</div>
<div class="cell">Asdf</div>
<div class="cell">12</div>
<div class="cell actions">
<button>Edit</button>
<button>Delete</button>
</div>
</div>
</div>

The problem is once you hover over the container and the scrollbar appears, then the content width shrinks. So even if you use a nested container whose width is equal to the container minus its scrollbar, the width of nested container will also shrink.
One solution is to increase the size of the contents by the width of the scrollbar on hover. Here is a solution that doesn't need to use any nested outer containers (categoryCont is the scrolling container and each menuBlock is one of the items to be scrolled):
<div id="categoryCont" style="position:relative;width:200px; overflow:hidden;">
<div class="menuBlock" style="width:200px">a</div>
<div class="menuBlock" style="width:200px">b</div>
<div class="menuBlock" style="width:200px">c</div>
...
</div>
<style type="text/css">
#categoryCont:hover{
overflow-y: auto;
}
#categoryCont:hover .menuBlock{
/* Increase size of menu block when scrollbar appears */
width: 218px; /* Adjust for width of scroll bar. */
}
</style>
One issue with the above is that the width of scrollbar differs slightly in different browsers. One of the following should help:
By using px
Make the content an absolute value with left indent as an absolute value
<div class="menuBlock" style="width:200px">
a
</div>
changes to
<div class="menuBlock" style="width:200px">
<span>a</span>
</div>
<style>
.menuBlock span{ /* Good cross-browser solution but cannot use % */
position:absolute;
left:70px;
}
</style>
By using %
You need both CSS and jQuery(First step is same)
<div class="menuBlock" style="width:200px">
a
</div>
changes to
<div class="menuBlock" style="width:200px">
<span>a</span>
</div>
<style>
.menuBlock span{ /* Good cross-browser solution but cannot use % */
position:absolute; /* This one does not use 'left' */
}
</style>
<script>
// Indent left 30% because container width remains same but content width changes
var leftIndent = (30/100) * $("#categoryCont").width();
$(".menuBlock span").css({"left":leftIndent});
</script>

I'm not really sure what your asking (sorry, I have very little CSS experience), but I think you want to set the width of an HTML div element to 100% with CSS, without having a scroll bar appear. Here is a solution.
#element {
background-color: blue;
height: 40px;
position: relative;
margin-left: 0px;
margin-right: 0px;
padding-left: 0px;
padding-right: 0px;
width: 100%;
}
<!DOCTYPE html>
<html lang="en">
<body>
<div id="element"></div>
</body>
</html>
A scroll bar appears because of the position, margin and padding properties of the div element. If you set the margin-right, margin-left, padding-right, and padding-left properties to 0, and you set the position property to relative, no scroll bar will appear.

* {
overflow: hidden;
}
simple way to hide the scrollbar

Related

Ensuring that responsive image and class are the same size

I'm trying to make a design that utilizes white space.
I have an image that I want on a white background. I have a class that has a white background, and the image itself (which also has a white background as part of the image). I'm having an issue where I can't ensure that the div class is the same height as the image itself if I have both be responsive.
I've tried adding a second image with the same height as the initial image that is just white space, setting the div to be responsive, and a bunch of other things, but I'm not sure what the best way to do this would be. The page itself is up at http://jamieaurora.com/devinTribute.html to get an idea of what I'm going for (though the code is a bit out of date than what I'm posting here). If anyone could point me in the right direction, it'd be greatly appreciated. I cut out the portions of the code that I don't feel are relevant, but if you would like to take a look at the full HTML file, it is located in this hastebin. Thank you so much!
https://hastebin.com/tifiqaciri.xml
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/js/bootstrap.min.js"></script>
<style>
.responsive
{
width: 100%;
height: auto;
}
.hero-section
{
background-color: white;
font-family: Oswald;
letter-spacing: 4px;
top: 0;
height: 64%;
width: auto;
padding-top: 5%;
padding-bottom: 1%;
}
</style>
<body>
<nav>
<ul id='navbar' style="z-index:0;">
<li><a class = "active" href="index.html">Home</a></li>
</ul>
</nav>
<section class="hero-section" id="hero-section">
<div class = "container-fluid">
<div class = "row">
<div class="col-xs-6">
<img src = "images/devin-townsend-evermore.jpg" class="responsive" ></img>
</div>
<div class="col-xs-6">
<h1 style="padding-left: 62%" class="responsive">Title Text</h1>
<h2 style = "padding-left: 60%; font-size: 140%; align: left;" class="responsive">Paragraph Text</h2>
</div>
</div>
</div>
</section>
I had a parent div container with two main components side-by-side. I had an image on the right that was responsive. I wanted the text on the left side to stay in the centre and to the left of the image as it changed size depending on the browser's screen size.
I set the parent's container height to the same size as the image in its original form but in em.
Using a combination of height: auto and max-height: 100% worked for me.
The return in my React Component was:
<div className="videoAndDescription">
<div className="left33">
<div className="textToSquare">
<h1>Firewood, delivered...</h1>
</div>
</div>
<div className="right66">
<img src={stoveburning} />
</div>
</div>
My CSS:
.videoAndDescription{
display: flex;
flex-direction: row;
background-color: red;
height: 40em;
}
.left33{
color: orange;
display: flex;
justify-content: center;
align-content: center;
width: 60%;
}
.left33 .textToSquare{
height: auto;
background-color: black;
}
.right66{
width: 40%;
}
.right66 img{
max-height: 100%;
}

Table / Table cell / Table cell > and get 100 height challenge

I'm unable to solve this problem:
I want to divide a known width space in two elements : textarea and a space for custom scrollbar. The textarea has a fix height (or dynamic if you use the vertical resizer) .
The table / table cell without width / table-cell width 1 px does the work, almost ....
The problem is that I'm unable to give the correct height & width and position for the right div.
If I use a wrapper to use the "absolute position" approach I have the correct height but wrong positioning (you can see using chrome or similar inspect tool that the div is outside...)
If I dont use the "absolute pos" approach I have the right width but no height... ( use the snippet, disable positioning for wrapper and inner div and see how there is a 20px space.)
I'm almost crazy with this problem...
I want to have and automatic width & height for the right div...
Any help w. be appreciated.
<div style="display: table;width: 320px; border: 1px solid red;"">
<div style="display: table-cell;">
<textarea style="width: 100%; height: 100px; max-height: 200px; resize: vertical;"></textarea> </div>
<div style="display: table-cell; width: 1px;height: 100%;position: relative;">
<div style="display: block; position: absolute; top: 0;bottom: 0;">
<div style="display:block; width: 20px;">
</div>
</div>
</div>
</div>
I think the problem is mainly caused by the browser default padding that applied to the <textarea>, you can simply set box-sizing: border-box; to it.
And remove that absolute positioned <div>, everything should work, updated demo below.
textarea {
box-sizing: border-box;
}
div, textarea {
vertical-align: top;
}
<div style="display: table; width: 320px; border: 1px solid red;">
<div style="display: table-cell;">
<textarea style="width: 100%; height: 100px; max-height: 200px; resize: vertical;"></textarea>
</div>
<div style="display: table-cell; width: 1px; height: 100%; border: 1px solid blue;">
placeholder
</div>
</div>

Scrollbar on window resize for only one div in multi-div vertical layout

I've been on this for days and read every conceivable article on css, overflow, and layout.
I have a page with a banner (position: absolute), below which is a div containing two block divs. The second block div, in turn has another div containing text.
I would like the inner-most DIV display a scroll bar when the window is resized.
I've read the posting on ensuring height is set on all containing elements, I've set overflow-y: auto in all the right places. Just doesn't work.
The containing DIV looks like this: http://i.imgur.com/oDHM4.png
I want the green part to scroll when the browser window is resized (y-direction only).
Scrollable DIVs in any design are so useful... but shouldn't be this hard.
Any and all help appreciated.
Danny
MARKUP
The markup is very simple:
<body>
<div id="page-header" style='background:blue;'>page-header</div>
<div id="page-content">
<div id="configContent" style='height: inherit; background: steelblue;'>
<h1 id='panTitle'>Panel Title</h1>
<div id='panProbes' class='libPanel' style="background: maroon;">
<p>panProbes</p>
<div id="probesCT1" class="configtable" style='background: red;'>
<p class='pTblTitle'>probesCT1</p>
</div>
<div id="probesCT2" class="configtable" style='background: grey;'>
<p>probesCT2</p>
<div id='pTbl' style='background: green;'>
<div class='pRow'>1st para in pTbl</div>
<div class='pRow'>some data</div>
<div class='pRow'>some data</div>
<div class='pRow'>some data</div>
<div class='pRow'>some data</div>
<div class='pRow'>some data</div>
<div class='pRow'>some data</div>
<div class='pRow'>some data</div>
<div class='pRow'>some more data</div>
<div class='pRow'>some more data</div>
</div>
</div>
</div>
</div>
</div>
</body>
** STYLING **
Here's the CSS cut down to the core essence:
html, body {
position:absolute;
margin: 0px;
padding: 0px;
height: 100%;
width: 1010px;
overflow: hidden;
}
#page-header {
position: absolute;
left: 5px;
top: 5px;
height: 60px;
width: 100%;
}
#page-content {
width: 100%;
height: 100%;
margin-top: 95px;
}
#configContent {
height: 100%;
width: 300px;
padding-left: 0px;
border-width: 3px;
margin-left: 30px;
margin-right: auto;
}
.libPanel { height: 100%; }
#probesCT1 { width: 150px; margin: 0 auto 0 30px; }
#probesCT2 {
width: 200px;
/* height: 100%; */
margin: 0 30px 50px 30px;
padding: 0 10px 10px 10px;
}
#pTbl { overflow-y: auto; }
.pRow { margin-bottom: 10px; }
For overflow-y: auto to work and make scroll bars, that div must have a specific height set. So in this example (with your html above) I set it to 200px, which was less space than necessary to display the content without a scroll bar, and thus shows a scroll bar. However, if set to 100% it does not work, because 1) you need to uncomment the height of the containing divs, and 2) your content in that div is less than needed to fill the height of the div, so no scroll bar shows up. With more content added, you get a scroll bar.
What I think you really want is to insure you always have a scroll bar if needed, but even then, you need to make sure the div does not extend below the bottom of the page or you could still have problems with the scroll bar itself going off the page. I've configured something that is probably more what your intent is, but note that I had to use multiple nested relative or absolute elements to achieve the effect. I also had to guess on some height positioning for the top of elements to clear your titles.

CSS DIV-based table with header and limited height showing scrollbar when necessary - percentage heights

I've searched high and low and cannot find a solution specific to this problem. I'm trying to accomplish the following:
Have a container DIV defined with a percentage height to serve as max-size container
A secondary container DIV that provides a content size-based borde
Have a header div that is fixed at the top of that DIV
Have a list of DIVs (table-like) under the header
When the list is short, the border is reduced to size of content
When list if long (> height of outer container), scrollbar is shown for DIV list and not header.
I put together the following simplified version:
<html>
<head>
<style type="text/css">
.panel { height: 10%; border: 1px solid red; overflow: hidden; margin-top: 10px; }
.sizer { max-height: 100%; border: 1px solid blue; }
.header { border-bottom: 1px solid black; }
.scroll { max-height: 100%; overflow: auto; }
</style>
</head>
<body>
<div class="panel">
<div class="sizer">
<div class="wrap">
<div class="header">Header</div>
<div class="scroll">
<div>Line1</div>
<div>Line2</div>
</div>
</div>
</div>
</div>
<div class="panel">
<div class="sizer">
<div class="wrap">
<div class="header">Header</div>
<div class="scroll">
<div>Line1</div>
<div>Line2</div>
<div>Line3</div>
<div>Line4</div>
<div>Line5</div>
<div>Line6</div>
<div>Line7</div>
<div>Line8</div>
<div>Line9</div>
<div>Line10</div>
<div>Line11</div>
<div>Line12</div>
</div>
</div>
</div>
</div>
</body>
</html>
The two red boxes should be fixed size. Check
The blue box should size to be the size of the content or size of red box maximum. Check
When contents in lower exceed red box size, scrollbar should be displayed under header. Fail
Any change I make that gets the scrollbar displayed causes the top blue box to enlarge to the size of it's container, red box. e.g., { .scroll height: 100% }
(The DIV.wrap does have a purpose - just not in this example. It is intended to provide a double-border effect on the sizer, so it should be the same size as sizer all the time).
Also, I have figured out some solutions where I used fixed (px) sizes for the DIVs, but this is not necessarily desired. Especially on DIV.panel - this must be set to a percentage height.
Not completely sure i understand the question, but if you want the scroll on the list but not on the header, have you tried:
overflow-y:scroll;
on the "scroll" div instead of
overflow:auto?
Let me know
Ok i think maybe i worked it out. I think cause you have overflow:hidden and a height on the container div, and not the variable scroll div. Just try the code below and let me know. I have added the height of 10% to the scroll div and not the overall container. Hope thats what you were looking for
<html>
<head>
<style type="text/css">
.panel { border: 1px solid red; overflow: hidden; margin-top: 10px; }
.sizer { max-height: 100%; border: 1px solid blue; display:block;}
.header { border-bottom: 1px solid black; }
.scroll { height: 10%;overflow-y: scroll; display:block; }
.scroll div {display:block; line-height:normal; clear:both; height:20px;}
</style>
</head>
<body>
<div class="panel">
<div class="sizer">
<div class="wrap">
<div class="header">Header</div>
<div class="scroll">
<div>Line1</div>
<div>Line2</div>
</div>
</div>
</div>
</div>
<div class="panel">
<div class="sizer">
<div class="wrap">
<div class="header">Header</div>
<div class="scroll">
<div>Line1</div>
<div>Line2</div>
<div>Line3</div>
<div>Line4</div>
<div>Line5</div>
<div>Line6</div>
<div>Line7</div>
<div>Line8</div>
<div>Line9</div>
<div>Line10</div>
<div>Line11</div>
<div>Line12</div>
</div>
</div>
</div>
</div>
</body>
</html>

Adjust the width of the div to the width of the site

I need the center div div#b to fill out the gab between div#a and div#c.
<div id="a">
<span>Div1</span>
</div>
<div id="b">
<span>Div2</span>
</div>
<div id="c">
<span>Div3</span>
</div>
I tried to do this by placing width: 100% on div#b but without luck.
div
{
border:1px solid red;
}
div#a
{
float:left;
width:50px;
}
div#b
{
float:left;
width:100%; ?? <!-- Doesn't work!!! -->
}
div#c
{
float:right;
width:50px;
}
How can I get div#b to expand from div#a to div#c?
There can be no line breaks.
CSS3
You can implement this dynamic behavior using the CSS3 Flexible Box Layout Module:
<style type="text/css">
div.Container
{
width: 100%;
display: box;
display: -moz-box;
display: -ms-box;
display: -webkit-box;
}
div.B
{
background: magenta;
box-flex: 1;
-moz-box-flex: 1;
-ms-box-flex: 1;
-webkit-box-flex: 1;
}
</style>
<div class="Container">
<div style="width: 50px; background: cyan;">
A
</div>
<div class="B">
B
</div>
<div style="width: 50px; background: yellow;">
C
</div>
</div>
A new version of FireFox, a new version of Google Chrome, Internet Explorer 10 and a new version of Safari supports CSS3 flexible box layout. Internet Explorer 9 and Opera is lacking support at the moment.
I also want to mention this new way to do it in FireFox:
<div style="float: left; width: 50px; background: cyan;">
A
</div>
<div style="float: left; width: -moz-calc(100% - 100px); background: magenta;">
B
</div>
<div style="float: left; width: 50px; background: yellow;">
C
</div>
FireFox is the only browser that support the calc function at the moment.
CSS2
Here is the old way to do it:
<div style="padding-left: 100px;">
<div style="float: left; width: 50px; margin-left: -100px; background: cyan;">
A
</div>
<div style="float: left; width: 100%; margin-left: -50px; background: magenta;">
B
</div>
<div style="float: left; width: 50px; background: yellow;">
C
</div>
</div>
A width of 100% inside the container div is the width of the container minus the 100px left padding. Then there is room for the left and right 50px div elements. Then you have to position them using some negative margin and floating.
Feature detection
Use feature detection with Modernizr. Then you can use CSS2 for browsers that lack support for CSS3 flexbox.
If you do .NET development you can download Modernizr with NuGet.
I've hit similar problems myself. The problem here is "width: 100%" will basically inherit the width of the parent container.
The other problem is the float. When you ask div#b to float to the left alongside div#a, you can't use the fancy margin trick to force div#b to stay out of the way of div#a. (In other words, margin can be used to keep div#b from entering and interfering with a certain amount of space on any of its sides.) However, with float, the margin is now not pushing div#b away from the edge of the page, but away from the edge of div#a.
OK, so the solution looks like this. Remove the float on div#b, and then apply left and right margins so div#b doesn't interfere with either side columns. Let div#b determine its own size (i.e. don't give it a "width"), so it will fit between the two floats. Lastly, shift div#b so that the floats occur before div#b is put in place, so that div#b is put between the floats.
Here's the new code:
<style type="text/css">
div
{
border:1px solid red;
}
div#a
{
float:left;
width:50px;
}
div#b
{
margin-left: 55px;
margin-right: 55px;
}
div#c
{
float:right;
width:50px;
}
</style>
<div id="a">
<span>Div1</span>
</div>
<div id="c">
<span>Div3</span>
</div>
<div id="b">
<span>Div2</span>
</div>
Determining margins is tricky. Borders aren't counted in the width calculation of an element, so a 50px-wide div with a 1px border is actually 52px-wide.
I have a feeling you won't like this answer, but the easiest way to do it is to remove float: left and any width from div#b, and then switch up the order of your divs, so both the sidebars are before your main content area. Here's the code:
HTML:
<div id="a">
<span>Div1</span>
</div>
<div id="c">
<span>Div3</span>
</div>
<div id="b">
<span>Div2</span>
</div>
CSS:
div
{
border:1px solid red;
}
div#a
{
float:left;
width:50px;
}
div#b
{
overflow: hidden;
/*margin: 0 60px;*/
}
div#c
{
float:right;
width:50px;
}
Note that I've applied overflow: hidden to the middle div - this will force it into columns (in most browsers). You could use the given margins instead, if you're not comfortable with a "magic" solution (there is a reasonable explanation for it, but I can never remember it off the top of my head).

Resources