Vertical alignment of text in container: WebKit vs Firefox - css

The problem is that Firefox and WebKit based browsers seem to align text vertically in different ways when contained in an element that has an even height/line-height and the font-size is uneven (or vice versa). I have looked at some similar threads, but I haven't really seen any great explanations for my question.
Consider the following example:
.box {
font-size: 15px;
font-family: Helvetica, Arial;
background-color: Blue;
height: 20px;
width: 60px;
color: White;
line-height: 20px;
}
<div class="box">
A text.
</div>
Is there any way to fix this? Is there any "text-align" property or something that I missed?

This is due to differences in how browsers handle subpixel text positioning. If your line-height is 20 pixels but font-size is 15 pixels, then the text needs to be positioned 2.5 pixels from the top of the line box. Gecko actually does that (and then antialiases or snaps to the pixel grid as needed on painting). WebKit just rounds positions to integer pixels during layout. In some cases, the two approaches give answers that differ by a pixel. Unless you're comparing them side-by-side, how can you even tell there's a difference?
In any case, making sure that your half-leading is an integer (i.e. that line-height minus font-size is even) will make the rendering more consistent if you really need that.

This is browser rendering issue. Use line-height 1px less than the given height, for example:
.box
{
background-color: Blue;
color: White;
font-family: Helvetica,Arial;
font-size: 15px;
height: 18px;
line-height: 17px;
width: 60px;
}

If you are looking for a way to do an exact vertical align, check out Stack Overflow question Problem with vertical-align: middle; - I described a solution there.
If you want an answer why Firebug and Chrome display this differently, this will be a bit more complicated. Line-height alignment is based on font-line rendering and fonts can be handled in a very different way across the browsers. For example, font-smoothing and font-weight can really mess with your page.
Also, are you using CSS reset for this page? It contains font related adjustments as well, and it may help you to overcome cross-browser issues. Refer to CSS Tools: Reset CSS.

Ugh, terrible but true! I just ran into this trying to create tiny count bubbles on an icon - so small that I had to get right next to text so every pixel counted. Making the line-height 1x less than text-size leveled the display field between FF and Chrome.

Related

Elements aren't displaying correctly using VW

I'm trying to position elements in a way so that when the browser width is changed, the webpage will scale everything in proportion, but what happens is that they shift a little. I don't understand why. I can adjust this okay using media queries, but they change drastically in mobile browsers. To illustrate what I'm talking about, I created an example in which I'm trying to keep this black text centered inside this green box. From my example, you'll see that scaling the browser on a desktop will keep the text in the box centered pretty well, but when switching to a mobile browser, the text will go out of the box. What can I do to keep it scaling correctly?
I realize that I can just fill the text div with a green background, but you have to understand that this is just an example of what I'm trying to do. The real webpage is much more sophisticated, so that will not be an option. I need to make sure that these divs scale appropriately. Thank you.
I provided an image to show the problem that I'm getting in my phone browser. It's a bit small, but you can see how the black text dips below the green box.
The example website: http://www.marifysworld.com
CSS:
#viewport {
width: device-width;
zoom: 1.0}
#-ms-viewport {
width: device-width}
body {
margin: 0px;
padding: 0px;
background-color: #fffff}
img {
display: block;
margin: 0px;
padding: 0px}
.text {
font-size: 2.25vw;
color: #000000;
text-align: center;
text-size-adjust: 90%}
.box {
width: 23.75%;
height: auto;
position: absolute;
left: 25%;
top: 40vw}
.divtext {
width: 20%;
height: auto;
position: absolute;
left: 26.75%;
top: 42.5vw}
HTML:
<img class="box" src="http://www.marifysworld.com/images/platform/box.jpg" />
<div class="divtext text">
Why won't this div of text stay in the center of the block in mobile browsers?
</div>
Well, you are using positions for your design but it is confusing and not possible.
Here is an idea to make this design work.
Just try it...
HTML:
<div class="box">
<div class="divtext text">
Why won't this div of text stay in the center of the block in mobile browsers?
</div>
</div>
CSS:
#viewport {
width: device-width;
zoom: 1.0}
#-ms-viewport {
width: device-width}
body {
margin: 0px;
padding: 0px;
background-color: #fffff;
}
.box{
background: url('http://www.marifysworld.com/images/platform/box.jpg');
width: 23.75%;
margin: auto;
margin-top: 20%;
}
.divtext {
width: 90%;
padding: 5% 0;
margin: auto;
}
.text {
font-size: 2.25vw;
color: #000000;
text-align: center;
}
Update: initially I thought the problem might be the (not universally supported) text-size-adjust property, but it seems this is unlikely. I leave those thoughts below just in case they are useful to someone else using that property.
Having been unable to reproduce the problem myself but seeing the useful image now put into the question I think we have to look at the actual font and how it is sized and using space. There are quite a few factors which maybe the browsers are setting different defaults for. Here's a few, there may well be more:
font-family - most obvious but is whichever browser is causing the problem using the same default font as browsers not causing the problem? Try setting a specific font and see what happens
Different fonts will take different widths for different characters. Try a monospace font - that will probably overflow - just to demonstrate the issue
kerning - no I don't fully understand how different fonts use it and what they mean by 'normal' (which is probably the browser's default) but that will also alter the space used as will...
..line height - perhaps that needs to be specifically set
font-weight will alter the space used - do all browsers/systems interpret say 400 exactly the same way
I guess there's loads more that may differ between browsers - for example how exactly do they calculate the spacing needed to center text, will they always break a line at the same place etc.
Sorry this is a waffle, but there are so many factors that could make the text overflow and I don't understand them all in enough depth.
Basically what you need is to be able to scale the text div to force it to fit - for that you would need a bit of JS I think (?or is there an equivalent of contain for divs?)
ORIGINAL STUFF:
I am seeing text stay within the green box on a mobile device (IOS Safari) so I imagine the problem you are having is with another mobile device/browser such as Android.
If this is case the area to look at is the use of the CSS property
text-size-adjust: 90%
There are a couple of things to note here:
According to MDN
This is an experimental technology. Check ... carefully before using in production.
This property is intended to be used in the case where a website has not been designed with smaller devices/viewports in mind.
According to MDN, while Chrome on Android implements text-size-adjust fully, Firefox on Android and Safari on IOS do not support the percentage version.
I may be missing something but the question explicitly states that 'the webpage will scale everything in proportion'. Apart from possible inbuilt browser margin and padding on the div, everything is expressed as vw or % so I cannot see anything else that would have an adverse affect on the text positioning.
I also cannot see why this property is being used. It may or may not be causing the problem, but it certainly may affect how text is displayed on some browsers and it seems to be, at best, redundant for a site that is designed with proportionality in mind from the start.

Why text-align:justify doesn't work with child block element [duplicate]

A few other questions have already addressed how best to apply text-align: justify to get inline-block elements to spread out evenly… for example, How do I *really* justify a horizontal menu in HTML+CSS?
However, the 100% width element that "clears" the line of inline-block elements is given its own line by the browser. I can't figure out how to get rid of that empty vertical space without using line-height: 0; on the parent element.
For an example of the problem, see this fiddle
For my solution that uses line-height: 0;, see this fiddle
The solution I'm using requires that a new line-height be applied to the child elements, but any previously set line-height is lost. Is anyone aware of a better solution? I want to avoid tables so that the elements can wrap when necessary, and also flexbox because the browser support isn't there yet. I also want to avoid floats because the number of elements being spaced out will be arbitrary.
Updated the "Future" solution info below; still not yet fully supported.
Present Workaround (IE8+, FF, Chrome Tested)
See this fiddle.
Relevant CSS
.prevNext {
text-align: justify;
}
.prevNext a {
display: inline-block;
position: relative;
top: 1.2em; /* your line-height */
}
.prevNext:before{
content: '';
display: block;
width: 100%;
margin-bottom: -1.2em; /* your line-height */
}
.prevNext:after {
content: '';
display: inline-block;
width: 100%;
}
Explanation
The display: block on the :before element with the negative bottom margin pulls the lines of text up one line height which eliminates the extra line, but displaces the text. Then with the position: relative on the inline-block elements the displacement is counteracted, but without adding the additional line back.
Though css cannot directly access a line-height "unit" per se, the use of em in the margin-bottom and top settings easily accommodates any line-height given as one of the multiplier values. So 1.2, 120%, or 1.2em are all equal in calculation with respect to line-height, which makes the use of em a good choice here, as even if line-height: 1.2 is set, then 1.2em for margin-bottom and top will match. Good coding to normalize the look of a site means at some point line-height should be defined explicitly, so if any of the multiplier methods are used, then the equivalent em unit will give the same value as the line-height. And if line-height is set to a non-em length, such as px, that instead could be set.
Definitely having a variable or mixin using a css preprocessor such as LESS or SCSS could help keep these values matching the appropriate line-height, or javascript could be used to dynamically read such, but really, the line-height should be known in the context of where this is being used, and the appropriate settings here made.
UPDATE for minified text (no spaces) issue
Kubi's comment noted that a minification of the html that removes the spaces between the <a> elements causes the justification to fail. A pseudo-space within the <a> tag does not help (but that is expected, as the space is happening inside the inline-block element), a <wbr> added between the <a> tags does not help (probably because a break is not necessary to the next line), so if minification is desired, then the solution is a hard coded non-breaking space character --other space characters like thin space and en space did not work (surprisingly).
Nearing a Future Clean Solution
A solution in which webkit was behind the times (as of first writing this) was:
.prevNext {
text-align: justify;
-moz-text-align-last: justify;
-webkit-text-align-last: justify; /* not implemented yet, and will not be */
text-align-last: justify; /* IE */
}
It works in FF 12.0+ and IE8+ (buggy in IE7).
For Webkit, as of version 39 (at least, might have crept in earlier) it does support it without the -webkit- extension but only if the user has enabled the experimental features (which can be done at chrome://flags/#enable-experimental-web-platform-features). Rumor is that version 41 or 42 should see full support. Since it is not seamlessly supported by webkit yet, it is still only a partial solution. However, I thought I should post it as it can be useful for some.
Consider the following:
.prevNext {
display: table;
width: 100%
}
.prevNext a {
display: table-cell;
text-align: center
}
​(Also see the edited fiddle.) Is that what you are looking for? The advantage of this technique is that you can add more items and they will all be centered automatically. Supported by all modern Web browsers.
First off, I like the approach of the pseudo-element in order to keep the markup semantic. I think you should stick with the overall approach. It's far better than resorting to tables, unnecessary markup, or over the top scripts to grab the positioning data.
For everyone stressed about text-align being hacky - c'mon! It's better that the html be semantic at the expense of the CSS than vice versa.
So, from my understanding, you're trying to achieve this justified inline-block effect without having to worry about resetting the line-height every time right? I contend that you simply add
.prevNext *{
line-height: 1.2; /* or normal */
}
Then you can go about coding as though nothing happened. Here's Paul Irish's quote about the * selector if you're worried about performance:
"...you are not allowed to care about the performance of * unless you concatenate all your javascript, have it at the bottom, minify your css and js, gzip all your assets, and losslessly compress all your images. If you aren't getting 90+ Page Speed scores, it's way too early to be thinking about selector optimization."
Hope this helps!
-J Cole Morrison
Attempting to text-align for this problem is pretty hackish. The text-align property is meant to align inline content of a block (specifically text) -- it is not meant to align html elements.
I understand that you are trying to avoid floats, but in my opinion floats are the best way to accomplish what you are trying to do.
In your example you have line-height:1.2, without a unit. This may cause issues. If you're not using borders you could give the parent and the children a line-height of 0.
The other options I can think of are:
Use display:table on the parent and display:table-cell on the children to simulate table like behaviour. And you align the first item left, and the last one right. See this fiddle.
Use javascript to do a count of the nav children and then give them a equally distributed width. eg. 4 children, 25% width each. And align the first and last items left and right respectively.
There is a way to evenly distribute the items but is a convoluted method that requires some non breaking spaces to be carefully placed in the html along with a negative margin and text-align:justify. You could try and adapt it the the nav element. See example here.
Your fiddle is awfully specific. It seems to me for your case this CSS would work well:
.prevNext {
border: 1px solid #ccc;
position: relative;
height: 1.5em;
}
.prevNext a {
display: block;
position: absolute;
top: 0;
}
.prevNext a:first-child {
left: 0;
text-align: left;
}
.prevNext a:last-child {
right: 0;
text-align: right;
}
​
As stated by #Scotts, the following has been implemented inside Chrome, without the -webkit part , which I really loved btw, specially since we need to get rid of the -browser-specific-shǐt real soon.
.prevNext {
text-align: justify;
-moz-text-align-last: justify;
-webkit-text-align-last: justify; /* not implemented yet, and will not be */
text-align-last: justify; /* IE + Chrome */
}
Note: Though still the Safari and Opera don't support it yet (08-SEPT-16).
I think the best way would be to create the clickable element with a specific class/id and then assign float:left or float:right accordingly. Hope that helps.

cant remove padding css

I've been helping a friend change the layout of his site (mostly css changes) at the moment I'm just fine tuning it a bit and have run into a problem. To begin with, here is a sample of the site. The problem is the titles for the posts, i want there to be less padding on the top and the bottom so that the background isn't taller than the text when you hover on them. I've tried changing margins, and padding, pretty much tried everything. Increasing the padding works fine but i can't seem to get it less than it is at the moment. I know it should work because it's modelled after the titles in another site. Can anybody see where the problem lies? Thanks
If I'm understanding correctly, you want to change the amount of empty space around the main post title. If so, adjust line-height:
#content .post .title h3 a {
text-align: left;
-webkit-transition: color 0.25s linear;
font-size: 36px;
letter-spacing: -1px;
font-weight: 750;
line-height: 50px; /* Change this */
color: #444444;
text-decoration: none;
padding:0px 0px;
}
Example with line-height (overly) reduced: http://jsfiddle.net/AH9VP/3/
See also: http://www.w3.org/wiki/CSS/Properties/line-height
However...Note that in spite of changing line-height (which definitely reduces spacing), there seems be a limit on how much the browser will constrain the box when you hover on the text. This is (I think) because the browser is allowing space for glyphs at the top/bottom (like the tail of the "y" in "usually").
This topic is somewhat related: https://stackoverflow.com/a/11857786/453277
I know it should work because it's modelled after the titles in
another site.
It would be helpful to see the other site, in case I've missed something.

"text-align: justify;" inline-block elements properly?

A few other questions have already addressed how best to apply text-align: justify to get inline-block elements to spread out evenly… for example, How do I *really* justify a horizontal menu in HTML+CSS?
However, the 100% width element that "clears" the line of inline-block elements is given its own line by the browser. I can't figure out how to get rid of that empty vertical space without using line-height: 0; on the parent element.
For an example of the problem, see this fiddle
For my solution that uses line-height: 0;, see this fiddle
The solution I'm using requires that a new line-height be applied to the child elements, but any previously set line-height is lost. Is anyone aware of a better solution? I want to avoid tables so that the elements can wrap when necessary, and also flexbox because the browser support isn't there yet. I also want to avoid floats because the number of elements being spaced out will be arbitrary.
Updated the "Future" solution info below; still not yet fully supported.
Present Workaround (IE8+, FF, Chrome Tested)
See this fiddle.
Relevant CSS
.prevNext {
text-align: justify;
}
.prevNext a {
display: inline-block;
position: relative;
top: 1.2em; /* your line-height */
}
.prevNext:before{
content: '';
display: block;
width: 100%;
margin-bottom: -1.2em; /* your line-height */
}
.prevNext:after {
content: '';
display: inline-block;
width: 100%;
}
Explanation
The display: block on the :before element with the negative bottom margin pulls the lines of text up one line height which eliminates the extra line, but displaces the text. Then with the position: relative on the inline-block elements the displacement is counteracted, but without adding the additional line back.
Though css cannot directly access a line-height "unit" per se, the use of em in the margin-bottom and top settings easily accommodates any line-height given as one of the multiplier values. So 1.2, 120%, or 1.2em are all equal in calculation with respect to line-height, which makes the use of em a good choice here, as even if line-height: 1.2 is set, then 1.2em for margin-bottom and top will match. Good coding to normalize the look of a site means at some point line-height should be defined explicitly, so if any of the multiplier methods are used, then the equivalent em unit will give the same value as the line-height. And if line-height is set to a non-em length, such as px, that instead could be set.
Definitely having a variable or mixin using a css preprocessor such as LESS or SCSS could help keep these values matching the appropriate line-height, or javascript could be used to dynamically read such, but really, the line-height should be known in the context of where this is being used, and the appropriate settings here made.
UPDATE for minified text (no spaces) issue
Kubi's comment noted that a minification of the html that removes the spaces between the <a> elements causes the justification to fail. A pseudo-space within the <a> tag does not help (but that is expected, as the space is happening inside the inline-block element), a <wbr> added between the <a> tags does not help (probably because a break is not necessary to the next line), so if minification is desired, then the solution is a hard coded non-breaking space character --other space characters like thin space and en space did not work (surprisingly).
Nearing a Future Clean Solution
A solution in which webkit was behind the times (as of first writing this) was:
.prevNext {
text-align: justify;
-moz-text-align-last: justify;
-webkit-text-align-last: justify; /* not implemented yet, and will not be */
text-align-last: justify; /* IE */
}
It works in FF 12.0+ and IE8+ (buggy in IE7).
For Webkit, as of version 39 (at least, might have crept in earlier) it does support it without the -webkit- extension but only if the user has enabled the experimental features (which can be done at chrome://flags/#enable-experimental-web-platform-features). Rumor is that version 41 or 42 should see full support. Since it is not seamlessly supported by webkit yet, it is still only a partial solution. However, I thought I should post it as it can be useful for some.
Consider the following:
.prevNext {
display: table;
width: 100%
}
.prevNext a {
display: table-cell;
text-align: center
}
​(Also see the edited fiddle.) Is that what you are looking for? The advantage of this technique is that you can add more items and they will all be centered automatically. Supported by all modern Web browsers.
First off, I like the approach of the pseudo-element in order to keep the markup semantic. I think you should stick with the overall approach. It's far better than resorting to tables, unnecessary markup, or over the top scripts to grab the positioning data.
For everyone stressed about text-align being hacky - c'mon! It's better that the html be semantic at the expense of the CSS than vice versa.
So, from my understanding, you're trying to achieve this justified inline-block effect without having to worry about resetting the line-height every time right? I contend that you simply add
.prevNext *{
line-height: 1.2; /* or normal */
}
Then you can go about coding as though nothing happened. Here's Paul Irish's quote about the * selector if you're worried about performance:
"...you are not allowed to care about the performance of * unless you concatenate all your javascript, have it at the bottom, minify your css and js, gzip all your assets, and losslessly compress all your images. If you aren't getting 90+ Page Speed scores, it's way too early to be thinking about selector optimization."
Hope this helps!
-J Cole Morrison
Attempting to text-align for this problem is pretty hackish. The text-align property is meant to align inline content of a block (specifically text) -- it is not meant to align html elements.
I understand that you are trying to avoid floats, but in my opinion floats are the best way to accomplish what you are trying to do.
In your example you have line-height:1.2, without a unit. This may cause issues. If you're not using borders you could give the parent and the children a line-height of 0.
The other options I can think of are:
Use display:table on the parent and display:table-cell on the children to simulate table like behaviour. And you align the first item left, and the last one right. See this fiddle.
Use javascript to do a count of the nav children and then give them a equally distributed width. eg. 4 children, 25% width each. And align the first and last items left and right respectively.
There is a way to evenly distribute the items but is a convoluted method that requires some non breaking spaces to be carefully placed in the html along with a negative margin and text-align:justify. You could try and adapt it the the nav element. See example here.
Your fiddle is awfully specific. It seems to me for your case this CSS would work well:
.prevNext {
border: 1px solid #ccc;
position: relative;
height: 1.5em;
}
.prevNext a {
display: block;
position: absolute;
top: 0;
}
.prevNext a:first-child {
left: 0;
text-align: left;
}
.prevNext a:last-child {
right: 0;
text-align: right;
}
​
As stated by #Scotts, the following has been implemented inside Chrome, without the -webkit part , which I really loved btw, specially since we need to get rid of the -browser-specific-shǐt real soon.
.prevNext {
text-align: justify;
-moz-text-align-last: justify;
-webkit-text-align-last: justify; /* not implemented yet, and will not be */
text-align-last: justify; /* IE + Chrome */
}
Note: Though still the Safari and Opera don't support it yet (08-SEPT-16).
I think the best way would be to create the clickable element with a specific class/id and then assign float:left or float:right accordingly. Hope that helps.

Text Alignment w/ IE9 in Standards-Mode

Can someone help me vertically center text inside a div, consistently across browsers. In IE9 ONLY, text is one pixel closer to the top of the parent div. All other browsers render the text as expected.
Important: I'm using standards-mode:
<!DOCTYPE html>
Here's some example HTML:
<!DOCTYPE html>
<div style="width:100px; height:16px; font-size:13px; font-family:Arial; line-height:1.2; background-color:red; color:White; vertical-align:middle">
<div style="line-height:16px">XXXXXXXXXX</div></div>
Bit late to the party. However, I came across a similar issue recently. After some digging about I came across this article: Sub-pixel Fonts in IE9.
I think this is directly responsible for the issues of font vertical alignment in IE9. Unfortunately there doesn't seem to be a fix as this is a forced option or customisable by the user (not likely to happen).
So it looks like the only solution is to increase the line-height as mentioned previously.
You might want to look at the following:
CSS: Standard (dynamic) way to centralize an element in the y-axis
There are some useful references that will probably still apply to IE9.
Based on your code: you are setting the line-height in more than one place. Try removing the line-height:16px property in your inner div, in fact, get rid of the inner div since vertical-align will only affect inline elements.
Also, make sure your container height is big enough to hold the text (1.2*13) otherwise you may get into issues related to different fonts or different default font-sizes across browsers.
Probably what is happening is that 1.2*13 = 15.6, and depending how the browser rounds off floating point numbers, that could account for a 1 pixel shift. Set line-height to 16px instead of 1.2 and see if that works.
Second Try:
.outer {
background-color: red;
color: white;
width: 100px;
height: auto;
padding-top: 0px;
font-family: Arial, sans-serf;
font-size: 13px;
line-height: 5.0;
}
applied to:
<div class="outer">XXXXXXXXXX</div>
If anything will fix this, make the line-height large enough so that there is some space above/below the lettering. Set the container height to auto and let the line-height control the height of the container.
There is an answer to this question here:
http://www.sitepoint.com/forums/css-53/text-alignment-w-ie9-standards-mode-745359.html
I had the same problem with the 1px off text rendering, and it would only appear with font size 13px in IE9.
adding the css style
{
height: 16px;
line-height:16.99px;
}
to the surrounding div fixed the problem for me on IE7-9, FF and Chrome on Windows.

Resources