Adapting container height to child's - css

I'm among the coutless people who are facing the same problem about adapting parent's height to the contained elements. I did some research and found similar questions, but no answer could help me, so i thought i should open a new one.
I already tried the suggestions given as answers here, and here, like adding "clearfix" as a class for the container div (in this case, the clearfix class is there in the Fiddle i created), adding a workaround-spacer, and so on. I don't have any floated element, thought, so maybe it's a different kind of problem.
The problem still remains, in both the nested divs i have in my code (#content_wrapper doesn't adapt to #div_1 and/or div_2, while #div_2 doesn't increase its height to the contained <ul>.
I really hope to find a solution (maybe it's just something wrong in my code i can't de-bug).
Thanks for your attention.

Generally speaking, you want to avoid using absolute positioning for layout purposes.
What you're looking for is equal height columns. The whole point of equal height columns is that you don't need to know the height of any of the columns involved, they'll all be the same height and expand gracefully no matter what their contents are. The simplest way to achieve this is by using the table* display properties.
http://jsfiddle.net/UfWJh/3/
body {
font-size:10px;
}
/* wrappers */
#header_wrapper {
width:95%;
height:40px;
margin:auto;
margin-top:5px;
padding:2px;
border:1px solid red;
}
#content_wrapper {
display: table;
width:95%;
margin:auto;
margin-top:5px;
padding:2px;
border:1px solid red;
}
/* div1 */
#div_1 {
display: table-cell;
width:70%;
border:1px solid purple;
}
/* div 2 */
#div_2 {
display: table-cell;
width:25%;
border:1px solid purple;
}
#div_2 ul {
list-style-type:none;
}
#div_2 li {
width:100px;
height:30px;
margin:2px;
padding:1px;
border:1px solid darkgrey;
}

If you want a parent element to adapt to it's children you cannot explicitly define the value of the axes (width or height) that you want to adapt. Use width:auto or height:auto then use min-width,min-height,max-width & max-height to set minimum and maximum values for the adapting axis.
You then set values for the children, which can either be explicit values or again min and max thresholds.
From your rather messy code, it was easy to see, you have done much of it right, but you must not understand the position options. Try to gain a better understanding of relative,absolute & fixed positioning.
I've fixed it by changing the absolute positioning to relative and fixing a missing css selector for the styles you were trying to use on the <li>'s:
/* div1 */
#div_1 {
position:relative;
width:70%;
top:5px;
left:5px;
border:1px solid purple;
}
/* div 2 */
#div_2 {
position:relative;
width:25%;
top:5px;
right:5px;
border:1px solid purple;
}
#div_2 ul {
position:relative;
top:0px;
left:0px;
list-style-type:none;
}
#div_2 ul li {
width:100px;
height:30px;
margin:2px;
padding:1px;
border:1px solid darkgrey;
}
I suspect you probably don't need all those fixes you tried. Also, I find code so much more readable in this format.

Here's is my answer:
Remove position absolute (it's not a good idea to implement your layout like this...not cross-browser friendly...)
Make its content display: table
and then display: table-cell on the 2 divs to have even height...
Here is the example:
http://jsfiddle.net/Riskbreaker/UfWJh/4/
If you do not want it this way or care about equal height then use overflow:hidden on the content wrapper and float: left the 2 divs...
Here is the example:
http://jsfiddle.net/Riskbreaker/UfWJh/7/

Related

Position: sticky behavior on a child element whilst the parent is not sticky?

I'm trying to achieve something that I'm not sure is supposed to be possible at all. Note that I'm looking for a CSS-only solution, I know I can solve this with JS, but I don't want to.
Consider the following pen:
https://codepen.io/fchristant/pen/PjoKOq
The second navigation bar (dark) is sticky, as you scroll down, it will stick to the top of the viewport. The first navigation bar (light) is not sticky, it will simply scroll away.
However, that light navigation bar has a child element that is sticky. The idea is that the parent will scroll away, yet the child sticks, effectively blending with the second navigation bar (which is sticky).
This does not work, however. Hence my question: is it possible at all to have a sticky child element inside a parent that is not sticky?
HTML:
<div class="site_header">
Site header
<div class="site_header_child">
sticky
</div>
</div>
<div class="site_nav">
Site header
</div>
CSS:
.site_header {
display:flex;
position:relative;
width:100%;
padding:10px;
background:#eee;
}
.site_header_child {
border:1px solid red;
margin-left:auto;
position:sticky;
z-index:2;
top:0;
right:20px;
}
.site_nav {
display: block;
position:sticky;
padding:10px;
background:#333;
color:#fff;
position:sticky;
z-index:1;
top:0;
}
It is not possible to use sticky in such case. The same effect can be achieved by other means though. You can simply use "fixed" positioning and the sticky child will stay were it was.
.site_header_child {
position:fixed;
top:10px;
background:#eee;
}
Demo: https://codepen.io/anon/pen/VMWovv
You can try adding display: contents; to the parent to make it act as the parent.
The .site_header_child will only stick for the duration of its parent element's height.
You will need to give the .site_header_child element a fixed position if you want it to appear in the second bar.
try it:
-> instead of top: 0 => top: 10px
.site_header_child {
border:1px solid red;
margin-left:auto;
position:sticky;
top:10;
z-index:2;
right:20px;
}
.site_nav {
display: block;
position:sticky;
top:10;
padding:10px;
background:#333;
color:#fff;
position:sticky;
z-index:1;
}

Two auto-width divs side by side

How can I position two divs with auto width side by side? The left div should take priority. Below is my attempt:
<div id='div_1'></div>
<div id='div_2'></div>
#div_1
{
display:inline-block;
float:left;
position:relative;
width:auto;
}
#div_2
{
display:inline-block;
float:right;
position:relative;
width:auto;
}
EDIT: Adding the goal for clarity -
'The goal is to make the first div be able to autosize itself. The second div should occupy the rest of the space.'
I believe you're looking for something like flexbox, which is not supported real well yet, I don't think.
An alternative is to configure the two as display: table-cell with a wrapping element using display: table and a width: 100%. See this question for a similar case:
https://stackoverflow.com/a/12650502/451969
What it would give you is something along the lines of:
<div id='wrapper'>
<div id='div_1'></div>
<div id='div_2'></div>
</div>
#wrapper
{
display: table;
width: 100%;
}
#div_1
{
display: table-cell;
}
#div_2
{
display: table-cell;
}
http://jsfiddle.net/mDyjE/
Fluid layouts rely on % width value. This is what you should use. For exemple: 50% for both of them.
Moreover, position: relative seems to be unnecessary here.
I assume the goal is to get them to be the same size, side by side. To do this, set width to be about 45% rather than auto. You use 45% because if you use 50% IE will drop the right div below the left.
#div_1
{
display:inline-block;
float:left;
position:relative;
width:45%;
}
#div_2
{
display:inline-block;
float:right;
position:relative;
width:45%;
}

Make Child Div Float Right of Parent

I'd like to make an inner div float right of the parent, regardless of the width of the parent. An example of what this looks like is here: http://jsfiddle.net/eqDyy/. That fiddle is just an example of what it should look like. It's done with the exact number of pixels given, but what I'm looking for is a solution that still lets that inner div appear to the right of its parent, even when the parent width changes.
The following is the code used in the fiddle:
HTML
<div id="one">
<div id="two"></div>
</div>
CSS
#one {
border:2px solid #ddd;
width:150px;
height:30px;
}
#two {
border:2px solid #ddd;
width:150px;
height:30px;
margin-left:150px;
margin-top:-2px;
}
Again, please remember that this is just to show what I'd like it to look like, but it isn't a satisfying implementation because it uses specific pixel amounts.
Since percentage-based margins are calculated against the containing block's width, you can set margin-left to 100%.
Example
#one {
border:2px solid #ddd;
width:150px;
height:30px;
}
#two {
border:2px solid #ddd;
width:50px;
height:30px;
margin-left:150px;
margin-top:-2px;
float:right;
}
I changed #two a little to show you the result.
http://jsfiddle.net/eqDyy/3/

CSS table-cell in Opera with :before and :after do not behave as normal

I want to achieve the following effect in CSS:
I use CSS table-cell with :before and :after pseudo-elements so that they auto-adjust their width in one row. In other words, I want the text container have the width of the text (with some padding) and the pseudo-elements fill the rest of the area. This means that I can't use 1px background-image positioned top, because each word has a different width.
Here's the fiddle.
HTML
<div id="container">
<div id="box">
<h2 id="header">UPDATES</h2>
</div>
</div>
CSS
#container {
background:url("http://lorempixel.com/output/abstract-q-g-640-480-9.jpg") center center no-repeat;
padding-top:50px;
height:400px;
width:50%;
margin:0 auto;
}
#box {
margin:0 auto;
width:50%;
display:table;
}
#header {
color:#fff;
font:14px Arial;
font-weight:500;
line-height:10px;
height:10px;
display:table-cell;
padding:0 10px;
width:auto;
text-align:center;
}
#box:after, #box:before {
content:"";
display:table-cell;
border:1px solid #fff;
border-bottom:0;
height:10px;
width:50%;
}
#box:after{
border-left:0;
}
#box:before{
border-right:0;
}
However, it doesn't work in Opera so, I need to find a different technique to achieve the same effect. I'd prefer to avoid using HTML tables and any js. Can you provide any suggestion?
In this example I got rid of the psuedo-elements and sandwiched the header tag between two that were styled as a table to get the line effect. Although this is done using a CSS table the similar concept should be applicable to an html table.
<div id="before" ></div>
<h2 id="header">UPDATES</h2>
<div id="after"></div>
styled like so....
#before {
content:"";
display:table-cell;
border:1px solid #fff;
border-bottom:0;
border-right:0;
height:10px;
width:50%;
}
#after {
content:"";
display:table-cell;
border:1px solid #fff;
border-bottom:0;
border-left:0;
height:10px;
width:50%;
}
http://jsfiddle.net/SteveRobertson/9SBXn/12/
After several tests, I found out that Opera needs a more detailed implementation when using CSS tables with pseudo-elements. In other words, it's not enough to set the parent container as display:table and children as display:table-cell.
You need to set the whole hierarchy, meaning that:
The parent needs to be set as:
display:table
The first children needs to be set as:
display:table-row
And finally set the other children as:
display:table-cell
If you set your CSS ignoring display:table-row like I did, Opera sets the children elements (after display:table-cell) as table-row and not as table-cell, thus the width of each child extends to 100% of the parent and behaves like a row. Setting the table hierarchy like in HTML tables (table > row > cell) you get the expected format.
This seems to affect only Opera, since all other browsers do not try to fix the hierarchy of the CSS table.
Here's the demo (check in Opera as well)
Instead of CSS tables, you could use inline-blocks with percentage width and max-width so that the containers don't fall in a new line.

Cannot move an element to be closer to a floated element

Why can't the #navbar be shifted further upwards ? I tried margin-top but it didn't work. Only an extremely large value had some effect, but the positioning is too skewed.
The #container contains all 3 elements.
#container {
position:relative;
margin: 0 auto;
width:790px;
}
#chicklogo {
float:left;
border:1px solid black;
}
#rightext {
float:left;
border:1px solid black;
}
#navbar {
clear:both;
border:1px solid blue;
}
It can't because #navbar has clear:both and is going to fall under the tallest of the floated elements. From your image, you can see that #rightext is taller and #navbar sits flush under it.
If you gave the logo and right text the same height then your nav would sit just under both.
I have created a JS Fiddle to demonstrate a negative margin-top which would mean the navbar would overlap the preceding element, even though it is set to clear: both.
Ideally, you would reduce the height of the #righttext element as it looks like the white-space in that element is causing your layout issue, but the negative margin-top can also work if that isn't possible.

Resources