Why is position: relative; not working on firefox? - html

I am postioning a div inside a relative container absolutely, but in firefox it completly ignores it.
Here is a fidde for this: http://jsfiddle.net/TThUZ/
My HTML:
<div class="main">
<ul>
<li>
<a>
Text
</a>
<div class="sub">
Sub
</div>
</li>
</ul>
</div>
CSS:
ul { display: table; }
li { display: table-cell; width: 300px; background: #ddd; padding-left: 50px; position: relative; }
.sub { position: absolute; left: 0; }
The .sub does not follow the position: relative of the li. Why? And How to fix it?

.sub is doing what it is supposed to. I believe it has to to with your display: table-cell;. Check this link out for verification: http://css-tricks.com/absolutely-position-element-within-a-table-cell/
[...]Table cell elements just won't take those position values. And
thus, you also can't absolutely position elements within the context
of those elements either.[...]
The article above suggests the following fix, add and element inside the table-cell to use positioning. Not very semantic, but it works.
http://jsfiddle.net/TThUZ/6/
Notice the additional div that is using the relative positioning instead of your li that has display: table-cell;.
HTML
<div class="main">
<ul>
<li>
<div class="table-cell-fix">
<a>
Text
</a>
<div class="sub">
Sub
</div>
</div>
</li>
</ul>
</div>
Now just a little extra CSS. Move position: relative; from the li to the new div. I also moved the padding you had on your li to the new div.
CSS
ul {
display: table;
}
li {
display: table-cell;
width: 300px;
background: #ddd;
}
.sub {
position: absolute;
left: 0;
top: 0;
}
.table-cell-fix {
position: relative;
padding-left: 50px;
}

try setting LI's display to block instead of table-cell
li {
display: block;
}
I have updated your FIDDLE.

I think you're applying styles that contradict themselves in the box model, so you wind up with what amounts to unpredictable behavior. From what I can tell, you're triggering this by specifying display: table; on the <ul>:
The effect of 'position:relative' on table-row-group,
table-header-group, table-footer-group, table-row, table-column-group,
table-column, table-cell, and table-caption elements is undefined.
(http://www.w3.org/TR/CSS21/visuren.html#propdef-position)
There is a table that tries to define the recommended user-agent behavior, at http://www.w3.org/TR/CSS21/visuren.html#dis-pos-flo, but I couldn't quite work out which is applicable for your example.
If I removed the table rules from your CSS, the absolutely-position element does seem to position itself correctly in relation to the <li> that wraps it.
EDIT:
The simplest solution I came up with is to wrap the contents of each <li> with a <div>, to which you then apply a position: relative; rule (** denotes additions): http://jsfiddle.net/TThUZ/4/
<div class="main">
<ul>
<li>
**<div class="test">**
<a>
Text
</a>
<div class="sub">
Sub
</div>
**</div>**
</li>
</ul>
</div>
and
ul { display: table; }
li { display: table-cell; width: 300px; background: #ddd; padding-left: 50px; }
**.test { position: relative; }**
.sub { position: absolute; left: 0; }
I'm fairly certain you can remove the positioning rule from the <li>, as it has no effect when the elements are displayed as table cells.

Related

Position absolute element's width like it's container (in css)

So there is the following layout:
We are focusing at the 'SERVICEUSER' button and its submenu problem.
So is there a way to make the minimum width of the submenu (with position absolute) the same as its parent.
I have recreated the situation on this
jsfiddle link.
So basicly what is needed is to make the .collection min-width same as the width of the li.
The html structure of this situation is like this:
<ul>
<li>
SERVICEUSER
<div class="collection">
<div class="item">Item-1</div>
<div class="item">Item-2</div>
<div class="item">Item-3</div>
</div>
</li>
</ul>
The css of this situation is like this:
ul { list-style-type: none; }
li { display: inline; }
a { background: green; }
.collection {
position: absolute; // this is necessary for the situation
background: white;
}
An element positioned with "absolute" is contained in the flow of its closest relative parent. If you make li relative, you can set the width for collection.
li { display: inline; position: relative; }
.collection {
position: absolute;
background: white;
min-width: 100%;
white-space: nowrap;
}
Edit: I added white-space: nowrap to allow the collection (subitems) to be larger than the main item.

parent wrapper with absolute position, how to make width auto fit content inside,

http://jsfiddle.net/rs659rLh/5/
How to keep the .label tag width auto fit the content inside (make span next to input)
I think problem is the wrapper .dropdown-list set position absolute but I need that? I tried set the .dropdown-list position top bottom left right zero but still not work and these not work too...
according https://stackoverflow.com/a/7337237/1575921 seems the only way is set the position:absolute; wrapper specific width (auto or 100% both not work)
/* config */
ul {
list-style: none;
}
ul, li {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
word-wrap: break-word;
}
.relative {
position: relative;
}
.absolute {
position: absolute;
}
.clearfix >div, .clearfix >li, .clearfix >span, .clearfix >ul, .clearfix >input {
float: left;
}
.clearfix:after {
content: '';
display: block;
clear: both;
visibility: hidden;
height: 0;
}
input, span {
display: block;
}
/* end: config */
.dropdown-list {
background-color: yellow;
}
<ul class="clearfix">
<li>
<div class="clearfix">
<ul>
<li>top</li>
</ul>
<span>icon</span>
</div>
<div class="container relative">
<ul class="dropdown-list absolute">
<li>
<div class="label clearfix">
<input type="checkbox" value="{{name}}">
<span>{{name................}}</span>
</div>
</li>
</ul>
</div>
</li>
</ul>
I don't know if you see, but you have two labels and only one is with the class dropdown-list which has background-color property.
That's the problem. You must put a class with background on both classes if you wanna background for both.
Now, if you need one div with same size of other, you must set this width on css or use javascript to be dynamic.
If you wanna set background color on label tag directly, you must write directly on label, without span tag, otherwise, set on parent tag.
HTML:
<ul class="dropdown-list absolute">
<li>
<label class="clearfix label-blue">
<input type="checkbox" value="{{name}}">
label text
</label>
</li>
</ul>
CSS:
/* config */
ul {
list-style: none;
}
ul, li {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
word-wrap: break-word;
}
.relative {
position: relative;
}
.absolute {
position: absolute;
}
input, span {
display: block;
}
/* end: config */
.dropdown-list {
background-color: yellow;
}
.label-blue {
background-color: blue;
padding: 10px;
}
}
remove position:absolute from your <ul>. You do not assign any coordinates or dimension here. So why the absolute positioning ?
Then get rid of
input, span {
display: block;
}
If you want two elements to appear next to each other you cannot make them both block elements without floating them. Block elements always come with a "line break" at the end.
You can either:
Leave it out, so input and span will be inline elements
keep the block but float both elements to the left
mark them as inline-block if that serves your purpose
ADD:
Have a look at https://jsfiddle.net/rs659rLh/7/ is that what you try to achieve?
The problem you have where is that you insist to use an absolutely positioned list element. The issue is that parent elements do not strech to accomodate all the content within its absolutely positioned children. If a child element is bigger than its parent the cnten just floats over or gets cut off.
Therefor you have to define the dimensions of the parent element. which is quite inflexible. I did set:
.container{
width: 200px;
}
just to show how it works. All in all: your markup seem sto be way overcomplicated for the little you are trying to chieve here. Maybe you should rethink the whole process.

div height: 0; without any floating child elements?

Here's some HTML I have
<nav class="navlist">
<span class="left">
<li><a class="active" href="#">Home</a></li>
<li>Work</li>
<li>Services</li>
</span>
<span class="right">
<li>About</li>
<li>Blog</li>
<li>Contact</li>
</span>
</nav>
Relevant CSS:
.navlist {
position: fixed;
top: 0;
width: 100%;
list-style: none;
background-color: rgba(255,255,255,0.4);
}
.navlist span {
position: absolute;
margin: 10px 0;
}
.navlist .left {
right: 0px;
margin-right: 50%;
padding-right: 75px;
}
.navlist .left li {
margin-left: 75px;
}
.navlist .right {
left: 0px;
margin-left: 50%;
padding-left: 75px;
}
.navlist .right li {
margin-right: 75px;
}
.navlist li{
display: inline;
}
.navlist li a {
font-family: "Futura Thin", sans-serif;
font-size: 1.2em;
color: black;
text-decoration: none;
}
Why is the height of the <nav> element 0 instead of wrapping the height around the child elements? I've tried absolutely everything, adding overflow: auto; etc. and nothing works without simply defining the height manually, which is definitely not what I want. Any help?
<span> should be <ul> or <li> should be <span> or any inline-elements to make a valid code. best is to use <ul><li><a> for a list of links.
position:absolute;(or fixed) takes element out of the natural flow of the page, so <nav> have no content to make it grow.
this is caused by your
position:absolute
rule on the span elements.
Absolutely positioned elements don't fill the parent container, causing it to have a height of 0px.
Try making the same layout without using absolute positioning, and you should be fine.
Also, the <li> elements should be in a <ul> parent, not a <span>
You have taken <li> without <ul> or <ol> it is not a best practice.
absolute: The element is positioned relative to its first positioned (not static) ancestor element, So its container doesnt have specific value.
<ul>
<li><a class="active" href="#">Home</a></li>
<li>Work</li>
<li>Services</li>
</ul>
Need to wrap as above and need to give style to remove its default bullets.
Your child elements are positioned as absolute, thus also taking them out of the flow. Because of this, the .navlist element doesn't know how to expand.
Use floats to position your navigation lists and then user the overflow:hidden fix on the .navlist to have it expand to fit the child elements.
As others have said, positioning a child element as absolute will pull it out of the layout, its parent will then always have a height of 0 as it technically has no layout inside of it.
It completely depends on what your end result should look like so its hard to advise but a little reduced case of what you may want ( with a red background colour to make it obvious height is set on the nav is here:
http://jsbin.com/osobor/1/
.navlist {
position: fixed;
top: 0;
width: 100%;
list-style: none;
background: red;
}
.navlist ul {
float: left;
width:50%;
padding:0;
margin: 0;
list-style: none;
}
.navlist .right {
float:right;
}
.navlist li a {
font-family: "Futura Thin", sans-serif;
font-size: 1.2em;
color: black;
text-decoration: none;
}
Edit: Also your spans should be UL ( or OL ) elements if you're nesting LI's within them ( I've added this to the jsbin example )

Vertically center ul in div

This is what my code looks like.
#container {
width: 584px;
height: 50px;
position: relative;
overflow: hidden;
}
#container ul {
position: absolute;
margin: 0;
padding: 0;
width: 3504px;
}
#container ul li {
width: 584px;
float: left;
margin: 0;
padding: 0;
overflow: hidden;
}
<div id="container">
<ul>
<li>...</li>
<li>...</li>
<li>...</li>
</ul>
</div>
As the title says, I want to center the ul vertically inside the div. I cannot change the above CSS rules because. I've been googling solutions and trying to find a way, but everything seems to collide with the rules I already have.
Any idea how to do this?
Would it help if instead of the #container div I used a table with one row and column?
Please use the search function in the future. The full answer is explained here; this is the code for your scenario:
.container {
display: table;
height: 100%;
position: absolute;
overflow: hidden;
width: 100%;}
.helper {
#position: absolute; /*a variation of an "lte ie7" hack*/
#top: 50%;
display: table-cell;
vertical-align: middle;}
ul{
#position: relative;
#top: -50%;
margin:0 auto;
width:200px;}
The three elements have to be nested like so:
<div class="container">
<div class="helper">
<ul><!--stuff--></ul>
</div>
</div>
http://jsfiddle.net/ovfiddle/yVAW9/
"Centring" a div or other containers vertically is quite tricky in CSS, here are your options.
You know the height of your container
If you know the height of the container, you can do the following:
#container {
position: absolute;
top: 50%;
margin-top: -half_of_container_height_here;
}
So we essentially place in the middle and then offset it using a negative margin equal to the half of the height. You parent container needs to have position: relative.
You don't know the exact height of your container
In this case you need to use JavaScript and calculate the appropriate margins (unfortunately you cannot use margin-top: auto or something similar).
More info here.
You can use flex to make your ul center vertical, horizontal or both like
.container{
background:#f00;
height:150px;
display:flex;
align-items:center;
/*justify-content:center;=>will make ul center horizontal*/
}
.container ul{
background:#00f;
}
<div class="container">
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
</ul>
</div>
If you can add jQuery library you could try this,
$(document).ready(function(){
// Remove li float
$("#container ul li").css("float", "none");
// Get the full height of the UL
var ulheight = $("#container ul li")[0].scrollHeight;
// Based on the height of the container being 50px you can position the UL accordingly
var pushdown = (50-ulheight)/2;
$("#container ul li").css("top", pushdown);
});
Now you can make the parent container display:flex and align-items:center. That should work. Although flexbox properties are not supported by older browsers.

Is it possible for horizontally oriented tiles to stretch their parent's width in CSS?

If I have this layout in HTML:
<div>
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</div>
With this CSS:
div
{
width: 200px;
overflow: hidden;
}
ul
{
list-style: none;
height: 100px;
}
li
{
display: block;
width: 100px;
height: 100px;
float: left;
}
I want the <ul> to stretch to the size of its content (400px), rather than two of the <li> elements wrapping down onto the next line.
Is this possible with CSS? I've always just counted the <li> elements with JavaScript and set the <ul> width like that.
This should do it (see fiddle; of course, it hides some because of your overflow: hidden on the div, remove that and you see it is working):
ul
{
list-style: none;
height: 100px;
white-space: nowrap;
}
li
{
display: inline-block;
width: 100px;
height: 100px;
}
Though to actually get the ul to stretch in size (it doesn't with just the above code), it also needs to have display: inline-block (see fiddle) or a float applied (see fiddle) to get it to take on the size of its contents.
When you float the <li> like that, you effectively remove it from the <ul>. Are you sure that's what you want to do? Why not just float the whole list?