position relative-absolute child margin bug? - javascript

Can anyone explain how I can prevent the margin of a sibling div from affecting the other one? It does not logically make sense to me why the browser is laying it out this way.
I am trying to get the yellow box to have it's top/left relative to the parent, but the blue box with a margin-top is affecting the yellow one.
http://jsfiddle.net/oufdfoLy/
section{
position: relative;
}
div.options{
position: absolute;
left: 10px;
top: 10px;
display: inline-block;
background: #ff0;
padding: 50px;
}
div.content{
height: 100px;
width: 100%;
background: #09c;
margin-top: 50px;
}
<article>
<section>
<div class='options'>
</div>
<div class='content'>
<h1>hello world</h1>
</div>
</section>
</article>

This is known as collapsing margins.
8.3.1 Collapsing margins
In CSS, the adjoining margins of two or more boxes (which might or might not be siblings) can combine to form a single margin. Margins that combine this way are said to collapse, and the resulting combined margin is called a collapsed margin.
One solution would be to set the overflow property of the parent element to something other than the default value, visible.
Values such as auto or hidden would produce the expect results.
(See the link above for alternative approaches to work around this.)
Updated Example
section {
position: relative;
overflow: auto;
}
Changing the overflow property's value establishes a new block formatting context.
9.4.1 Block formatting contexts
Floats, absolutely positioned elements, block containers (such as inline-blocks, table-cells, and table-captions) that are not block boxes, and block boxes with 'overflow' other than 'visible' (except when that value has been propagated to the viewport) establish new block formatting contexts for their contents.
In a block formatting context, boxes are laid out one after the other, vertically, beginning at the top of a containing block. The vertical distance between two sibling boxes is determined by the 'margin' properties. Vertical margins between adjacent block-level boxes in a block formatting context collapse.

Related

Z-index not working nested absolutes divs

I've one question that why z-index not working in nested absolutes:
Here my code:
.relative {
width: 400px;
height: 400px;
margin: 50px auto;
position: relative;
background-color: #E7E7E7;
}
.absolute {
width: 200px;
height: 200px;
position: absolute;
top: 20px;
left: 20px;
background-color: #16E186;
z-index: 4;
}
.absoluteChild {
width: 75%;
height: 200px;
position: absolute;
top: 20px;
background-color: #1665e1;
z-index: 1;
}
.absoluteGrandchild {
width: 90%;
height: 80px;
position: absolute;
top: 20px;
background-color: #ff0056;
z-index: 1;
}
<div class="relative">
<div class="absolute">
Hello World
<div class="absoluteChild">
<div class="absoluteGrandchild">
</div>
</div>
</div>
</div>
Within a stacking context, child elements are stacked according to the
same rules previously explained. Importantly, the z-index values of
its child stacking contexts only have meaning in this parent. Stacking
contexts are treated atomically as a single unit in the parent
stacking context.
...
Each stacking context is self-contained: after the element's contents
are stacked, the whole element is considered in the stacking order of
the parent stacking context.
Source
It works as intentional. They are stacked in the correct order within their parent.
Without any z-index value, elements stack in the order that they appear in the DOM (the lowest one down at the same hierarchy level appears on top). Elements with non-static positioning will always appear on top of elements with default static positioning.
Also note that nesting plays a big role. If an element B sits on top of element A, a child element of element A can never be higher than element B.
z-index is a third-dimensional graphical indexing. Imagine a table where lots of papers are present. In this analogy the paper above the other paper has a higher z-index. However, you believe you experienced a different behavior, however, you are mistaken. Imagine a closed book on the table. It has a first page, a second page and so on. While you can index the pages of the book, you cannot put any of the pages of the book above or below the book unless you take it out of the book. In more technical terms, z-index indexes siblings, but will not index child-parents.
It's actually supposed to work that way.
Let me explain with boxes. Whenever you give a z-index value to an element, it becomes a box. Consequently, we have three boxes.
A big box: .absoulte
A medium box: .absoluteChild
A small box: .absoluteGrandchild
You can give an order of how your want the sibling boxes in to be stacked, but you can't say that you want a smaller, child box to be on top of a bigger, parent box.
To the packaging man, aka the browser, you are saying with your z-index values:
Get a big box and give it the number 4.
In the big box, get a medium box and give it a number 1.
In the medium box, get a small box and give it a number 1.
A box with a lower value will go under a box with a higher value of the same size.
Warning
You must not take a littler box and stack it on top or below that of a bigger box! What happens in the box stays in the box! Not doing so will cause an unstable stack of boxes that will give all developers a massive headache!
Lastly, you start the sizes of the box from the first time you set a z-index value.
no value
no value
no value
value (big box)
value (medium box)
value (small box)
value (medium box)
value (small box)
value (small box)
value (small box)
value (big box)
value (medium box)
value (small box)
value (medium box)
value (small box)
value (small box)
value (small box)

Set coordinates of element in DIV with js, css, html

im working on some graphic representation of journal issues. What I need is to display block of text using simple DIVs (or else) inside of other DIV, exactly the way they are organized on issue page. To do that I need to set coordinates of DIV element to exact number, but in relation to parent DIV. Is there any way to do that by using css or js??
If you outer div is set to position: relative, you can have the inside div as position: absolute and set its top, left, right and bottom properties to the pixels you need. For example.
.outer {
position: relative;
}
.inner {
position: absolute;
top: 10px; //your coordinate
left: 5px; //your coordinate
}
<div class="outer">
<div class="inner">Your content</div>
</div>
Otherwise, you can simply use padding on the inner element.
If you want the div to be display: block;, you can use simple margin-top and margin-left to set coordinates.
Lets say (for example) you need to set the coordinates of the div as <100,50>:
To do that, in CSS, set margin-left: 100px and margin-top: 50px

Separating two select boxes on same row equally in CSS

I have a container that is a certain width.
I have two select elements rendering on the same line in this main div container. The first one is absolute positioned 40px left from the main div container and the right one is absolute positioned 40px right from the main div container. Thus, resulting in a centered container within the main div container.
My goal is to push two select elements into the resulting container that sit on either side of either, having the same width, and having a space equidistant in the middle.
Here is my current HTML:
<div id="container">
<select class="edit" style="left: 40px; top: 290px; width: 136px;"></select>
<select class="edit" style="left: 190px; right:40px; top: 290px; width: 136px"></select>
</div>
So in this one we are assuming that the left has a combined pixel count of 40+136=176px, width plus left positioning and the right having a pixel count of 190+136+40=366, left positioning plus width plus right;
the result would be a container having two equidistant select boxes within the constraints of 40px each way.
I'm not sure if my math is correct but any assistance with this would be greatly appreciated.
Try removing the left:190px from the right hand element. The right:40px is enough to position the element to the right.
I'm not sure if this is exactly what you're looking for, so let me know if I've misunderstood something, but what about this solution (note that .edit could just as easily have a strictly %-based width, I just wanted to show how flexible this solution could be):
https://jsfiddle.net/Lcn51a1p/
HTML:
<div class="container">
<select class="edit"></select>
<select class="edit pull-right"></select>
</div>
CSS:
.container {
margin: 0 40px;
}
.edit {
width: 120px;
max-width: 50%;
}
.pull-right {
float:right;
}

Achieving Absolute positioning without Position attribute, using Margin/Padding

I am working on building Email Based HTML. Now as we know, Position attribute is not well supported in Email clients so i will have to go on without that. Now, looking at my options... i can go for either Margin or padding to position the elements.
The input elements can be relatively positioned or absolute. I'll just take the absolute part for now. So, my input will be for example
One Parent DIV (top:0, left:0)
A Child DIV (top:20, left:20)
Second Child DIV (top:20, left: 200)
Now, in a normal browser based HTML, these elements would easily be placed on their appropriate positions. But without the position: absolute or even top, left attributes. It get's tricky as the margin attribute arranges the elements relative to the other elements. Here is a sample run:
<div style="width: 600pt; height: 600pt; border:2px solid red; margin-left:20pt; margin-top: 30pt">
<div style="width: 100pt; height: 100pt; border:2px solid black; margin-left:20pt; margin-top: 30pt"></div>
<div style="width: 100pt; height: 100pt; border:2px solid black; margin-left:20pt; margin-top: 30pt"></div>
<div style="width: 100pt; height: 100pt; border:2px solid black; margin-left:20pt; margin-top: 30pt"></div>
</div>
Fiddle
My Expected outcome was, all the black divs overlapping each other, placed on the same position. That is possible if it calculates the margins according the the "Parent Element" but it is margining left from parent and top from the previous elements.
So My question now is, Is there a side way of using marging-left, top as top, left attributes and producing the same behavior as they would with position:absolute? Or simply, placing these three elements on top of each other using margin or padding attributes (No position, as it is not supported by Email clients)
I also know, using Divs for email isn't the best approach and i should consider using tables but trust me, the kind of HTML i am dealing with can only be generated using Divs and some playing around with margin or paddings. Any help will be appreciated.
You can use negative margins to achieve overlapping.
margin-top: -50pt
http://jsfiddle.net/pkdqh7kt/1/
Here is an example of stacking your divs horizontally:
http://jsfiddle.net/pkdqh7kt/2/
Also you can check this table to find out which CSS properties are currently supported by major email clients.

Simulating a "Card Layout" when using Flexbox

I'm having a rather complex problem here. I'd like to make a Layout in CSS featuring multiple Layers which means basically having multiple <div> elements stacked ontop of each other (or at least make it look like this) and only the top one is visible.
In many other GUI Environements this is known as a Card Layout.
So the plan was:
Create all <div class='layer'> elements in one parent <div class='container'> element
Make them have display: none initially
invoke $.show() or $.hide() to show or hide them
HTML:
<div id="containerOne">
<div class="layer a"></div>
<div class="layer b">
<div class="inner b1"></div>
</div>
<div class="layer c"></div>
</div>
CSS:
#containerOne {
width: 150px;
height: 150px;
background: red;
}
#containerOne .layer {
display : none;
width: 100%;
height: 100%
}
.a {
background: green;
}
.b {
background: orange;
}
.b1 {
width: 50%;
height: 50%;
background: yellow;
}
.c {
background: blue;
}
This works at first since the elements will not have any space reserved on the page initially and will only occupy space when shown.
Now if i have a nested element inside a Layer and i want it to have a size of 50% x 50% this also works well: Even if the layer div is set to display: none initially.
Now by default my Container div is set to display: block and all the size calculation seems to work fine and here's where my problem begins:
I need the Container div to have display: flex to take advantage of the Flexbox features of modern browsers. Instead of setting a fixed width for my Layers i now configure them to have flex: 1 so they grow to the full size of the container.
This also works as expected. With one exception: The nested Element that should have a size of 50% x 50% won't have a size at all. Debugging this in JavaScript shows that this is because at the moment the Layers are created they will all have a size of 0 x 0 and will first get their size assigned when they are shown by $.show().
What i would expect is that once they are shown, the nested element will grow to its 50% x 50% size but it doesn't.
Is there anything i can do about it? (good solutions and back-hack-workaround solutions).
I also made a Fiddle to demonstrate the problem and to play around with.
The thing you're expecting to happen should happen, but it doesn't (in Chrome) due to a bug. It actually works correctly in Firefox.
Here's a simplified version of your testcase with no dynamic changes:
http://jsfiddle.net/CN7e8/4/
This behavior was actually recently changed in the flexbox spec, to the behavior you're expecting. The issue is that your 50% height on b1 is resolving against an auto-height element (the flex item, b) and Chrome is treating that auto-height as an invalid percent basis, even though the auto-height can actually be resolved to the container's height. (It'll become the container's height due to the default align-items: stretch on the flex container, which makes auto-height flex items take on the container's height).
For reference, the spec change to clarify this is mentioned under ISSUE 3, part (a), in this post:
http://lists.w3.org/Archives/Public/www-style/2014Mar/0350.html
ANYWAY. To work around the Chrome bug, you can't have an auto-height on your flex item b, given that you're depending on it being a percent-basis. You have to give it an explicit height, e.g. height:100% (which more directly resolves against the container's height). Here's your fiddle, with that changed: http://jsfiddle.net/CN7e8/5/

Categories