Margin:auto's function in centering a div within a div - html

I was searching the archives and came across the following article about how to center a div within a div, where the solution was to apply the following styles to the inner div:
#inner {
width: 50%;
margin: auto;
}
The answer states that the margin:auto is what causes the centering. How exactly does this work?

margin:auto; is specifically designed to automatically set a margin, usually for the purpose of centering an element. It actually only works on the left and right margins. Using margin:auto; is shorthand for the following:
{ margin:0px auto 0px auto; }
And to spell that out further:
{ margin-top:0px; margin-right:auto; margin-bottom:0px; margin-left:auto; }
Check out the CSS2 spec.

It basically solves the equation margin = ("outer-width" - "inner-width") / 2 and sets the result to the margin value.
The result is, that the margin of your inner div is the same on both sides and its overall width (width + 2×border + 2×margin) fills exactly your outer div. So it's body is centered.

Related

overflow:hidden on inline-block adds height to parent

I'm certain this has been asked before in some form or other, but I just can't find an answer..
I have some nested divs
<div class="parent">
<div class="child">A</div>
</div>
And the child has display:inline-block and overflow:hidden
.parent{
background-color:red;
}
.child{
background-color:green;
display:inline-block;
overflow:hidden;
}
And it gets rendered like this:
You can notice that the parent is 5px higher than the child.
Where does the extra height come from?
Here is the sample: http://jsfiddle.net/w8dfU/
Edit:
I don't want to remove display:inline-block or overflow:hidden, this is a simplified example to illustrate the problem, but in my real layout I need them both.
I just want to understand why this extra height appears. Is it specified somewhere that it should be like this? Is it a consequence of some other css feature?
I had this issue when building a horizontal slider. I fixed it with vertical-align:top on my inline-block elements.
ul {
overflow-x: scroll;
overflow-y:hidden;
white-space: nowrap;
-webkit-overflow-scrolling: touch;
}
ul&::-webkit-scrollbar {
display: none;
}
li {
display: inline-block;
vertical-align: top;
width: 75px;
padding-right: 20px;
margin:20px 0 0 0;
}
The accepted answer above is correct, but it does not give the explanation I was looking for.
A good explanation was provided by #Alohci in his comment.
Explanation in a few words:
The value for vertical-align is baseline, therefore the child div is aligned with the baseline of the text.
This text baseline is not the same as the bottom line. It's a bit higher up, to accommodate letters with descenders: p, q, g.
This is why the problem is fixed by setting vertical-align:top.
.child{
background-color:green;
display:inline-block;
overflow:hidden;
vertical-align: top;
}
This extra space coming from overflow:hidden of Child class. Remove this property and check and if your really wanted to use overflow:hidden property then use negative margin to child class . You can remove this extra space.

Regarding margin property and value auto

CODE:
*{
margin:0px;
padding:0px;
}
body{
font-family:sans-serif;
width:1024px;
height:700px;
border:1px solid green;
//margin:0 auto;
margin-left:auto;
margin-right:auto;
margin-top:auto;
margin-bottom:auto;
}
1.i expected a centered box from all sides , but top part of the box model is at beginning of body, if i explicitly set margin-top:20px, boxmodel is moved down, but why top part doesnt align automatically like others.
2.i also didnt get what auto value "DOES" to achieve centering
in case of margin:0 auto; // what is the unit of 0?px,em or pt.
Vertical alignment in Css is such a fun and painful topic. This stackoverflow queston is the best concise explanation I have seen regarding why vertical alignment can be so painful
As to your 1st question, the reason you can't vertically align using margins is explained below in the quote.
... the nature of document flow and element height calculation algorithms make it impossible to use margins for centering an element vertically inside its parent. Whenever a vertical margin value is changed, it will trigger a parent element height re-calculation (reflow), which would in turn trigger a re-center of the original element... making it an infinite loop.
As to your 2nd question, margin auto achieves horizontal centering by calculating the width of the child container in relation to its parent's width. Then it does simple math to add an even amount of margin to the left and right of the child container, enforcing horizontal centering.
As for 2nd question Part B,
margin: auto is the same as the following:
margin-top: auto;
margin-bottom: auto;
margin-right: auto;
margin-left: auto;
where as margin: 0 auto is the equivalent to the following:
margin-top: 0;
margin-bottom: 0;
margin-right: auto;
margin-left: auto;
A solution to achieve vertical centering
There are some options that you can utilize however to achieve vertical alignment despite the limitations. The easiest is to leverage a table. With tables, one of the few strong points of them is that using the vertical-align property actually behaves as you would expect when enforced inside of a table. So you can do something like the following:
<body>
<table style="width: 100%; height: 100%">
<tr>
<td>
<div id="verticallyCenteredContent" style="vertical-align: middle">
OMG it's vertically aligned
</div>
<td>
<tr>
<table>
<body>
There are two other common methods that I demonstrated in this jsfiddle.
Useful article that demonstrates a number of scenarios and approaches for achieving vertical centering - Vertical Centering with Css
Cheers!
At first, use css to horizontal centering the "Div". After that is using javascript to centering vertical. See demo on jsfiddle
HTML:
<div class="center">Div content</div>
CSS:
.center {
font-family:sans-serif;
width:300px;
height:300px;
border:1px solid green;
margin: 0 auto;
text-align:center;
}
JS (JQuery):
$().ready(function () {
$(".center").css("margin-top", ($(window).height() - 300) / 2);
});
See demo on jsfiddle
Here is one more resource on CSS margin issue. http://techslate.net/looking-at-css-margins/

CSS alternative to center

People frown upon the center tag, but for me it always works just the way I want it. Nevertheless, center is deprecated so I'll make an effort.
Now I see many people suggest the cryptic CSS margin: 0 auto; but I can't even get it to work (see fiddle here). Other people will go modify position or display, but that always breaks something else.
How can I center a span using css so that it behaves exactly like the center tag?
<div class="container">
<span class='btn btn-primary'>Click me!</span>
</div>
Span is an inline element, and the margin: 0 auto for centering only works on non-inline elements that have a width that is less than 100%.
One option is to set an alignment on the container, though this probably isn't what you want for this situation:
div.container { text-align: center }
http://jsfiddle.net/MgcDU/1270/
The other option is to change the display property of the span:
/* needs some extra specificity here to avoid the display being overwritten */
span.btn.btn-primary {
display: table;
margin: 0 auto;
}
Using display: table eliminates the need to hard code a specific width. It will shrink or grow as appropriate for its content.
http://jsfiddle.net/MgcDU/1271/
You can set .container { text-align:center; } so that everything inside div.container will be centered.
In general, there are two ways centering things.
To center inline elements (such as text, spans and images) inside their parents, set text-align: center; on the parent.
To center a block level element (such as header, div or paragraph), it must first have a specified width (width: 50%; for example). Then set the left and right margins to auto. Your example of margin: 0 auto; says that the top and bottom margin should be 0 (this doesn't matter for centering) ad that the left and right margins should be auto - they should be equal to each other.
The <center> element is really just a block-level element with text-align:center;. If you sent border: solid red 1px; on it, you can see that it's 100% wide, and that everything inside it is centered. If you change text-align to left, then its children are no longer centered. Example: http://jsfiddle.net/KatieK/MgcDU/1275/. Perhaps you should just consider your <div class="container"> with text-align:center; } to be equivalent to <center>.
You make the span block level, give it a width so margin:auto works
see this fiddle
.center {
display:block;
margin:auto auto;
width:150px; //all rules upto here are important the rest are styling
border:1px solid black;
padding:5px;
text-align:center;
}
UPDATE: In order to NOT specify a width and have natural width of element on the span you will have to use textalign on parent
see this fiddle
.container{text-align:center}
.center {
border:1px solid black;
padding:5px;
}
<span> is an inline element. <div> is a block element. That's why it is not centering.
<div class="container" style='float:left; width:100%; text-align:center;'>
<span class='btn btn-primary'>Click me!</span>
</div>
You can center the content of span only when you convert it into block, using 'inline-block' style.
Your parent element needs to have a larger width in order to let a child element be positioned within it. After that the trick with margin: 0 auto; is getting the parent and child container position and display values to be compatible with each other.
.container {
border: 2px dashed;
width: 100%;}
.btn {
display: block;
margin: 0 auto;
width: 25%;
}
http://jsfiddle.net/rgY4D/2/

padding is getting added to width of div

i use this code
<div class="main">
<div class="babyOne">
</div>
<div class="babyTwo">
</div>
</div>
.main{
width:100%;
position:relative;
}
.babyOne,.badyTwo{
width:50%;
float:left;
}
with this CSS above everything works fine.
but as soon as i give padding to inner divs all the ui breaks,
.babyOne,.badyTwo{
width:50%;
float:left;
padding:5px;
}
and fire bug shows the increase in the width of divs equal to padding.
According to padding property this should not happen.
any idea how to prevent this?
First of all you need to learn CSS box-model
This states that whatever padding, border, margin you add to you element does count outside it, so for example the element is of 200px width and 100px height, if you add padding say 5px than the width and height will be 205px and 105px respectively, so inorder to workaround with this you need to use CSS3 box-sizing property, but as still it is CSS3 property and if IE is the main thing you want to supprt, I suggest you to resize the elements according to your needs
So for example a div with these styles
div {
height: 100px;
width: 200px;
padding: 5px;
}
You can re-size the above as
div {
height: 95px;
width: 195px;
padding: 5px;
}
CSS3 box-sizing Reference
The WRAPPER must have fixed size: http://jsfiddle.net/esVgH/1 example:
.main{
width:200px;
position:relative;
}
Another solution is display the .baby as a table cell:
.babyOne, .badyTwo {
display: table-cell;
}
Your problem is the expected behaviour.You set a width and then you say give it some padding.So the width plus the padding is going to be greater than the original width.
You can try CSS3s box-sizing attribute: http://www.quirksmode.org/css/box.html
I'm not sure how widely supported it is though.
There's also a host of SO answers here: How apply padding in HTML without increasing the div size?
.babyOne,.badyTwo{
width:45%; /* As you have like based on padding */
float:left;
padding:5px;
}

Dynamic width with inline-block

I have two <div> elements, one next to the other. Both have the CSS attribute display: inline-block;. Now the second <div> element has a fixed width of 100 px, whereas the first <div> element doesn't have a fixed width: it depends on the size of the window.
My problem is that the first <div> element will spread over 100% vertically if the window is narrow. I would like to restrict its width to 100% minus 100px, so that both <div> elements can align one next to the other at all times.
I've looked at posts with similar questions, but none really dealt with the case of inline-block.
EDIT: Here is a jsfiddle: http://jsfiddle.net/y3sXu/ I want the first <div> to provide some room for the second <div> on the same line.
There's no particular reason to use display: inline-block to do this.
Here's a clean implementation using floats instead: http://jsfiddle.net/y3sXu/14/
<div id="container">
<div id="DivB">b</div>
<div id="DivA">a</div>
</div>
#container {
overflow: hidden;
}
#DivA {
overflow: hidden;
}
#DivB {
float: right;
width: 100px;
}
This is an old question but has some weight in Google so I thought I'd update it with a new answer. A more modern way to accomplish this is to stick with display:inline-block; and use calc for the width of the variable element.
So long as you have one fixed width inline element width: 150px, you can offset the variable width element by the fixed width calc(100% - 150px).
Your code should look like this:
.fixed-width-element {
display: inline-block;
width: 150px;
}
.variable-width-element {
display: inline-block;
width: calc(100% - 150px);
}
I think I understand what you are asking for. http://jsfiddle.net/y3sXu/6/
I have gone for a traditional two column layout, as it seems like the best way to solve your problem.
float has been used to ensure that the right hand div always sits on the right, and margin-left to keep the left div away. overflow:hidden is used a cheap and cheerful clearfix.
best way I can figure doing it is with absolute positioning:
div#TextB{
position:absolute;
right:10px;
top:10px;
}
div#master{
margin-right:120px;
}
http://jsfiddle.net/Vnxr7/1
There is one very ugly solution:
Set the overflow of the outer div to hidden, take the div out of the dom using position:relative, setting the left to -100px and the width to 100%.
You have to play around with the display, position and left/top etc. or get back with some more details so one could know what you want to achieve.
what about this ?
div {
background:green;
margin-right:100px;
}
#TextB{
width:100px;
background:red;
float:right;
margin:0px;
}
Updated version
Just give the outer div a padding of 50px on both left and right side
EDIT
Place this where u want to put the gap:
<div width="100px" height="1em"> <div>