position: absolute not doing what I expect - html

I am having problems getting the grasp of position: absolute
I understand that it positions itself according to the position of its relative parent. So what is wrong with my example? when clicking on the first ".col-lg-6", why is the faded blue line not centered on the right col?
Please could you rework the code and explain why this is happening?
.formWrapper
{
background: blue;
height: 100vh;
position: relative;
margin: 0;
}
.formWrapper .contactForm
{
width: 750px;
height: 400px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: yellow;
}
<div class="formWrapper">
<div class="contactForm row">
<div class="col-lg-6"><h1>HI</h1></div>
<div class="col-lg-6"><h1>HI</h1></div>
</div>
</div>

I can't rework the code and give you what you want exactly, because I don't see the faded blue line you're talking about. But, I will explain what is going on with your code, as I see it.
HTML Markup
<div class="formWrapper">
<div class="contactForm row">
<div class="col-lg-6"><h1>HI</h1></div>
<div class="col-lg-6"><h1>HI</h1></div>
</div>
</div>
.formWrapper
{
background: blue;
height: 100vh;
position: relative;
margin: 0;
}
You have a .formWrapper div colored blue. It takes up the full screen, and you've positioned it relative. Positioning it relative provides an anchor for its child element to use when defining its own position as absolute (necessary).
.formWrapper .contactForm
{
width: 750px;
height: 400px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: yellow;
}
You've defined the a fixed width and height of the yellow .contactForm div and colored it yellow.
By defining position: absolute, with top:50% and left:50%, the top left position of the .contactForm div would appear in the very middle of the .formWrapper div. However, you've also added the transform: translate(-50%, -50%) style, which moves the .contactForm div to the left 50% of its own width and up 50% of its own height.
Important
The position: absolute style that you've set in the parent of the div.col-lg-6 elements does not affect the children's positioning within that element. Position absolute only directly affects the actual element to which you've applied this style, changing its position in reference to its own parent, or the closest parent that has a position style defined.
Position Fixed
If your goal is to have a pop up that sits in the center of the screen, then you might want to use position: fixed, which positions the element relative to the window. This way you don't have to worry about the effects of other elements.
You could position the popup in the middle of the view the same way you positioned the .contactForm div in the middle of the its parent div.
Bootstrap
If you are using bootstrap or any other css framework, you may want to consult their documentation on how to accomplish your goals. Frequently, when using a css framework, adding your own custom styles that affect the sizes and positioning of elements can have consequences that are difficult to manage.
By setting a position of absolute or fixed, you might break the expected flow of the rest of the css. So, only do it when there is no standard way of doing what you need and you know the consequences.

Related

Fixed element positioning relative to its parent

I have an element that gets position: fixed while dragging. This element is inside a modal that is a direct child of the body element.
On the image below, the modal is gray, the rest of the body is black, and the button is blue. When I add the following styles to the button:
position: fixed;
top: xxxpx;
left: -100px;
It positions the button relative to the modal, not the viewport. Is that even possible that an element with position: fixed be positioned relative to something but the viewport? It acts like an absolutely positioned element instead.
'normally' position fixed fixes relative to the viewport.
But there are exceptions. See MDN
The element is removed from the normal document flow, and no space is created for the element in the page layout. It is positioned relative to the initial containing block established by the viewport, except when one of its ancestors has a transform, perspective, or filter property set to something other than none (see the CSS Transforms Spec), in which case that ancestor behaves as the containing block. (Note that there are browser inconsistencies with perspective and filter contributing to containing block formation.) Its final position is determined by the values of top, right, bottom, and left.
Here's a simple example:
body {}
.parent {
position: relative;
margin: 100px;
transform: scale(1);
width: 50vw;
height: 10vw;
background: black;
rfilter: blur(1);
}
.child {
position: fixed;
top: 0px;
left: 0px;
width: 100px;
height: 100px;
background-color: blue;
}
<body>
<div class="parent">
<div class="child"></div>
</div>
</body>
Notice that the blue child element is placed at the top left of its parent. Its parent has a transform - and as it's scale(1) we might assume it doesn't do much. But it does create the parent as the containing block.
I think your problem is the transform on the parent.

Container transformed to fit, positioned absolute, still causing overflow as if not transformed

Edit: I had forgot to mention that I also had it positioned absolute. Absolutely sorry for that. Edits in content are in bold.
I have this container that I use for scaling its contents. I needed to scale things down evenly, and realized that I could use transform CSS attribute for my convenience.
The result is good, the contents are scaled and placed nicely. The problem is, I get overflow on the body element, caused by the container element. It is not crossing the window borders, not when its transformed, and is positioned absolute. However, for some reason, my browser (Edge 16) decides to accommodate space for the element as if it was not transformed.
.container {
position: absolute;
width: 10000px; height: 10000px;
border: solid 100px red;
transform-origin: top left;
transform: scale(0.01);
}
.orange-box {
width: 5000px; height: 2000px;
background-color: orange;
}
<div class='container'>
<div class='orange-box'>
</div>
I have tried it a couple of times on Chrome 64, I don't get overflows on body there. I do want to make use of this, though, and I want to have Edge support.
Is there a way to get around of this bug/issue? Is there, perhaps, a way to prevent specific elements from causing overflow, without completely hiding them? I don't want to overflow: none on the body, either, since the body might legitimately be overflowing.
I don't think it's a bug in Edge. At least, I see scrollbars in Chrome.
May be you can get around it placing the div far to the left and top (that don't stretch the body boundaries)
.container {
width: 10000px;
height: 10000px;
border: solid 100px red;
transform: scale(0.01);
top: -10095px;
position: absolute;
left: -10095px;
transform-origin: right bottom;
}
.orange-box {
width: 5000px; height: 2000px;
background-color: orange;
}
<div class='container'>
<div class='orange-box'>
</div>
I encapsulated it all inside another container, positioned it as relative, transformed it with translate(0). Transformation does nothing, but it is different than none, which is all I need to have a child positioned as fixed to respect its container's position: See MDN/position/fixed
Then, I have changed the positioning of our former container to fixed, which did what the absolute couldn't do on Edge 16, and removed the container from the document flow.
.container-container {
position: relative;
top: 50px;
transform: translate(0);
}
.container {
position: fixed;
width: 10000px; height: 10000px;
border: solid 100px red;
transform-origin: top left;
transform: scale(0.01);
}
.orange-box {
width: 5000px; height: 2000px;
background-color: orange;
}
<div class='container-container'>
<div class='container'>
<div class='orange-box'>
</div>
</div>
I positioned the container-container away from the top left, to show that the fixed child moves along with it, thanks to the translate(0) transform.
However, I didn't use this. I instead styled the container-container to have its overflow as hidden via CSS, and left everything as before. This works out only if the container-container has width and height set to be contained within the body, which was already the case in my application.

Absolute Centering Items Within A Div

I am trying to center items (vertically and horizontally) within a div. I have looked around here and other places and can't seem to get anything to work. What I am looking for is to have each item centered both vertically and horizontally in its respective div. Notice that there are two navigation tiles on the left and 4 on the right (1 div per tile). The divs also have parent divs which I used to build the sticky footer. The challenge is that it needs to be responsive so I cannot used fixed pixels.
.absolute-center {
position: relative;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
}
The above is what I tried to get the content centered. Its not working unfortunately.
Here's the fiddle: https://jsfiddle.net/jmc3t164/
Any help is greatly appreciated!
You have this structure (shortened for brevity)
<div class='top-half'>
<p class='absolute-center'>Time left to order</p>
</div>
<div class='bottom-half'>
<p class='absolute-center'>Add Produce</p>
</div>
Centering both vertically and horizontally is often acheieved by
.absolute-center {
position: absolute; /* note */
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
BUT this requires that the parent element (in which the child will be centered) has position:relative.
So, you need to add that
.top-half {
width: 100%;
height: 50%;
position: relative;
}
.bottom-half {
width: 100%;
height: 50%;
position:relative;
}
JSFiddle Demo
<div id="blahblah" style="width:90%;margin:auto 5%"> content </div><br> blahblah can be any id you want, or not necessary.<br> You definitely need a width of something, ideally less than 100%; and divide the remainder from 100 by 2 and set it as margin. ( margin: auto is for up and down margings, the 5%, or whatever is for left / right.
Another way is to have a class .center{text-align:center} and assign it to your Div.
Finally, yet another is to insert a div under your position relevant div and style it with 'text-align:center.

how to make a div stay in a div

I'm making a pong clone using HTML/CSS/Js. I've set a div element to act as a border for the game, just to keep things in a confined space. How do I get elements (for example, a scoreboard) to act relative to their parent element? For example, if I tell the child to move 50% left, it moves to the center of the parent-div, and NOT to the center of the web-page. Basically I want the child confined by the dimensions of their parent (haha). It seems like
child-div {
position:relative;
}
in CSS would do the trick, but it's not...maybe it's because I'm developing in CodeAcademy's IDE?
position:relative means relative to itself not parents/children etc. It seems likely that you want relative on the parent and possibly absolute on the children. Without code, it's hard to help much further
Here's a quick demo for you.
.container {
width: 80%;
height: 250px;
margin: 0 auto;
position: relative;
border: 4px solid green;
}
.scoreboard {
width: 200px;
height: 50px;
background: lightblue;
border: 2px solid grey;
position: absolute;
top: 10px;
/* just for a bit of space */
left: 50%;
/*almost centered*/
margin-left: -100px;
/* half of known width */
}
<div class="container">
<div class="scoreboard"></div>
</div>
Note...there are other centering methods for absolutely positioned divs depending on whether the width is known and browser support requirements
left: 50%; does not center an element...it moves the element's top/left corner to the center of the containing element. You have to move it back half of it's width (if known)...see above.
One final point....positioned elements are not constrained to their ancestor elements but rather positioned in relation to them. It's quite common to have positioned elements outside the bounds of parents.

How can I dynamically offset the position of a child element to 50% of it's own size?

Exactly as the title says, I have an element that dynamically resizes itself to fit the content. I would like this element to be positioned proportionally to its size (so it stays centered on a fixed point). The problem I'm facing is that the parent element I'm using to position the child element is not inheriting the calculated size of the child element. I don't know if there's any CSS tricks to make the parent element get it's child's height without having to specify it using javascript.
The following fiddle demonstrates the problem, with the issue being displayed on the left and the desired final product on the right (minus the ability to do it dynamically).
http://jsfiddle.net/YEcx6/
The html:
<div class="parent">
<div class="child">This content is dynamic</div>
</div>
<div id="static" class="parent">
<div class="child">This content is static</div>
</div>
and the CSS:
.child {
position: relative;
right: -50%;
top: -50%;
}
.parent {
position: absolute;
top: 50px;
left: 10px;
background: #ddd;
}
#static {
left: 100px;
height: 54px;
}
.child {
background: red;
max-width: 50px;
}
== EDIT ==
I now know there is no way to do any relational positioning with regard to height without using javascript.
What about height:auto and width:auto on the parent ?
The problem is in order to get the vertical positioning to work right, you need to have a defined height to reference by. Since you want a dynamic height, it makes it challenging. I tried using negative margin-top instead of top but that, as I suspected, defaults to using the width of the element to determine the height offset (which does not achieve your effect). I found a solution that might work for you if you can compromise by setting the position of the upper left corner of the .child rather than the upper left corner of the .parent. Here is the solution, with the explanation following (this was only tested in FF).
HTML
<div class="parent">
<div class="child">This content is dynamic
<div class="bkg"></div>
</div>
</div>
CSS
.parent {
position: absolute;
top: 50px;
left: 10px;
}
.child {
position: relative;
}
.bkg{
position: absolute;
width: 100%;
height: 100%;
top: 50%;
bottom: -50%
left: -50%;
right: 50%;
background-color: #ddd;
z-index: -1;
}
The .parent now is supposed to be the final position of the upper left of where .child will be. The .child contains the content you want but gives a relative position by which .bkg will be related. By giving .bkg a width and height of 100%, that set's its size, which apparent is enough to correctly then calculate the correct 50% offsets to reposition it down and to the left (which is the same relationship you wanted for your original look).