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

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.

Related

Whenever I use absolute positioning to vertically center, the entire nav disappears

ul {
margin: 0;
padding: 0;
overflow: hidden;
background-color: #333333;
position: relative;
li {
height: auto;
width: 20%;
position: absolute;
top: 50%;
transform: translateY(-50%);
a {
display: block;
color: white;
text-align: center;
padding: 16px;
text-decoration: none;
}
}
.float-left {
float: left;
font: 2em bold sans-serif;
}
}
Here is my html for context. I added another div just to test out vertical centering on a different element and it works fine. But I couldn't keep the li's on the nav from disappearing whenever I give them absolute positioning. Sorry it's in sass.
<ul>
<li class="float-left">Michael Thomas</li>
<li>About</li>
<li>Résumé</li>
<li>Portfolio</li>
<li>Contact</li>
</ul>
When the "li"s are inline/relative, they force the parent "ul" to take the dimensions of the child elements. But when you change the "li"s to position absolute, the "li"s no longer force the parent "ul" to take encompass the shape of its content, so the parent "ul" has a height and width of zero. If you removed the "overflow:hidden" on the parent I think you'd still see its contents. I think you need to give your nav/ul a height and width.

Do inline-block elements widths get set by their content?

Hi i just started trying to teach myself HTML/CSS a few days ago. I really dont like asking for answers id rather figure it out myself. But now i need some help so i can find peace and FINALLY move on. Im trying to make a horizontal menu with one drop down button and links in it.
.container {border:1px solid black;
text-align:left;
border-radius:10px;
overflow:hidden;}
.container a {padding:15px;
display:inline-block;
font-size:30px;
text-decoration:none;
background-color:grey;
color:white;}
.aboutcontainer {display:inline-block;}
.about {position:absolute;
display:none;
width:100%;}
.about a {display:block;
text-align:left;
font-size:20px;
padding:15px 5px;}
.aboutcontainer:hover .about {display:block;}
.container a:hover, .aboutcontainer:hover .button {background-color:red;}
.about a:hover {background-color:lightgrey;}
<div class="container">
<a href="#">Home</a
><a href="#">Media</a
><a href="#">Store</a
><div class="aboutcontainer">
<a class="button" href="#">About</a>
<div class="about">
About2
About3
</div>
</div>
</div>
I cant figure out how to make the dropdown menu automatically the same width as the drop down button. I figured that perhaps the drop down menu (.about) which has a width:100% would stretch as far as the div its contained in (.aboutcontainer) which is displayed as inline-block whose width would be determined by the "About" text-link inside of it. But the drop down menu, when displayed, goes the full length of the screen. So it seems to be the case that actual content inside an inline:block element will not define the width of that element. And although the border of an inline:block element wraps around its content automatically, its just an illusion and its actual width is really the full length of the screen, if no fixed widths have been defined in any of the parent divs (hope im using the right terminology). So is there a way to do this without any fixed widths assigned? If not then thats ok. Ill finally have my answer and know what im trying to do is impossible and stop wasting time on it.
Yes, an inline-block element will size to fit it's content.
Why isn't it working in your situation? You have .about positioned absolute.
When you position an element absolutely, you are taking it out of the HTML structure, meaning:
Do not leave space for the element. Instead, position it at a specified position relative to its closest positioned ancestor if any, or otherwise relative to the containing block. Absolutely positioned boxes can have margins, and they do not collapse with any other margins.
MDN Docs
This means the element is pulled out of the structure, and no longer influences the surrounding elements, or its parent.
An example of this:
.parent {
background: blue;
}
.child {
background: red;
position: absolute;
top: 20px;
}
Below is the parent element, with a blue background.
<div class="parent">
<div class="child">Bye bye parent</div>
</div>
If you run the snippet above, you don't see the parent or it's blue background at all, because the child element has been positioned out of it, and relative to the viewport.
Now back to your problem. How can we make the absolute positioned element be positioned relative to its parent, instead of the viewport?
The answer is extremely simple: position:relative; on the parent:
This keyword lays out all elements as though the element were not positioned, and then adjust the element's position, without changing layout (and thus leaving a gap for the element where it would have been had it not been positioned). The effect of position:relative on table-*-group, table-row, table-column, table-cell, and table-caption elements is undefined.
Relative positioning means that the absolute child elements will be positioned relative to the parent. While absolute will still pull the element out of the HTML structure, and it still won't influence the surrounding elements or its parent, the absolute element will now be influenced by its parent. So, in your case, setting width to 100% will be 100% of .aboutcontainers width, instead of 100% of the viewports width:
.container {
border: 1px solid black;
text-align: left;
border-radius: 10px;
}
.container a {
padding: 15px;
display: inline-block;
font-size: 30px;
text-decoration: none;
background-color: grey;
color: white;
}
.container>a:first-of-type {
border-radius: 10px 0 0 10px;
}
.aboutcontainer {
display: inline-block;
position: relative;
}
.about {
position: absolute;
display: none;
width: 100%;
}
.about a {
display: block;
text-align: left;
font-size: 20px;
padding: 15px 5px;
}
.aboutcontainer:hover .about {
display: block;
}
.container a:hover,
.aboutcontainer:hover .button {
background-color: red;
}
.about a:hover {
background-color: lightgrey;
}
<div class="container">
<a href="#">Home</a
><a href="#">Media</a
><a href="#">Store</a
><div class="aboutcontainer">
<a class="button" href="#">About</a>
<div class="about">
About2
About3
</div>
</div>
</div>
You'll notice in the snippet above, we had to remove overflow:hidden from .container. That is because now that the element is positioned absolutely within its parent element, it gets hidden when it overflows from .container. You had applied overflow:hidden so the end elements wouldn't stick out over the border-radius, so I simply added a border-radius to the first element.
Here, I removed overflow: hidden from .container and added position: relative to .aboutcontainer.
.container {
border: 1px solid black;
text-align: left;
border-radius: 10px;
}
.container a {
padding: 15px;
display: inline-block;
font-size: 30px;
text-decoration: none;
background-color: grey;
color: white;
}
.aboutcontainer {
display: inline-block;
position: relative;
}
.about {
position: absolute;
display: none;
width: 100%;
}
.about a {
display: block;
text-align: left;
font-size: 20px;
padding: 15px 5px;
}
.aboutcontainer:hover .about {
display: block;
}
.container a:hover,
.aboutcontainer:hover .button {
background-color: red;
}
.about a:hover {
background-color: lightgrey;
}
<div class="container">
<a href="#">Home</a
><a href="#">Media</a
><a href="#">Store</a
><div class="aboutcontainer">
<a class="button" href="#">About</a>
<div class="about">
About2
About3
</div>
</div>
</div>

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.

Make link in lower z-index level clickable

I would like to make an anchor that is in a lower z-index clickable, here's a fiddle:
http://jsfiddle.net/mjooh3gv/
Setting the z-index only for the anchor (that's different from the partent div) does not work.
.underlay a {
position: absolute;
z-index: 5000;
}
What's the point in layering the two DIVs on top of each other in the first place?
If you want to position elements at the outer edges of a container, you can use several methods:
postion: relative on the container and postition: absolute on the children, or
float: left and float: right on the children (with clearing the container), or
using display: inline-block and width: 50% on the children, or
a layout <table> with two columns (Yeah, I know. Sue me.), or
using display: table-row on the container and display: table-cell on the children, or
display: flex, see https://css-tricks.com/snippets/css/a-guide-to-flexbox/ and http://caniuse.com/#feat=flexbox
The latter would work like this:
.container {
border: 5px inset red;
width: 300px;
padding: 5px;
display: flex;
}
.overlay {
margin-right: auto;
}
.underlay {
margin-left: auto;
}
<div class="container">
<div class="overlay">
Link 1
</div>
<div class="underlay">
Link 2
</div>
</div>

Why is position: relative; not working on firefox?

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.