I am trying to vertically align a div and an input:
<div id="a">
Button
</div>
<input type="text" id="b" placeholder="text">
They both share the same styles:
#a, #b{
box-sizing: border-box;
vertical-align: baseline;
padding: 0;
margin: 0;
outline: none;
font-size: 10px;
line-height: 10px;
font-family: serif;
border: none;
height: 30px;
width: 100px;
background: green;
display: inline-block;
border: none;
}
However, they are not vertically aligned:
Sample
How is that possible?
Please note: This is an abbreviated example from a bigger project where I have to use vertical-align: baseline. It is not possible to change that value and I do not want to use any hack like adding a margin-top. I want to understand why the vertical-align behaves this way and try to find a clean solution.
Since your height has a static value, you can use line-height: 30px; CSS property to force the alignment you want.
JSFiddle
Cumbersome explanation:
Your div's baseline is 10 px (see line-height property), while your element's height is 30 px. Text inside input element is vertically centered by default, baseline, in your case, 30px. So basically, browser tries to center elements by it's baseline, which is different for the elements, thus causing the first element, with a smaller baseline value, to be pushed down.
You need to add float: left to make it align on vertically.
Related
in chrome, I thought the height of .wrap should be 24px.
it is 25px when the vertial-align is set to middle. can someone explain why?
answer in this article
body {
line-height: 1.5;
}
.wrap {
font-size:16px; /* 16*1.5= 24 */
}
.btn {
font-size: 14px;
padding: 4px;
line-height: 1;
box-sizing: border-box;
border: 1px solid blue;
vertical-align: middle;
}
<div class="wrap">
<button class="btn">
OK
</button>
</div>
As It is explained Here
Aligns the middle of the element with the baseline plus half the
x-height of the parent.
The line-height of your .wrap element is by default 1.5 that inherits from the body, the vertical align property will render depending on your line-height, so if the line height is bigger than your wrapper element, you will see the effect. to fix it just put line-height in your .wrap class, you can play with it to see how the line-height affects the vertical alignment.
body {
line-height: 1.5;
}
.wrap {
line-height:1;
background:red;
}
.btn {
font-size: 14px;
padding: 4px;
line-height: 1;
box-sizing: border-box;
border: 1px solid blue;
vertical-align: middle;
}
<div class="wrap">
<button class="btn">
OK
</button>
</div>
Inline elements (for whatever reason) are surrounded by whitespace.
Changing the element to display: block will fix your problem but there are other ways to fix it whilst keeping it inline.
One way would be to set font-size: 0 on the .wrap element as the whitespace is governed by font size. In this instance that would be fine as you are setting a font size on the child button (beware when using ems as they are relative to the parent font size).
More options can be found here - https://css-tricks.com/fighting-the-space-between-inline-block-elements/
Solving the problem:
Simply you're getting the extra pixel because of this:
body {
line-height: 1.5;
}
All your HTML elements are inheriting this attribute from the body.
Answering the question:
why the height of the out div is affected by vertical-align
The <button> default display attribute is "inline-block", which gets affects by white-spaces, line-height, font-size, and other text-related CSS attributes. vertical-align is one of these text-related attributes. For example, if you change the button's display to "block" you can see that it no longer affects the .wrap's height.
Please give block CSS for the btn
.btn { display: block;}
Why block and not inline-block??
Elements in the inline formatting context will cause white spaces from carriage returns and white-spaces in your HTML
The inline-block value is incredibly useful when wanting to control margin and padding on "inline" elements without the need to block and float them. One problem that arrises when you use inline-block is that whitespace in HTML becomes visual space on screen.
This isn't a "bug" (I don't think). It's just the way setting elements on a line works. You want spaces between words that you type to be spaces right? The spaces between these blocks are just like spaces between words.
So thats OK!
I have a very simple setup:
<button>
Lorem
</button>
<input type="text" value="Ipsum">
with both elements next to each other using display: inline-block:
button, input{
height: 34px;
line-height: 34px;
display: inline-block;
box-sizing: border-box;
vertical-align: baseline;
padding: 0;
margin: 0;
border: 1px solid green;
font-size: 14px;
}
Example here: http://jsfiddle.net/j02ypo0v/
As you can see, the two elements are not perfectly aligned (off 1px).
I know, I could easily solve this by changing vertical-align to middle, but I want to understand why this offset is present in the first place.
IMO, it doesn't make any sense that the two elements are not perfectly vertically aligned since they share all CSS attributes (especially height, line-height, display and vertical-align).
Can anybody explain me where the 1px offset is coming from?
The baseline alignment is to do with the positioning of the text rather than the positioning of the element as a whole. If we zoom in on the button and input elements and add a straight line below the text, you'll see that the text in both elements is in fact vertically aligned at the same position:
I can't tell you what the exact cause of the problem is, but what I do know is that if you reduce the line-height to 32px or increase it to 35px the two elements become in line with each other whilst keeping the text in line as well:
My guess is that there's a difference in calculation on the browser side of things when using a line-height of 34px and a font-size of 14px between a button and input element as in your example, as if we do change the vertical-align to middle as your question suggests the text is no longer in line:
It's because a button is replaced inline element.
MDN says about line-height:
On non-replaced inline elements, line-height specifies the height that
is used to calculate line box height. On replaced inline elements such
as buttons or other input element, line-height has no effect.
You need to remove the following:
padding: 0, since the input will naturally have padding
height: 34px, since you already use the line-height
Find the results here: jsfiddle.net
button, input{
line-height: 34px;
border: 1px solid green;
font-size: 14px;
display: inline-block;
box-sizing: border-box;
vertical-align: baseline;
margin: 0;
}
I have added a yellow div container so it's easier to see.
I have a problem concerning CSS and HTML.
I'm trying to wrap a DIV around another element (an UL in this case) and having it wrap around it and at the same time keeping both centered. As an added bonus I can't set a specific width since the width of the content inside the wrapping DIV have to be dynamic (since this is basically a template).
I've tried floating, and that works as far as wrapping goes, but then the thing ends up either to the right or to the left.
I'm going a bit crazy over this, and google is no help!
Thanks in advance!
UPDATE:
Sorry about not including code or images. This is what I'm trying to do illustrated with images:
One state of the UL width
Another state of the width
The wrapping DIV can't stretch the full width of the container. It has to wrap around the UL.
The dark grey is the DIV around the UL. I need the DIV to wrap around the UL (which has a horizontal layout) no matter the width of the content, since like I said above, the content of the UL is going to by different from time to time. The text in the LIs are going to change.
I also need it to be centered. I've made it work with float left and float right, but I need it to be centered.
This is the code I'm currently using for the container DIV and the UL and LI elements:
#container{
height: 100px;
width: 500px;
font-size: 14px;
color: #grey;
display: table-cell;
vertical-align: middle;
}
#container ul{
text-transform: uppercase;
text-align: center;
font-weight: bold;
}
#container li{
background: url(checkmark.png) center left no-repeat;
display: inline;
padding-left: 20px;
margin-right: 5px;
}
#container li:last-child{
margin-right: 0;
}
UPDATED
I got it. Is it this you were looking for?? http://jsfiddle.net/vZNLJ/20/
#wrapper {
background: #ccc;
margin: 0 auto; /* to make the div center align to the browser */
padding: 20px;
width: 500px; /* set it to anything */
text-align: center;
}
#wrapper ul {
background: #aaa;
padding: 10px;
display: inline-block;
}
#wrapper ul li {
color: #fff;
display: inline-block;
margin: 0 20px 0 0;
}
#wrapper ul li:last-child {
color: #fff;
display: inline-block;
margin: 0;
}
<div id="wrapper">
<ul>
<li>Menu</li>
<li>Menu</li>
<li>Menu</li>
</ul>
</div>
This is an old post, but what you can do now is:
<div style="display: flex; justify-content: center;">
<div style="display: inline-block;">
<input type="button" value="Example Button" />
</div>
</div>
The problem isn't wrapping the DIV around the content, but getting the content to state it's actual size, therefore pushing the DIV boundaries out. There are several things that need to be considered when tackling this issue. Not just from an existing UL or LI tag, but a DIV within a DIV.
I use custom tags to help describe layouts cleaner. Custom tags are DIV tags, thus their properties must be manipulated by CSS in order to get the proper behavior.
<layout-linear horizontal>
<control-label>Label 1</control-label>
<control-label>Label 2</control-label>
<control-label>Label 3</control-label>
<control-label>Label 4</control-label>
<control-label>Label 5</control-label>
</layout-linear>
This layout suggests that the contents .. the control-label(s) tags .. will be display in a horizontal row. To get the border for the layout-linear tag to wrap around the content of the control-label tags, there are several things to do:
layout-linear[horizontal]
{
display : block;
box-sizing: border-box;
border : 1px solid black;
padding : 1px 1px 1px 1px;
white-space: nowrap;
width : 100%;
clear : both;
text-align : center;
}
First, the box-sizing property must be set to border-box. This will force the linear-layout (DIV) tag to wrap around content. Padding, Border, Margin will insure that an empty DIV tag displays. Other tricks to make an empty DIV tag display are to use or :after { content:.; visibility: hidden; }.
If you don't want the control-label tags to wrap, adding white-space : nowrap.
I will discuss text-align when I discuss the float property of the control-label tag.
The next part requires the inner DIV tags (control-labels) to properly specify their box-sizing type and borders.
control-label
{
display : inline-block;
/* float : left; */
box-sizing: border-box;
border : 1px solid black;
margin : 5px 5px 5px 5px;
padding : 5px 5px 5px 5px;
}
Display : inline-block, causes the control-label tags to flow left to right. Display : Block, will cause the tags to stack up vertically.
Float is commented out specifically to draw your attention to the fact that float will cause the layout-linear tag shrink to its smallest box size, based on the margins, padding, and border.
To have the control-labels flow right to left, add text-align : right to the layout-linear tag. Or in this specific case, set text-align : center.
Again, box-sizing is used to tell the control-label (DIV) tag to wrap around it's content completely. Not just the text, but the edges of the box as drawn by the border, padding and margin settings.
This arrangement of CSS properties is what causes the outer and inner boxes to be rendered properly, or as expected.
Happy Coding.
You didn't supply code, but take a look at this fiddle I just setup, which might help:
http://jsfiddle.net/qXDJr/
Please let me know if I'm misunderstanding what you mean. Example code will always help for future reference.
This might help.
If you cant set the width you can just add align='center' in the div wrapping ul
<div align="center">
<ul>
<li>MenuItem</li>
<li>MenuItem</li>
<li>MenuItem</li>
</ul>
</div>
Consider the following example: (live demo here)
HTML:
<div id="outer_wrapper">
<div class="wrapper">
<a><img src="http://img.brothersoft.com/icon/softimage/s/smiley.s_challenge-131939.jpeg" /></a>
</div>
<div class="wrapper">
<a><img src="http://assets.test.myyearbook.com/pimp_images/home_page/icon_smiley.gif" /></a>
</div>
<div class="wrapper">
<a><img src="http://thumbs3.ebaystatic.com/m/mvHqVR-GDRQ2AzadtgupdgQ/80.jpg" /></a>
</div>
<div class="wrapper">
<a><img src="http://upload.wikimedia.org/wikipedia/commons/thumb/f/fa/718smiley.png/60px-718smiley.png" /></a>
</div>
</div>
CSS:
#outer_wrapper {
background-color: #bbb;
width: 350px;
}
.wrapper {
display: inline-block;
border: 1px solid black;
width: 90px;
height: 100px;
text-align: center;
margin-right: 20px;
}
a {
display: inline-block;
width: 80px;
height: 80px;
border: 1px solid red;
}
The output is:
Why the black wrappers are not vertically aligned ? How could I fix that ?
The images are horizontally centered in the red boxes. How could I vertically center them ?
Please do not change the HTML, if possible.
Observe that it is the base of the images which are aligned. This is to do with the vertical-align; if you use a value for vertical-align on .wrapper other than baseline, like top, middle or bottom, it will fix it. (The difference between these will only be apparent if you put some text inside the div as well.)
Then you want to centre the images in their 80x80 spots. You can do that with display: table-cell and vertical-align: middle on the a (and add line-height: 0 to fix a couple more issue). You can then play further with mixing these groups of styles in the a tag, the .wrapper, or even throwing away the .wrapper if it isn't necessary (it would only be needed - if it is at all - if you're putting text in with it).
Result, with no further tweaks than what I've mentioned here: http://jsfiddle.net/jESsA/38/.
This will work on all decent browsers, and even on IE8/9, but it won't work on IE6/7. A technique for solving this which should work in IE6/7 is this: on the a, set display to block and alter the line-height from 0 to 78px (I'm not entirely clear on why 80px makes it shift down one pixel, but it does; if I thought about it long enough I could probably figure out why), and shift the vertical-align: middle to the img child. Final result: http://jsfiddle.net/jESsA/44/
You can try assigning a vertical-align attribute on the img tag. Vertical align is relative to the line box which means you need to set the line box as tall as the height of the a tag. So these changes are needed in your CSS markup:
#outer_wrapper {
overflow: hidden; /* required when you float everything inside it */
}
.wrapper {
/* display: inline-block is not required */
/* text-align: center is not required -- see below */
float: left; /* float all wrappers left */
}
a {
display: block; /* block display required to make width and height behave as expected */
margin-left: 4px; /* shift the block to make it horizontally centered */
margin-top: 9px; /* shift the block to make it vertically centered */
text-align: center; /* center inline content horizontally */
line-height: 80px; /* line height must be set for next item to work */
}
img {
vertical-align: middle; /* presto */
}
Demo here.
Take a look at this:
http://jsfiddle.net/jESsA/37/
Basically you use float: left to put your boxes inline and a background image instead of an img tag. Because you are using float, you need to clear after to cancel the float effect on other elements.
I changed the DIV tags to A tags so you can have a link on the hole block and keep it simple. But you can keep it as a DIV tag and put an A block inside though (or use JavaScript)
.wrapper {
float: left;
}
http://jsfiddle.net/jESsA/3/
You could check this out: http://www.brunildo.org/test/img_center.html
may be this will help you
http://css.flepstudio.org/en/css-tutorials/centered-vertical-horizontal-align.html
it helped me :)
Example of problem http://img638.imageshack.us/img638/3733/97914817.jpg
I'm trying to recode one of my older forms. It was filled with tables that I want to replace with CSS. However I'm having trouble having text and a form element aligned vertically together. As the picture shows the text defaults to starting at the top instead of in the middle. The blue highlights around the row is dreamweavers interpretation / selection of what is going on.
I have label and input divs, both floated left, inside a div called #light, which is inside a general container. This is what my css code looks like:
#contentBox{
width: 600px;
float: left;
background-color: #e2e2e2;
overflow: auto;
border-color: #c5c5c5;
border-width: 1px;
border-style: solid;
font-size: 12px;
}
#light {
float: left;
width: 500px;
padding: 15px;
background-color: #e2e2e2;
margin: 7px;
border-color: #c5c5c5;
border-width: 1px;
border-style: solid;
vertical-align: middle;
}
input {
float: right;
width: 20em;
}
label {
float: left;
text-align: right;
vertical-align: baseline;
}
Any idea what the problem is? I've tried swapping around the vertical-align in different divs, floating in different directions, getting rid of the label but I just end up with more problems rather than less.
You cannot use vertical-align on elements unless they are table cells (or displayed as such) as this article explains. Set line-height to the element height if you've only got one row of text.
Usually, to solve that problem, I use the line-height property:
Ex:
div{width:600px;font:normal normal 12px/30px Arial, Helvetica, sans-serif;}
This will set the font to 12px, and the line-height to 30px, keeping the font vertically align within the 30px of its line.
Vertical alignment of text can be incredibly annoying or incredibly easy.
If the size of all the involved elements are known, your best bet is to set manual padding/margins on the text itself to make sure it's aligned.
If the content you want to center vertically is dynamic, this is your best bet.
Not sure, but your input tag is set to "float:right", so its height won't be taken into account by the parent. Hence, the height of the parent is actually probably the height of the label (I suspect dreamweaver is not interpreting correctly what browsers do.) Try to remove the float on the input tag and see if it makes a difference.
Vertical alignment can be applied only to inline elements.
The best solution is to modify your HTML and make it like in this examples
You could go for a 'cheap' solution and apply a padding-top to the label divs.