margin-top: 50% works strange - html

I would like to center a div both horizontally, and vertically. I tried to manage it like this:
div {
background: red;
width: 200px;
height: 200px;
position: absolute;
margin-top: 50%;
margin-left: 50%;
top: -100px;
left: -100px;
}
The margin-top xx% depends on the width of the page for some reason, not the height.
jsFiddle: http://jsfiddle.net/MxE8Y/embedded/result/
What do I wrong? How to fix it without using javascript?

the reason of vertical % related to parent's width:
The percentage is calculated with respect to the width of the generated box's containing block. Note that this is true for 'margin-top' and 'margin-bottom' as well. If the containing block's width depends on this element, then the resulting layout is undefined in CSS 2.1.
http://www.w3.org/TR/CSS2/box.html#margin-properties
the answer of Hashem Qolami tells you what to do instead :)
Else, you can keep everything in the flow using display: (display:table) http://jsfiddle.net/MxE8Y/2/
body, html {
background: green;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
display:table;
}
body {
display:table-cell;
vertical-align:middle;
}
div {
background: red;
width: 200px;
height: 200px;
margin:auto;
}
or http://codepen.io/anon/pen/iJgbv/ (display:flex) :
html,body {
height:100%;
width:100%;
margin:0;
}
body {
display:flex;
}
div {
width:100px;
height:100px;
background:gray;
margin:auto;
}

A percentage value for top/bottom padding/margin is relative to the width of box's containing block.
8.3 Margin properties: 'margin-top', 'margin-right', 'margin-bottom', 'margin-left', and 'margin'
<percentage> The percentage is calculated with respect to the width
of the generated box's containing block. Note that this is true for
'margin-top' and 'margin-bottom' as well. If the containing block's
width depends on this element, then the resulting layout is undefined
in CSS 2.1.
Try using top and left properties for positioning the absolutely positioned element and use negative values on top/left margin:
EXAMPLE HERE
div {
background: red;
width: 200px;
height: 200px;
position: absolute;
top: 50%;
left: 50%;
margin-top: -100px;
margin-left: -100px;
}

A 2016 option using the translate -50% method
css
div {
position: absolute;
top: 50%; left: 50%;
transform: translate(-50%, -50%);
}
fiddle
http://jsfiddle.net/Hastig/MxE8Y/6/

Related

absolute div inside absolute div cuts off with respect to relative position

I have 3 divs on top of each other having following css.
.d1 {
position: relative;
background-color: yellow;
height: 50px;
width: 100px;
overflow: hidden;
}
.d2 {
position: absolute;
background-color: green;
height: 25px;
width: 50px;
}
.d3 {
position: absolute;
left: 83px;
}
and the divs that have classes are as follows:
<div class="d1">
<div class="d2">
<div class="d3">text</div>
</div>
</div>
and as a result I see content of d3 cut off because of overflow:hidden in d1.
How can I avoid cut off content of d3 without modifying d1?
Getting around the overflow..
An element can overflow from a relative or absolute positioned parent by setting its position to fixed. An element that has position: fixed will have the default left,right,top, and bottom styles set as auto. This will position .d3 to the top-left of .d2, and then the left: 83px style will push it to the left from there.
Making up the additional space..
However, to get that additional movement to the right as the original markup, you will need to add margin-left: 8px, which will make-up the additional ~8px needed to replicate the original. Further adjustments to the position of .d3 will need to be done by setting the margin style (see below).
Your updated code should look like this..
.d1 {
position: relative;
background-color: yellow;
height: 50px;
width: 100px;
overflow: hidden;
}
.d2 {
position: absolute;
background-color: green;
height: 25px;
width: 50px;
}
.d3 {
position: fixed;
margin-left: 8px;
left: 83px;
}
Some considerations and caveats..
As a previous commenter mentioned, best practice would be to fix your html markup because this solution could cause issues if you ever need to move the position of .d3. For example, setting left,right,top, or bottom will cause the default setting of this style, auto, from being unset, and the element will be positioned relative to the viewport rather than the parent relative or absolute element.

Set parent's (undefined width and height) dimension equal to child's

I have a parent div with undefined width or height.
The first child 'a' has set width and height. How can I make the parent have the size dimensions as the child.
.parent{
position: fixed;
background: green;
padding: 10px;
}
.child-a{
position:absolute;
width: 300px;
height:50px;
background: red;
}
.child-b{
width:100%;
height:120%;
background: blue;
}
<div class='parent'>
<div class='child-a'></div>
<div class='child-b'></div>
</div>
2nd part: I want the div 'c' to be 120% of the parent's height, and be positioned behind div 'a'. So only the bottom of 'c' is visible.
I've tried multiple solutions include display: table, overflow: overlay etc but nothing gives me the desired result. I'm looking for a CSS only solution.
function childSize () {
var parentHeight = document.getElementById( HAVE PARENTS ID HERE ).offsetHeight;
parentHeight = parentHeight / 100 * 120;
document.getElementById( HAVE CHILD C ID HERE ).offsetHeight = parentHeight;
}
This answer is only for the second part hope it helps :)
For height percentage to work, its parent has to have a height property too. See https://stackoverflow.com/a/16642908/5599288 . Therefore, the parent's height cannot be undefined or automatically sized.
You gotta set a fixed height on the parent, then control the child using percentage. This is how i would do it, in a pure CSS way,
https://codepen.io/jacobgoh101/pen/jZrvWw
.parent {
position: fixed;
background: green;
padding: 10px;
width: 300px;
height: 50px;
}
.child-a {
position: absolute;
background: red;
// set size, padding 10px and centering
width: calc(100% - 20px);
height: calc(100% - 20px);
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.child-b {
width: 100%;
height: 120%;
background: blue;
}

"top" CSS property has no effect when using a percentage

I have this CSS defined with my page:
.content {
background-image: url("img/bg.jpg");
width: 100%;
}
.exhibit {
width: 100%;
height: 100%;
text-align: center;
}
.yt-embed {
width: 560px;
height: 315px;
position: relative;
top: 50%;
}
The DIV with .yt-embed is inside one with .exhibit, and the DIV with .exhibit is inside one with .content.
My issue is that the "top" property in my .yt-embed class is having absolutely no effect. However, it does work when it is set to a pixel value, instead of a percentage.
Percentage values are relative-to-parent.
So, for any dimension of a given element, if you want to use a percentage value, the rendering engine must already know an explicit value for the corresponding dimension of the element's parent.
The one exception is the <html> element, which can accept a percentage value because the rendering engine will regard that value as relative-to-viewport instead of relative-to-parent.
Consequently, to enable your
.yt-embed {
top: 50%;
}
declaration to work, you'll need to declare:
html, body, div {
height: 100%;
}
at the start of your CSS.
My issue is that the "top" property in my .yt-embed class is having absolutely no effect.
Your problem is that your outter elements don't have a specific height. They are being expaded by the inner element .yt-embed that has the height declaration.
Using percentage based values is widely used and works fine. Here's a quick example:
* {
box-sizing: border-box;
}
.wrapper {
display: inline-block;
width: 300px;
height: 300px;
position: relative;
background: #f00;
padding: 10px;
}
.full.sized {
width: 100%;
height: 100%;
background: #0f0;
}
.inner {
position: absolute;
top: 50%;
left: 50%;
background: #00f;
color: #fff;
padding: 10px;
}
<div class="wrapper">
<div class="full sized">
<div class="inner">inner</div>
</div>
</div>
You can use the percents by changing the position to absolute
.yt-embed {
width: 560px;
height: 315px;
position: absolute;
top: 50%;
}
The parent element (in this case .exhibit) needs to have a pixel value on the height property, so that the browser can determine where exactly its position is.
You can read about top here: http://www.w3schools.com/cssref/pr_pos_top.asp
The same applies when applying a percentage value to the height of an element within another element; if the child has a percentage value then the parent must have a pixel value to have any effect.
Edit
Example:
.exhibit {
height: 315px;
*or*
min-height: 315px;
}
or create another div inside .exhibit, containing .yt-embed, with these values if necessary.
.yt-embed {
top: 50%;
position: absolute/relative;
width: 560px;
}

button position absolute not working as expected

Can anyone explain why this button is not absolute-positioned to the right? I would expect it to be 3px from every edge.
HTML:
<div class="wrapper">
<button>Hello world</button>
</div>
CSS:
.wrapper {
height: 300px;
width: 300px;
background-color: #f33;
position: relative;
}
.wrapper button {
position: absolute;
top: 3px;
bottom: 3px;
left: 3px;
right: 3px;
}
Also, how is it that the button is able to align its contents vertically?
button, like most form elements, is a replaced element. Replaced elements behave differently from regular non-replaced elements (such as div) when absolutely positioned. The following two points from section 10.3.8 of CSS2.1 apply:
The used value of 'width' is determined as for inline replaced elements. If 'margin-left' or 'margin-right' is specified as 'auto' its used value is determined by the rules below.
...
If at this point the values are over-constrained, ignore the value for either 'left' (in case the 'direction' property of the containing block is 'rtl') or 'right' (in case 'direction' is 'ltr') and solve for that value.
The width of the button is determined not based on the specified offsets, unlike for non-replaced elements, but by the contents of the button itself. Since the used value of width is not auto, and the specified values of left and right are not auto, the values are over-constrained and the browser is forced to ignore right in order to respect width.
If you want the button to fill the entire height and width of the wrapper, don't use absolute positioning. Instead, specify 100% height and width on the button, and use padding on the wrapper to offset the button:
.wrapper {
height: 300px;
width: 300px;
background-color: #f33;
padding: 3px;
box-sizing: border-box;
}
.wrapper button {
height: 100%;
width: 100%;
}
<div class="wrapper">
<button>Hello world</button>
</div>
(If you can't use box-sizing, subtract the padding from the dimensions of the wrapper.)
The vertical alignment of the text probably has to do with how the browser draws button controls by default, which is usually based on system button controls.
You can use calc to get the exact width minus the padding you get from the positioning:
width: calc(100% - 6px);
JSFiddle
You might want to use inherit/100% value for width and height css properties.
.wrapper {
height: 300px;
width: 300px;
background-color: #f33;
padding: 3px;
}
.wrapper button {
width: inherit;
height: inherit;
}
Fiddle
NOTE: If you want to have the dimensions exactly 300 then subtract padding. (which will be 294px)
please use below css ..
.wrapper {
height: 300px;
width: 300px;
background-color: #f33;
position: relative;
padding: 3px
}
.wrapper button {
position: absolute;
top: 0;
bottom:0;
left:0;
right:0;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
width:100%;
}
I think you are trying to put button in center.You declared top and left 3px so no matter what you define bottom and right button is going to to be 3px from top and left ignoring other.To put button in center use marginFirst define width of button and set marginLike thia
.
wrapper button{
Width:100px;
margin:0px auto;
}
not margin doesn't work with absolute position.
.wrapper {
height: 300px;
width: 300px;
background-color: #f33;
position: relative;
}
.wrapper button {
position: absolute;
top: 3px;
bottom: 3px;width:97.5%;
right: 3px;
}
Try this.
You need to set the width of the button, to make it fill the space.
The easiest way to do this is to set it to the correct size.
.wrapper {
height: 300px;
width: 300px;
background-color: #f33;
position: relative;
}
.wrapper button {
position: absolute;
top: 3px;
bottom: 3px;
left: 3px;
right: 3px;
height: 294px;
width: 294px;
}

CSS - margin top of 50% is more than 50%

I want a child div with a op-margin via percentage. The y-position shall be 50% percent of the parent div. But it is somehow more. Why isn't it 50% ?
js fiddle
HTML
<div class="content">
<header></header>
</div>
CSS
.content {
width: 300px;
height: 200px;
background: blue;
position: relative;
clear: both;
}
.content header {
width: 100px;
height: 100px;
margin-top: 50%;
background: red;
position: relative;
float: left;
}
This is because when it comes to top/bottom margins and paddings in percentages, the values will be taken as the fractional width of the parent element, not the height. According to the W3C definition:
The [margin] percentage is calculated with respect to the width of the
generated box's containing block. Note that this is true for
'margin-top' and 'margin-bottom' as well. If the containing block's
width depends on this element, then the resulting layout is undefined
in CSS 2.1.
This question has been addressed before in StackOverflow - see here.
Suggestion: If you would want to position an element in the center vertically, you can use the following trick instead:
Position the child element absolutely
Declare dimensions for the parent, such that the parent's dimensions do not rely on those of the child
Position the child element 50% from the top
Use a nifty trick of CSS 2D translation.
Here's the modified CSS from your fiddle that works:
.content header {
width: 100px;
height: 100px;
top: 50%;
background: red;
position: absolute;
-webkit-transform: translate(0, -50%);
transform: translate(0, -50%);
}
http://jsfiddle.net/teddyrised/73xkT/7/
Change child's position from relative to absolute.
Instead of margin-top use top
http://jsfiddle.net/73xkT/5/
.content header {
top: 50%;
position: absolute;
}