2 floated divs with first div width 100% - css

I have 2 divs floated left in a container div. The second div has width: 20px. I need the first div to fill all the available space and remains inline. Set first div width to 100% doesn't work because the second div with fixed width goes down. How can i do?
The code is described here: http://jsfiddle.net/7EW5h/4/
Thanks

You can use calc CSS3 function and set a dynamic width to #inner1 div as follows:
width: calc(100% - 20px);
It will be compatible with Firefox 16 (or later) and Internet Explorer 9 (or later).
You can add vendor prefixes as shown:
width: -moz-calc(100% - 20px);
width: -webkit-calc(100% - 20px);
width: calc(100% - 20px);
To make it compatible with Chrome 19 (or later), Firefox 4 (or later), Internet Explorer 9 (or later) and Safari 6 (or later).
You can check compatible tables here: http://caniuse.com/#search=calc
Regarding to you example, I had to set border: 0 to #inner1 and #inner2 divs.

I have tested and worked out a solution in Chrome, IE9, Firefox and Opera:
Use containers for the two input elements.
Change the order of the elements so that the right one is first.
Do not float the element that is supposed to fill the remaining space, just set the display to block (which is the default for div elements).
Set the margin-right of the larger container to the total width of the right element. Here we also need to account for things like borders, margins and paddings of both elements.
HTML:
<div id="container">
<div id="inner2">
<input />
</div>
<div id="inner1">
<input />
</div>
</div>​
CSS:
#inner2 {
float: right;
}
#inner2 input {
height: 20px;
width: 20px;
border: 1px solid #000;
}
#inner1 {
margin-right: 24px;
}
#inner1 input {
width: 100%;
height: 20px;
border: 1px solid #000;
}
Live example: http://jsfiddle.net/7EW5h/22/.
Also note that i have explicitly set borders on the two input elements.
I can not get it to work without changing the HTML or the order of the two elements without using absolute positioning.

Have you tried using position:absolute; to position the elements as you need?
See fiddle - JSFiddle Example

I think, without complicating things, you can do the following.
​Remove the floats from the two inputs.
Absolutely position the second input as shown below.
add padding-right to the first input to avoid content overlap.
also, even if it is not shown in my code below, don't forget the presence of default border, margin and padding.​ ​
#container {
overflow: hidden;
background-color: red;
}
#inner1 {
width: 100%;
background-color: blue;
padding-right:45px;
}
#inner2 {
height: 20px;
width: 20px;
background-color: green;
position:absolute;
right:0;
top:0;
}
​

Related

Unexpected scroll bars with calculated height accounting for margin

I have the following CSS and HTML
body {
margin:0px
}
.outer {
height: 100vh;
}
.inner {
height: calc(100vh - 20px);
margin: 20px;
}
<div class="outer">
<div class="inner">
</div>
</div>
This results in scroll bars.
If I remove the 'outer' class, everything works as expected - no scroll bars.
Obviously, the outer class is redundant, however, I want to know why the scroll bars appear
Any ideas?
This is because browsers define a default margin for the body.
Your outer starts lower and to the right by about 10px (the default margin), and then extends its size equal to the size of the viewport by creating the scroll bars.
When the default margin is reset, the scroll bars disappear.
body, html {
margin: 0px;
}
.outer {
height: 100vh;
background-color: green;
}
.inner {
position: absolute;
width: calc(100vw - 40px);
height: calc(100vh - 40px);
margin: 20px;
background-color: yellow;
}
<div class="outer">
<div class="inner">
</div>
</div>
UPDATE
In my first answer I had copied your code including an error (margin 20px on the .inner class) that did not allow me to see this further "problem", however the first answer remains valid, even if partial.
This second problem in my opinion is due to the "margin collapse". Here is a paragraph (of this MDN doc) that I believe is your case:
These rules apply even to margins that are zero, so the margin of a
descendant ends up outside its parent (according to the rules above)
whether or not the parent's margin is zero.
If you inspect with the browser developer tools (maybe with colors it is easier than with both white boxes) you will realize that the margin of .inner comes out of his parent .outer.
You can find the solution in the MDN guide, in my case I set position: absolute to .inner class, but you can find the same answers here: SO Answer
And last thing margin: 20px applies 40px of margin per height (20px top and 20px bottom) and 40px width, so your calc should be height: calc(100vh - 40px);.
Code updated above

Two divs inside another div and slide left right

I have a div that is masked off in terms of its width. Inside, I have 2 divs of the same width floated, so 100% + 100%. This means that either the left is visible or the right is visible at any one time.
In fact, what I'm trying to achieve is almost exactly the same as this:
jquery slide div within a div
Just one difference though. The height of my parent isn't fixed, it's dependent on the child size. So when I apply position: absolute; to the parent, it all goes pear-shaped.
Any solutions to this? I can use flexbox if necessary as I don't support IE8/9.
CSS would be something like this
.outer-wrap {
overflow:hidden;
position:relative;
width:300px;
}
.middle-wrap {
overflow:hidden;
position:absolute; // this doesn't work because it has no fixed height
left:0;
width:600px;
}
.middle-wrap.open {
right:0;
}
.inner-wrap {
float:left;
width:300px;
}
HTML
<div class="outer-wrap">
<div class="middle-wrap">
<div class="inner-wrap"></div>
<div class="inner-wrap"></div>
</div>
</div>
Another edit: I created a codepen, it's here: http://codepen.io/anon/pen/oxwmex CLick on the two buttons on the far right, they switch between the states
As you noted, your solution doesn't work because .middle-wrap has no fixed height. Try it with the following settings (note: no floats, no absolute positions):
.outer-wrap {
overflow-x: hidden;
position: relative;
border: 1px solid red;
width: 300px;
margin: 0 auto;
}
.middle-wrap {
position: relative;
width: 600px;
left: 0px;
}
.inner-wrap {
display: inline-block;
width: 300px;
vertical-align: top;
}
This will display the left of the two .inner-wraps within the visible part of .outer-wrap. To make the right .inner-wrap visible apply something like
jQuery(".middle-wrap").css("left", "-300px")
to the element or event you use for switching between the two inner-wraps. Or if you want it animated:
jQuery(".middle-wrap").aminmate({left: "-300px"})
(Plus another method to switch back to left: 0px)
The heigth of all elements is automatically adjusted to the heigth of the higher of the two .inner-wrap elements.
P.S. (edit): Erase the style="height:100px;" settings from the inner-wraps in the HTML, just fill them with some content to see it working.

Setting width/height as percentage minus pixels

I'm trying to create some re-usable CSS classes for more consistency and less clutter on my site, and I'm stuck on trying to standardize one thing I use frequently.
I have a container <div> that I don't want to set the height for (because it will vary depending on where on the site it is), and inside it is a header <div>, and then an unordered list of items, all with CSS applied to them.
It looks a lot like this:
I want the unordered list to take up the remaining room in the container <div>, knowing that the header <div> is 18px tall. I just don't know how to specify the list's height as "the result of 100% minus 18px".
I've seen this question asked in a couple other contexts on SO, but I thought it would be worth asking again for my particular case. Does anyone have any advice in this situation?
You can use calc:
height: calc(100% - 18px);
Note that some old browsers don't support the CSS3 calc() function, so implementing the vendor-specific versions of the function may be required:
/* Firefox */
height: -moz-calc(100% - 18px);
/* WebKit */
height: -webkit-calc(100% - 18px);
/* Opera */
height: -o-calc(100% - 18px);
/* Standard */
height: calc(100% - 18px);
For a bit of a different approach you could use something like this on the list:
position: absolute;
top: 18px;
bottom: 0px;
width: 100%;
This works as long as the parent container has position: relative;
I use Jquery for this
function setSizes() {
var containerHeight = $("#listContainer").height();
$("#myList").height(containerHeight - 18);
}
then I bind the window resize to recalc it whenever the browser window is resized (if container's size changed with window resize)
$(window).resize(function() { setSizes(); });
Don't define the height as a percent, just set the top=0 and bottom=0, like this:
#div {
top: 0; bottom: 0;
position: absolute;
width: 100%;
}
Presuming 17px header height
List css:
height: 100%;
padding-top: 17px;
Header css:
height: 17px;
float: left;
width: 100%;
Use negative margins on the element you would like to minus pixels off. (desired element)
Make overflow:hidden; on the containing element
Switch to overflow:auto; on the desired element.
It worked for me!
Try box-sizing. For the list:
height: 100%;
/* Presuming 10px header height */
padding-top: 10px;
/* Firefox */
-moz-box-sizing: border-box;
/* WebKit */
-webkit-box-sizing: border-box;
/* Standard */
box-sizing: border-box;
For the header:
position: absolute;
left: 0;
top: 0;
height: 10px;
Of course, the parent container should has something like:
position: relative;
Another way to achieve the same goal: flex boxes.
Make the container a column flex box, and then you have all freedom to allow some elements to have fixed-size (default behavior) or to fill-up/shrink-down to the container space (with flex-grow:1 and flex-shrink:1).
#wrap {
display:flex;
flex-direction:column;
}
.extendOrShrink {
flex-shrink:1;
flex-grow:1;
overflow:auto;
}
See https://jsfiddle.net/2Lmodwxk/
(try to extend or reduce the window to notice the effect)
Note: you may also use the shorthand property:
flex:1 1 auto;
I tried some of the other answers, and none of them worked quite how I wanted them to. Our situation was very similar where we had a window header and the window was resizable with images in the window body. We wanted to lock the aspect ratio of the resizing without needing to add in calculations to account for the fixed size of the header and still have the image fill the window body.
Below I created a very simple snippet that shows what we ended up doing that seems to work well for our situation and should be compatible across most browsers.
On our window element we added a 20px margin which contributes to positioning relative to other elements on the screen, but does not contribute to the "size" of the window. The window-header is then positioned absolutely (which removes it from the flow of other elements, so it won't cause other elements like the unordered list to be shifted) and its top is positioned -20px which places the header inside of the margin of the window. Finally our ul element is added to the window, and the height can be set to 100% which will cause it to fill the window's body (excluding the margin).
*,*:before,*:after
{
box-sizing: border-box;
}
.window
{
position: relative;
top: 20px;
left: 50px;
margin-top: 20px;
width: 150px;
height: 150px;
}
.window-header
{
position: absolute;
top: -20px;
height: 20px;
border: 2px solid black;
width: 100%;
}
ul
{
border: 5px dashed gray;
height: 100%;
}
<div class="window">
<div class="window-header">Hey this is a header</div>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
</ul>
</div>
Thanks, i solved mine with your help, tweaking it a little since i want a div 100% width 100% heigth (less height of a bottom bar) and no scroll on body (without hack / hiding scroll bars).
For CSS:
html{
width:100%;height:100%;margin:0px;border:0px;padding:0px;
}
body{
position:relative;width:100%;height:100%;margin:0px;border:0px;padding:0px;
}
div.adjusted{
position:absolute;width:auto;height:auto;left:0px;right:0px;top:0px;bottom:36px;margin:0px;border:0px;padding:0px;
}
div.the_bottom_bar{
width:100%;height:31px;margin:0px;border:0px;padding:0px;
}
For HTML:
<body>
<div class="adjusted">
// My elements that go on dynamic size area
<div class="the_bottom_bar">
// My elements that goes on bottom bar (fixed heigh of 31 pixels)
</div>
</div>
That did the trick, oh yes i put a value little greatter on div.adjusted for bottom than for bottom bar height, else the vertical scrollbar appears, i adjusted to be the nearest value.
That difference is because one of the elements on dynamic area is adding an extra bottom hole that i do not know how to get rid of... it is a video tag (HTML5), please note i put that video tag with this css (so there is no reason for it to make a bottom hole, but it does):
video{
width:100%;height:100%;margin:0px;border:0px;padding:0px;
}
The objetive: Have a video that takes the 100% of the brower (and resizes dynamically when browser is resized, but without altering the aspect ratio) less a bottom space that i use for a div with some texts, buttons, etc (and validators w3c & css of course).
EDIT: I found the reason, video tag is like text, not a block element, so i fixed it with this css:
video{
display:block;width:100%;height:100%;margin:0px;border:0px;padding:0px;
}
Note the display:block; on video tag.
I'm not sure if this work in your particular situation, but I've found that padding on the inside div will push content around inside of a div if the containing div is a fixed size. You would have to either float or absolutely position your header element, but otherwise, I haven't tried this for variable size divs.

Pixel and percentage width divs side-by-side

I've found a lot of similar questions, and tried out several solutions (including some of the so-called "holy grail" CSS layouts), but they don't quite do what I need.
I have a containing div (a CSS containing block) with id right. Inside it on the left side, I want a fixed-width div (a splitter bar, but it doesn't matter what it's being used for; id splitpane); on the right, filling the rest of the space, another div (id right-box below).
I've tried making the two inner divs display: inline-block (with vertical-align: top), setting the left one to width: 3px, but then there's no way to set the right to have width 100% - 3px. I've also tried using the float: left/margin-left: -100%/margin-left: 3px trick, but it has the same problem: the 100% plus the 3px overflows the parent containing block and causes a scroll bar to pop up. (Of course, it's not the scroll bar per se that's the problem; I could use overflow: hidden to remove it, but then content on the right would be truncated.)
Currently I'm using width: 99.5% for the right div, but that's a terrible hack (and is subject to overflow depending on screen width). It looks a bit like this:
<div id="right"><div id="splitpane"></div><div id="right-box">
...
</div></div>
With CSS as follows (float version, but the inline-block version is similar):
#right {
display: inline-block;
vertical-align: top;
height: 100%;
width: 85%; /* this is part of a larger div */
}
#right-box {
width: 99.5%; /* stupid hack; actually want 100% - 3px for splitter */
height: 100%;
}
#splitpane {
float: left;
width: 3px;
height: 100%;
background: white;
border-left: solid gray 1px;
border-right: solid gray 1px;
cursor: e-resize;
}
Is it even possible to do this? This is for an internal app., so solutions only need to work in Firefox 3 (if they are specific to FF3, though, preferably it's because the solution is standards-compliant but other browsers aren't, not because it's using Firefox-only code).
DIVs are the wrong element type for this since they don't "talk" to each other. You can achieve this easily with a table:
<table style="width:200px">
<tr>
<td id="splitpane" style="width: 3px">...</td>
<td id="rightBox" style="width: 100%">...</td>
<tr>
</table>
The 100% will make the rightBox as wide as possible but within the limits of the table.
This is possible. Because block level elements automatically expand to take up any remaining horizontal space, you can utilise a block level element next to an uncleared floated element with your desired width.
<style type="text/css">
div {
height: 100px;
}
#container {
width: 100%;
}
#left {
background: #FF0;
}
#splitpane {
position: relative;
float: right;
background: #000;
width: 3px;
}
</style>
<div id="container">
<div id="splitpane"></div>
<div id="left"></div>
</div>
See http://jsfiddle.net/georeith/W4YMD/1/
why you didn't use margin-left (since it was float layout) on right box?
so no need to create a splitter div...
#right{
width:200px; /*specify some width*/
}
#rightbox{
float:left;
margin-left: 3px; /*replace the splitter*/
/*margin: 0 3px; /*use this to give left & right splitter*/ */
}
yeah something like that, i hate empty div, it's not semantic and it's like putting a splitter on the "old" table way
If the div #right-box is only going to contain non-floated content it might be an idea to just put the content inside #right instead and let it wrap around the floated #splitpane.

CSS 100% height with padding/margin

With HTML/CSS, how can I make an element that has a width and/or height that is 100% of it's parent element and still has proper padding or margins?
By "proper" I mean that if my parent element is 200px tall and I specify height = 100% with padding = 5px I would expect that I should get a 190px high element with border = 5px on all sides, nicely centered in the parent element.
Now, I know that that's not how the standard box model specifies it should work (although I'd like to know why, exactly...), so the obvious answer doesn't work:
#myDiv {
width: 100%
height: 100%;
padding: 5px;
}
But it would seem to me that there must be SOME way of reliably producing this effect for a parent of arbitrary size. Does anyone know of a way of accomplishing this (seemingly simple) task?
Oh, and for the record I'm not terribly interested in IE compatibility so that should (hopefully) make things a bit easier.
EDIT: Since an example was asked for, here's the simplest one I can think of:
<html style="height: 100%">
<body style="height: 100%">
<div style="background-color: black; height: 100%; padding: 25px"></div>
</body>
</html>
The challenge is then to get the black box to show up with a 25 pixel padding on all edges without the page growing big enough to require scrollbars.
I learned how to do these sort of things reading "PRO HTML and CSS Design Patterns". The display:block is the default display value for the div, but I like to make it explicit. The container has to be the right type; position attribute is fixed, relative, or absolute.
.stretchedToMargin {
display: block;
position:absolute;
height:auto;
bottom:0;
top:0;
left:0;
right:0;
margin-top:20px;
margin-bottom:20px;
margin-right:80px;
margin-left:80px;
background-color: green;
}
<div class="stretchedToMargin">
Hello, world
</div>
Fiddle by Nooshu's comment
There is a new property in CSS3 that you can use to change the way the box model calculates width/height, it's called box-sizing.
By setting this property with the value "border-box" it makes whichever element you apply it to not stretch when you add a padding or border. If you define something with 100px width, and 10px padding, it will still be 100px wide.
box-sizing: border-box;
See here for browser support. It does not work for IE7 and lower, however, I believe that Dean Edward's IE7.js adds support for it. Enjoy :)
The solution is to NOT use height and width at all! Attach the inner box using top, left, right, bottom and then add margin.
.box {margin:8px; position:absolute; top:0; left:0; right:0; bottom:0}
<div class="box" style="background:black">
<div class="box" style="background:green">
<div class="box" style="background:lightblue">
This will show three nested boxes. Try resizing browser to see they remain nested properly.
</div>
</div>
</div>
The better way is with the calc() property. So, your case would look like:
#myDiv {
width: calc(100% - 10px);
height: calc(100% - 10px);
padding: 5px;
}
Simple, clean, no workarounds. Just make sure you don't forget the space between the values and the operator (eg (100%-5px) that will break the syntax. Enjoy!
According the w3c spec height refers to the height of the viewable area e.g. on a 1280x1024 pixel resolution monitor 100% height = 1024 pixels.
min-height refers to the total height of the page including content so on a page where the content is bigger than 1024px min-height:100% will stretch to include all of the content.
The other problem then is that padding and border are added to the height and width in most modern browsers except ie6(ie6 is actually quite logical but does not conform to the spec). This is called the box model. So if you specify
min-height: 100%;
padding: 5px;
It will actually give you 100% + 5px + 5px for the height. To get around this you need a wrapper container.
<style>
.FullHeight {
height: auto !important; /* ie 6 will ignore this */
height: 100%; /* ie 6 will use this instead of min-height */
min-height: 100%; /* ie 6 will ignore this */
}
.Padded {
padding: 5px;
}
</style>
<div class="FullHeight">
<div class="Padded">
Hello i am padded.
</div
</div>
1. Full height with padding
body {
margin: 0;
}
.container {
min-height: 100vh;
padding: 50px;
box-sizing: border-box;
background: silver;
}
<div class="container">Hello world.</div>
2. Full height with margin
body {
margin: 0;
}
.container {
min-height: calc(100vh - 100px);
margin: 50px;
background: silver;
}
<div class="container">Hello world.</div>
3. Full height with border
body {
margin: 0;
}
.container {
min-height: 100vh;
border: 50px solid pink;
box-sizing: border-box;
background: silver;
}
<div class="container">Hello world.</div>
This is one of the outright idiocies of CSS - I have yet to understand the reasoning (if someone knows, pls. explain).
100% means 100% of the container height - to which any margins, borders and padding are added. So it is effectively impossible to get a container which fills it's parent and which has a margin, border, or padding.
Note also, setting height is notoriously inconsistent between browsers, too.
Another thing I've learned since I posted this is that the percentage is relative the container's length, that is, it's width, making a percentage even more worthless for height.
Nowadays, the vh and vw viewport units are more useful, but still not especially useful for anything other than the top-level containers.
Another solution is to use display:table which has a different box model behaviour.
You can set a height and width to the parent and add padding without expanding it. The child has 100% height and width minus the paddings.
JSBIN
Another option would be to use box-sizing propperty. Only problem with both would be they dont work in IE7.
Another solution: You can use percentage units for margins as well as sizes. For example:
.fullWidthPlusMargin {
width: 98%;
margin: 1%;
}
The main issue here is that the margins will increase/decrease slightly with the size of the parent element. Presumably the functionality you would prefer is for the margins to stay constant and the child element to grow/shrink to fill changes in spacing. So, depending on how tight you need your display to be, that could be problematic. (I'd also go for a smaller margin, like 0.3%).
A solution with flexbox (working on IE11): (or view on jsfiddle)
<html>
<style>
html, body {
height: 100%; /* fix for IE11, not needed for chrome/ff */
margin: 0; /* CSS-reset for chrome */
}
</style>
<body style="display: flex;">
<div style="background-color: black; flex: 1; margin: 25px;"></div>
</body>
</html>
(The CSS-reset is not necessarily important for the actual problem.)
The important part is flex: 1 (In combination with display: flex at the parent). Funnily enough, the most plausible explanation I know for how the Flex property works comes from a react-native documentation, so I refer to it anyway:
(...) flex: 1, which tells a component to fill all available space, shared evenly amongst other components with the same parent
To add -webkit and -moz would be more appropriate
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
Frank's example confused me a bit - it didn't work in my case because I didn't understand positioning well enough yet. It's important to note that the parent container element needs to have a non-static position (he mentioned this but I overlooked it, and it wasn't in his example).
Here's an example where the child - given padding and a border - uses absolute positioning to fill the parent 100%. The parent uses relative positioning in order to provide a point of reference for the child's position while remaining in the normal flow - the next element "more-content" is not affected:
#box {
position: relative;
height: 300px;
width: 600px;
}
#box p {
position: absolute;
border-style: dashed;
padding: 1em;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
<div id="box">
<p>100% height and width!</p>
</div>
<div id="more-content">
</div>
A useful link for quickly learning CSS positioning
This is the default behavior of display: block The fastest way that you can fix it in 2020 is to set display: 'flex' of parent element and padding e.g. 20px then all its children will have 100% height relative to its height.
Border around div, rather than page body margin
Another solution - I just wanted a simple border around the edge of my page, and I wanted 100% height when the content was smaller than that.
Border-box didn't work, and the fixed positioning seemed wrong for such a simple need.
I ended up adding a border to my container, instead of relying on the margin of the body of the page - it looks like this :
body, html {
height: 100%;
margin: 0;
}
.container {
width: 100%;
min-height: 100%;
border: 8px solid #564333;
}
<style type="text/css">
.stretchedToMargin {
position:absolute;
width:100%;
height:100%;
}
</style>

Resources