I have a container div that has two inner divs. The inner divs toggle display:block/none on a hover over the outer container, so only one inner is visible at any given time.
The outer container has a min-height, but can expand depending on the inner contents. If both inner contents are shorter than the min-height, everything works well. However, if one of the inner containers is taller than the min-height, I get a jump in the height of the outer container on hover.
What I want is:
The outer container keeps its min-height if both inner containers are shorter.
The outer container has the height of the taller of the two inner containers IF either one is taller than the min-height
There is no expanding/collapsing happening on hover at any time.
Sample HTML:
<div class="outer">
<div class="inner inner1">Inner 1 Green</div>
<div class="inner inner2">Inner 2 Blue</div>
</div>
<div class="after">Some text afterwards</div>
Sample CSS:
.outer {
position:relative;
width: 300px;
min-height: 150px;
background: red;
padding: 10px
}
.inner {
width: 200px;
}
.inner1 {
background: green;
height: 200px
}
.inner2 {
background: blue;
height: 100px;
display: none;
}
.outer:hover .inner1 {
display: none;
}
.outer:hover .inner2 {
display: block;
}
Sample Fiddle: http://jsfiddle.net/ZhS6c/
Important: I am looking for a pure CSS solution. I could easily fix this with jQuery or basic JS, but this is not an option.
Don't hide the elements by setting display to none, instead set their margin-left to a large negative number which places them far away the left side of the screen. This way, if you float the two .inner and add a clearfix (or better, set display: hiddden on .outer), the container will always be tall as the tallest child element.
In code:
.inner {
width: 200px;
float: left;
}
.inner1 {
background: green;
height: 200px
}
.inner2 {
background: blue;
height: 100px;
margin-left: -1000px;
}
.outer:hover .inner1 {
margin-left: -1000px;
}
.outer:hover .inner2 {
margin-left: 0;
}
Then, on the container you have two solutions: the clearfix (http://jsfiddle.net/ZhS6c/3/)
.outer:after{
content: "";
display: block;
clear: left;
}
and the block formatting context forcing (http://jsfiddle.net/ZhS6c/2/)
.outer{
visible: hidden;
}
Method two
There are also different methods, for example you can hide the unwanted element by shrinking its width to zero. When doing this (with all the floating thing, of course) also set overflow to hidden, otherwise the content will still be visible. Live example: http://jsfiddle.net/ZhS6c/4/.
Without floating
If you don't like the float in there you could try a inline-block approach, and set the widths as before. Live example: http://jsfiddle.net/ZhS6c/5/. This solution needs also a little edit of the HTML code, since if you place a whitespace between the two .inner it will be actually rendered (try to remove the comment in the example to see what happens).
Try this.Uses combination of display and visibility :
Case 1: .inner1 is always greater than .inner2
.inner1 {
display:inline-block;
background: green;
height: 200px
}
.inner2 {
background: blue;
height: 100px;
display: none;
}
.outer:hover .inner1 {
visibility:hidden; /*sets visiblity instead of display to maintain height;*/
width:1px; /*reduces width to 1px for adjustment."width:0px" will not work. */
}
.outer:hover .inner2 {
/* Below two lines for .inner2 div to be on same line*/
display: inline-block;
float:left;
}
See this Demo Fiddle with .inner1 height = 200px
Even if you increase the height of .inner1 the container will adjust the height accordingly:
See this Demo Fiddle with .inner1 height = 300px
OR
Case 2: .inner2 can be greater than .inner1
See this Demo Fiddle .inner2 > .inner1
Change done for above fiddle:
.inner2 {
position:relative;
right:4px;
background: blue;
height: 400px;
display: none;
}
.outer:hover .inner2 {
/* Below two lines for .inner2 div to be on same line*/
display: inline-block;
vertical-align:top;
}
Fiddle in response to comment: Container gets taller div height in the beginning itself
If the margin trick doesn't work, another option is using display: table, then collapse the one not to be shown with a combination of width: 0 and visibility: hidden. The two items will form cells in a row which has the height of the taller one, while the zero width prevents it from otherwise impacting the page layout.
Maybe playing with opacity can help
Here's a fiddle
all i'v done is
.outer:hover .inner1 {
opacity:0;
}
.outer:hover .inner2 {
display: block;
position:absolute;
top:10px;
}
I put the inner2 in absolute so it goes on top, and so give it a margin top of 10px (cause of the padding of the parent container)
.outer:hover .inner1 {
visibility: hidden;
}
Try using visibility.
Remove the min height from the outer and let the hight be determined by the what ever is the highest inner div
.outer {
position:relative;
width: 300px;
min-height: 150px; !!!! remove this
background: red;
padding: 10px
}
Related
JsFiddle: http://jsfiddle.net/techsin/csfvb91u/
(just realized normal div is collapsing ALSO to size of content, is min height completely useless?)
I need two divs, one left, and on right. Left one is 100px wide and stays that way. While, right div expands infinitely and doesn't shrink beyond 400px. Both Divs should be the height of parent. And parent has no exact height but minimum height of 800. So if content of one of these 2 divs were to push the height of div and extend it. Then The height of parent should increase and thus also the height of other div.
I tried using floats. I managed to some extent. However left side which was on float left, its height kept collapsing and didn't follow height:100% rule. It only worked if parent had definite width.
I tried using inline block but then right div won't expand to fillin the available space..
Why in the world css doesn't have fit-content, fill-available, choose what % refers to, choose what to position against, use vector or use pngs to shape div, inset textshadow, etc.
<div class="cont">
<div class="a"></div>
<div class="b"></div>
</div>
try with display:table and display:table-cell for child you will need to give fixed with for the left div
demo - http://jsfiddle.net/z90fma6e/
html,
body {
height: 100%;
}
* {
margin: 0;
padding: 0;
}
.cont {
display: table;
height: 100%;
}
.left,
.right {
height: 100%;
}
.left {
width: 200px;
background: red;
display: block;
}
.right {
width: 100%;
display: table-cell;
background: green;
}
<div class="cont">
<div class="left">fixed
<br/>height adjusts</div>
<div class="right">expands
<br/>height adjusts</div>
</div>
Sounds like your divs are collapsing. Your going to need a clearfix you can add to divs. There are a few ways to do this; however, this option is best.
.clearfix:after {
content: ".";
visibility: hidden;
display: block;
height: 0;
clear: both;
}
Add this clearfix class and css to your divs so they wont collapse.
You can read more about them at cssTricks
perfect use case for CSS flex layout:
<style>
body {
display: flex;
flex-direction: row;
margin: 0;
padding: 0;
}
div:first-child {
width: 200px;
background: red;
}
div:last-child {
flex: 1;
background: blue;
}
</style>
<div></div>
<div></div>
If you wish to support IE8 or earlier I would suggest you to use positioning:
Here's what I came up with
Fiddle : http://jsfiddle.net/csfvb91u/4/
If the content on the right is going out of the container, you can always use margin-right:200px as the right side container is shifted 200px using left:200px. Hope you get what I'm saying... :)
HTML:
<div class="cont">
<div class="a"></div>
<div class="b"></div>
</div>
CSS:
.a {
position:absolute;
width: 200px;
background-color: green;
height: 100%;
}
.b {
width:100%;
position:absolute;
left:200px;
background-color: blue;
height: 100%;
}
.cont {
position:relative;
border:1px solid #333;
min-height:300px;
overflow:hidden;
}
I have two inline-block elements (first image). The first one has fixed width. The second one doesn't have fixed width because the container may grow horizontally so it should fill it.
When second element text is large (second image) then it wraps down.
But what I want is the element to grow vertically (third image).
I need also text to preserve line breaks.
You can apply max-width: calc( 100% - LABEL_WIDTH ) to your .element class. Replace LABEL_WIDTH with the width of the label. This way you can define a width in em for the label instead of using two percentual values.
See this JSFiddle for a working example: http://jsfiddle.net/QL78X/2/
See this link for a table of browsers supporting calc(): http://caniuse.com/calc
li {
display: inline-block;
vertical-align: top;
list-style-type: none;
}
.label {
width: 7em;
}
.element {
width: calc( 100% - 7em );
white-space: pre-line;
}
Here's a fiddle: http://jsfiddle.net/Pv8yH/1/
Basically, I've set a width on the label, then set a max-width on the element. I've set the white-space to 'nowrap' so that the second LI doesn't wrap down. Then I have to make sure that white-space is reset back to 'normal' within the LI itself. The max-width is just for show, really, the magic is the white-space property (at least in terms of your question).
ul { white-space: nowrap; }
ul li {
display: inline-block;
white-space: normal;
}
li.label { width: 30%; vertical-align: top; background: red; }
li.element { max-width: 70%; background: green; }
NB. If you are setting a width in ems for the first element, it may be tricky to get it to all fit. It will flow like you want, but you will definitely have to tweak it to make it look nice.
You can use
float:left;
Check this example here:
http://jsfiddle.net/3M5MF/
I suggest you use max-width on the right element. I did an example here: http://codepen.io/mattdrose/pen/qCLzG?editors=110
.field__item {
display: inline-block;
vertical-align: text-top;
}
.field__item--1 {
width: 30%;
}
.field__item--2 {
max-width: 70%;
}
I use percentages, but you can replace these with your preferred method.
However, I think you should use floats so you don't have to deal with the html white space when calculating your widths.
I used relative position of container with fixed height http://jsfiddle.net/6qMvy/
.container{
width: 400px;
height: 600px;
position: relative;
}
.left{
width: 100px;
position: absolute;
}
.right{
position: absolute;
left: 120px;
}
Does anyone know why in this example
the inner <div> displayed vertically instead of horizontally?
I use chrome element inspect can see a huge margin area on the right of each <div>, but without any margin value.
Found this example
could be the answer to this question, too. Just in case anyone needs it.
It happens so because you are using block layout for each inner div (display:block as default for div elements). Instead you should use (for example ) display:inline-block and reduce width (to 33% in my example) as it adds some extra pixels as spacing between three inner divs :
.cols_section > div{
display:inline-block;
}
Example
Another option is to use table layout, so you don't have to change width for each inner div:
.cols_section {
display:table;
width:100%;
}
.cols_section > div{
display:table-cell;
}
Example
Set width for each class to auto. That should solve your problem..
Example:
.cols_section {
max-width: 1045px;
height: 100px;
}
.col1 {
background: green;
width: auto;
height: 100px;
}
.col2 {
background: yellow;
width: auto;
height: 100px;
}
.col3 {
background: blue;
width: auto;
height: 100px;
}
I have a layout involving a div.left on the left with a set width of 40px, and a div.right on the right with a width of 100% to fill the remaining parent-container space.
HTML:
<div class="parent">
<div class="left">
L
</div>
<div class="right">
R
</div>
</div>
CSS:
.parent {
background: maroon;
max-width: 500px;
}
.left {
float: left;
background: green;
width: 40px;
opacity: 0.7;
}
.right {
width: 100%;
padding-left: 50px;
background: blue;
}
Jsfiddle
Is it possible to achieve this layout (one element with fixed width next to another that fills the remaining space) without resorting to the padding method I'm currently using? My problem is that I'd like to use a transparent background on the left-floated element, so the padding hidden beneath those elements would be visible. Also, my current approach doesn't downsize fluidly.
For that you need to float: left; the other element as well..
.right {
width: calc(100% - 40px);
background: blue;
float: left;
}
Demo
Also, am using calc() here, to deduct the fixed width sidebar which is 40px from 100% right bar.
As #Krimson commented that you want some space between the element as well, than use margin
.right {
width: calc(100% - 80px);
background: blue;
float: left;
margin-left: 40px;
}
Demo
Note: In the demo, am using overflow: hidden; as a quick fix for clearing floats, but better use clear: both; for that, for more information on clearing floats, you can read my answer here.
Inspected Elements
What if u change your .right to this:
.right {
/* width: 100%; remove width */
margin-left: 50px; /* Margin instead of Padding */
background: blue;
}
JSFiddle Demo
I have to divs layouted as display: inline-block. Intentionally, I want these two divs (tileImage, title) to share the 300px width of the parent div (preview). Thus, I have set their width to 50%. For some reason the second div is moved to the next line.
Changing the width of div "title" to 48% will move the div next to the div "titleImage". There you notice the space in between. Where does this space come from? How do I get rid of it?
Here is the JFiddle: http://jsfiddle.net/SFDPe/2/
Thanks!
You should float your elements to the left and right, instead. Then, make sure you set height: auto; and overflow: auto; to the parent container. This ensures that the .parent container actually overflows and grows automatically when elements are floated inside of it.
JSfiddle here.
.preview {
width: 300px;
border: 1px solid red;
vertical-align: top;
height: auto;
overflow: auto;
}
.title {
width: 50%;
background-color: olive;
float: right;
}
.tileImage {
width: 50%;
background-color: orange;
float: left;
}
Instead of using display:inline-block use, float:left for both divs.
http://jsfiddle.net/SFDPe/3/
Take a look onto this article:
Fighting the Space Between Inline Block Elements
Maybe you can use float: left; instead? Like this:
.preview, .preview div {
float: left;
}