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.
Related
This question already has answers here:
How to make an element width: 100% minus padding?
(15 answers)
Closed 1 year ago.
Now im having an input text element which be warpped by a div container (form-group)
And i set the width to the input text element become 100% (width: 100%). And i expect that the input text it will cover the entire width of the form-group div element. And the result is kinda weird to me. The input text, it likes it flow out of the form-group element, like the this picture here:
In this picture, im currently hover the form-group element, and you can see the orange part, is the margin of the it, but you can see, the input text element, the part i highlighed is like overlaying the margin of the form-group element, which proved that the input text element is flow out of the container element of it, which is the form-group element. And that's weird, at least to me, because I set the width to 100%, and so i think it should be cover the container element of it. Please help me to understand this.
I know i can use the overflow property to fix but, i want to know why this is happening, so hopefully, someone can help me with this, thank you so much.
.form-container {
background-color: black;
padding: 20px;
}
.form-group {
width: 50%;
font-size: 1.5rem;
background-color: red;
margin: 3rem auto;
display: block;
}
input {
padding: 1.5rem 2rem;
border-radius: 2px;
border: none;
outline: none;
width: 100%;
color: var(--primary-color);
}
<form action="#" class="form-container">
<div class="form-group">
<input type="text" placeholder="Enter text...">
</div>
</form>
This happens because by default the box-sizing property is content-box.
When you add padding to the input element, the input element size remains equal to the size of form-group div.
But, this increases the overall width of the input element and extends it outside as the padding adds up to the total width. It looks like the actual width of the input element has increased but actually just the padding is adding.
You can change this if you wish to, by changing the box-sizing to border-box. This way the padding gets added to the input element by compromising the actual size of the input element.
input {
box-sizing: border-box;
padding: 1.5rem 2rem;
border-radius: 2px;
border: none;
outline: none;
width: 100%;
color: var(--primary-color);
}
Also, after adding border-box, you can try adding some height to the form-group div to visualize their comparative heights.
Use this developer tool on your browser to help you see the width, padding and margins.
You are coming up against box-sizing.
The input has quite a noticeable padding added to it (3rem horizontally in all). While the basic element takes up the width of its parent on the width: 100% setting, the box-sizing is set to content by default in CSS. This means any padding (and borders) is outside the basic size.
Changing the box-sizing to border-box for the input means that the padding is included within the overall size so you get the width you expect - in total 100% of the parent:
input {
padding: 1.5rem 2rem;
border-radius: 2px;
border: none;
outline: none;
width: 100%;
color: var(--primary-color);
box-sizing: border-box; /* ADD THIS */
}
In html every elements have default padding and margin property..we overlapped this values.
use following code..to avoid these kind of issues.
* {
padding: 0px;
margin:0px;
box-sizing:border-box;
}
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 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.
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>
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.