So I've come up with a way to center children in a parent that is smaller than itself. I'm not to keen on the extra markup it takes to accomplish, and I am wondering if there is a better way to accomplish this, with better meaning less extra markup/styling, or "cleaner" in general.
THE GOAL
Given a parent that is smaller (less wide), put the center of the child element in the center of the parent element dynamically without knowing the width of the child element or the parent element.
MY APPROACH
So my approach uses three nested spans (the element itself is of little consequence).
The first span has a width of 0px and is centered via margin: 0 auto. This gives us the center of the parent container.
The second span has a width of auto, a white-space of nowrap, and a display of inline-block. The display is the key here. This restores the natural width of the child element
the third span has a position of relative, and a left of -50%. This centers the span in relation to the parent by offsetting half of the width of the child in relation to the center of the parent.
THE QUESTION
Is there a cleaner/less "janky" way of doing this?
THE MARKUP
<div class="box">
<span class="first-wrap">
<span class="second-wrap">
<span class="third-wrap">
This should be centered in relation to the box;
</span>
</span>
</span>
</div>
THE STYLES
.box {
border: 1px solid red;
width: 20px;
height: 20px;
margin: 40px auto;
}
.box .first-wrap {
display: block;
width: 0px;
margin: 0 auto;
border: 1px solid blue;
}
.box .first-wrap .second-wrap {
display: inline-block;
white-space: nowrap;
width: auto;
border: 1px solid green;
}
.box .first-wrap .second-wrap .third-wrap {
position: relative;
left: -50%;
border: 1px solid black;
}
THE FIDDLE
https://jsfiddle.net/d3w1wom0/
Just delete your css and replace with the following:
.box {
display: flex;
justify-content: center;
border: 1px solid black;
}
If you want to change the width, and center things accordingly you can just add the following to the above .box class:
width: 60%;
margin: 0 auto;
.box {
display: flex;
align-items: center;
justify-content: center;
height: 20px;
}
will center your text in the box
Related
I need to center image inside my div but when i use some code it will change my other code and that is like magic circle.
My HTML http://textuploader.com/d40ta
My CSS http://textuploader.com/d40t5
Images are inline-block by default. That means you can center them inside a block-level parent by using text-align: center. <div> or <p> elements, to name a few, are block-level by default, but you can make almost any element block-level by applying display: block to that element.
If the image is display: block already, you can center it by applying margin: 0 auto where the auto is the functional value (the first value could be any unit, adding margin to the top and bottom of the image).
CSS3 Solution:
Simply modify the below CSS class.
.iui {
border: 2px solid black;
width: 200px;
height: 200px;
border-radius: 100px;
top: 20px;
display:flex;
justify-content:center;
align-items:center;
background-color: red;
margin-left: auto;
margin-right:auto;
}
JSFiddle Demo
CSS Solution:
In the below solution, we need to set the CSS property line-height the same as that of the element height for the class iui. Then we need to set the image inside the div with the CSS properties display:inline-block;vertical-align:middle, this will center the image.
.iui {
border: 2px solid black;
width: 200px;
height: 200px;
line-height: 200px;
border-radius: 100px;
text-align: center;
background-color: red;
margin-left: auto;
margin-right:auto;
}
.iui img{
vertical-align:middle;
display:inline-block;
}
JSFiddle Demo
I have a general, possibly beginner question about HTML.
#container {
height: 200px;
max-width: 600px;
border: 1px solid black;
margin: auto;
margin-top: 10px;
}
#item1 {
height: 100px;
max-width: 200px;
border: 1px solid red;
}
#item2 {
height: 100px;
max-width: 200px;
border: 1px solid blue;
}
<div id="container">
<div id="item1"></div>
<div id="item2"></div>
</div>
My question is, why do #item1 and #item2 divs go underneath each other as opposed to next to each other? Isn't it true that they are no longer block-level elements because I have specified a set width for them? Why are they not lined up next to each other inside of #container? The #container has more than enough width to accommodate both items.
Note: This is strictly for learning/curiosity. I know that I can use margins and positioning to place them where I want to. However, I'm just curious as to why it behaves this way.
Thanks.
Div elements are block elements, unless you specify the display property to inline or inline-block it wont align to to the right like other inline elements do.
adding display : inline-block to the css of div's will give you what you want.
You have two ways to place you blocks horizontally: display property or float property.
It doesn't matter that you have set width to your elements. They are still block and displayed vertically.
To change this behaviour, use stylesheet (note that in both cases width, not max-width should be set):
#container {
height: 200px;
max-width: 600px;
border: 1px solid black;
margin: auto;
margin-top: 10px;
}
#item1 {
height: 100px;
width: 200px;
border: 1px solid red;
display: inline-block;
}
#item2 {
height: 100px;
width: 200px;
border: 1px solid blue;
display: inline-block;
}
or this:
#container {
height: 200px;
max-width: 600px;
border: 1px solid black;
margin: auto;
margin-top: 10px;
}
#item1 {
height: 100px;
width: 200px;
border: 1px solid red;
float: left;
}
#item2 {
height: 100px;
width: 200px;
border: 1px solid blue;
float: left;
}
<div> tag always start with new line if you are not using frameworks like bootstrap or other. If you want to see multiple items in single line then add css like display: inline-block
just add float:left; property in child divs or display:inline-block; https://jsfiddle.net/8tvn0kw6/5/
div is the standard block-level element. A block-level element starts on a new line and stretches out to the left and right as far as it can. Other common block-level elements are p and form, and new in HTML5 are header, footer, section, and more.
Even if you specify width it wont allow other elements right next to it. This the property of block level element.
Use the css inline-block it will occupy the specified width or content width.
https://developer.mozilla.org/en-US/docs/CSS/display
The height of the container should be the sum of heights of the child divs and the heights of the borders of the children
ie., height of parent container = 100+ 100+ 1+ 1+ 1+ 1 = 204px
#container {
height: 204px;
}
The #container ie you div has a display property of block. This is a default property if you don't set it to anything else. In your case the div takes this default display property.
To view #item1 and #item2 side by side just use display: inline-block in your #container.
Please replace your class like below.
#item1{
height:100px;
max-width:200px;
border:1px solid red;
display:inline-block;
}
#item2{
height:100px;
max-width:200px;
border:1px solid blue;
display:inline-block;
}
I have the following:
#innerLabels,
#innerFields {
display: inline-block;
width: 200px;
height: 200px;
border-style: solid;
border-width: 1px;
vertical-align: top;
}
.innerLabel {
display: table;
border-style: solid;
border-width: 1px;
height: 100px;
width: 80%;
}
.innerLabel div {
display: table-cell;
vertical-align: middle;
border-style: solid;
border-width: 1px;
}
#outterFields {
background-color: red;
width: 60%;
min-width: 300px;
height: 300px;
}
#outterFields div {
display: inline-block;
}
<div id="outterFields">
<div id="innerLabels">
<div class="innerLabel">
<div>hello</div>
</div>
</div>
</div>
I can't work out why the inner most div isn't being centred? I did look at some of the answers here regarding centring however I can't see what the problem is...
I want the hello to be centred vertically to the centre but not horizontally. All other divs are positioned how I want them. There is no error in the other divs they are positioned side by side for a reason. The only change I want is the hello div moved vertically to the centre
You are just overiding your inner div with
#outterFields div {
display: inline-block;
}
Just remove it or if you where intending a direct child do:
#outterFields > div {
display: inline-block;
}
#innerLabels,
#innerFields {
display: inline-block;
width: 200px;
height: 200px;
border-style: solid;
border-width: 1px;
vertical-align: top;
}
.innerLabel {
display: table;
border-style: solid;
border-width: 1px;
height: 100px;
width: 80%;
}
.innerLabel div {
display: table-cell;
vertical-align: middle;
border-style: solid;
border-width: 1px;
}
#outterFields {
background-color: red;
width: 60%;
min-width: 300px;
height: 300px;
}
#outterFields div {
/* display: inline-block; */
}
<div id="outterFields">
<div id="innerLabels">
<div class="innerLabel">
<div>hello</div>
</div>
</div>
</div>
Your outterfields display inline block is overwriting other display items. I came up with better solution for you. I haven't used table but used flex here learn about flex it's more worth.
#outterFields {
background-color:red;
width:60%;
min-width:300px;
height:300px;
}
#innerLabels, #innerFields {
display:flex;
align-items:center;
width:200px;
height:200px;
border: 1px solid #000;
}
.innerLabel {
display:flex;
align-items:center;
border: 1px solid #000;
height:100px;
width:80%;
}
.innerLabel div {
display:table-cell;
vertical-align: middle;
border: 1px solid #000;
}
<div id="outterFields">
<div id="innerLabels">
<div class="innerLabel"><div>hello</div></div>
</div>
</div>
The necessary and most often sufficient condition where you can center a div using a display: table-cell, is as follows:
<div id="a">
<div id="b">
<div id="c">Helo</div>
</div>
</div>
CSS as follows:
body, html {
height: 100%;
}
#a {
display: table;
width: 100%;
height: 100%;
}
#b {
display: table-cell;
vertical-align: middle;
}
#c {
margin: auto;
text-align: center;
}
You need html and body elements to actually span the entire height of the document area if you want your a div to be able to make use of its 100% height. If your use case demands height that does not depend on the height of the document body, you don't have to use the body, html selector.
When you use display: table the otherwise auto-expanding width for a div element (width: auto implicit rule) does not apply the same way anymore as elements with display: table use a conservative width calculation -- they only by default take as much space as the content requires. Since I am illustrating a "100% 100%" centering to you, I have width: 100% there to have the element expand to available parent width.
height: 100% is likewise needed to have the element expand to available parent height. It does not matter if its display: block as with regular div elements, or display: table -- you need to specify height if you want computed height that goes beyond content height.
The display: table-cell rule only works if there is an ancestor element with display: table, hence you need at least two elements inside one another to apply display: table-cell to the one that is contained in the other. You don't need to specify height because elements with display: table-cell occupy available parent height automatically.
vertical-align rule for the display: table-cell elements is the only case where the alignment applies to the content inside the element, as opposed to its usual behavior where it applies with regard to how the element is positioned within the parent. Meaning that in our case, the vertical-align tells the browser that everything contained in the element with display: table-cell is to be centered vertically within its computed height.
For the c element you would need margin: auto only if you had content that did not completely fill available parent width. Since div elements normally do, it is not necessary, but is forward thinking on my part -- in case you decide to use span or something else that computes its width conservatively. The text-align speaks for itself -- The anonymous textual content and text inside descendant elements, will be centered in the middle along horizontal axis.
I have the following fiddle for this question: http://jsfiddle.net/jcb9xm44/
There are 2 inline-block div's in a parent div:
<div class="outer">
<div class="inner1">
Y
</div>
<div class="inner2">
X
</div>
</div>
The css assigns a width to the parent div and 2 widths to the child div's.
.outer {
width: 210px;
border: 1px solid red;
}
.inner1 {
width: 200px;
border: 1px solid orange;
display: inline-block;
}
.inner2 {
width: 50px;
position:relative;
left: -50x;
display: inline-block;
border: 1px solid lightblue;}
I was expecting that both divs appear on the same line. Although the parent is not wide enough to hold both children, since the second child has a negative offset, it should be possible to fit them both on the same line. Why does it break the line?
Why does it break the line?
As you stated, it's because the parent element isn't wide enough for both elements. To change this behavior, you could add white-space: nowrap to the parent element in order to prevent the inline-block elements from wrapping.
Example Here
.outer {
width: 210px;
border: 1px solid red;
position:relative;
white-space: nowrap;
}
Side notes:
You had a typo - left: -50x -> left: -50px.
inline elements respect whitespace in the markup.
The element's border is included in its width calculations. Use box-sizing: border-box to include it.
You could alternatively use margin-left: -50px as Mary Melody pointed out.
I have a "container" div to which I gave margin:auto;.
It worked fine as long as I gave it a specific width, but now I changed it to inline-block and margin:auto; stopped working
Old code (works)
#container {
border: 1px solid black;
height: 200px;
width: 200px;
}
.MtopBig {
margin-top: 75px;
}
.center {
margin-left: auto;
margin-right: auto;
text-align: center;
}
<div class="center MtopBig" id="container"></div>
New code (doesn't work)
#container {
border: 1px solid black;
display: inline-block;
padding: 50px;
}
.MtopBig {
margin: 75px auto;
position: relative;
}
.center {
text-align: center;
}
<div class="center MtopBig" id="container"></div>
DEMO fiddle.
It is no longer centered because it now flows on the page in the same way inline elements do (very similarly to img elements). You will have to text-align: center the containing element to center the inline-block div.
#container {
border: 1px solid black;
display: inline-block;
padding: 50px;
}
.MtopBig {
margin: 75px auto;
position: relative;
}
.center {
text-align: center;
}
<div class="center">
<div class="MtopBig" id="container"></div>
</div>
What 'auto' means:
Using auto for the horizontal margin will instruct the element to fill up the available space (source: http://www.hongkiat.com/blog/css-margin-auto/).
Why 'display: inline-block' does not center:
There is no available horizontal space in an inline setting. Before and after it are other inline elements (characters) that take up their own space. Therefore, the element will act as if the horizontal margin is set to zero.
Why 'display: block' centers:
When used as an element with display: block set to it, the available horizontal space will be the full width of the parent element minus the width of the element itself. This makes sense because display: block is reserving this horizontal space (thus making it 'available'). Note that elements with display: block cannot be placed next to each other. The only exception occurs when you use float, but in that case you also get the (expected) zero-margin-behaviour, as this disables the horizontal 'availability'.
Solution for 'inline-block' elements:
Elements with display: inline-block should be approached as characters. Centering characters/text can be done by adding text-align: center to their parent (but you probably knew that already...).
For elements with property display: inline-block;
A computed value of 'auto' for 'margin-left' or 'margin-right' becomes a used value of '0'. [reference: CSS2ยง10.3.9]
margin-left:50%;
transform: translateX(-50%);
.container{
border:solid 1px red;
}
.container img{
display:inline-block;
margin-left:50%;
transform: translateX(-50%);
}
<div class="container">
<img src="https://placekitten.com/100/300" />
</div>