How to vertically align text in a browser-independent way? - css

Context:
I'm trying to use CSS to display playing cards for a game I'm designing on my free time
What I'm trying to do, specifically:
Nothing revolutionary, there's a place on my cards in which I need to write some text, and I want to center the text so that it looks good
What I did:
The relevant part of the HTML is simply this:
<div class = "card_header">
<div class = "card_cost">1</div>
</div>
And the relevant CSS:
.card_header {
position: relative;
top: 110px;
box-sizing: border-box;
width: 100%;
height: 75px;
}
.card_cost {
position: absolute;
top: 50%;
right: 165px;
transform: translateY(-50%);
font-size: 60px;
font-weight: bold;
}
What's the problem:
I expected the card_cost text to be vertically centered between the top and bottom borders of the card_header, but under the browser I was using (Firefox), the text was a bit too high. I tried to fix this by using top: calc(50% + 4px);, which looks like this (a bit better):
Since it felt a bit too tweaky for my taste, I went and checked how it looked like under another browser (Safari) to see whether it looked the same, and it looks like this:
which is the opposite problem: the text is too low.
I've tried adding border: 1px dotted gray; to get a better idea of what's happening, and here's what I see (safari on the left, firefox on the right):
The text seems to be vertically centered within card_cost in Safari (which means it would probably get centered properly if I simply used top: 50%; as I originally did), but in Firefox the box seems to be bigger and text way-high within the box.
What exactly is going on here? Why is this behaving differently depending on the browser? Is there a way to make this render the same? Or, more broadly, is there any browser-independent way for me to make the text vertically centered here?
Edit:
Since someone mentioned line-height in the comments, here's what it looks like when I add line-height: 1; for card_cost (again, Safari on the left and Firefox on the right):
With this, the text doesn't seem as centered as before under Safari, and it's even more clear that the text is way-high under Firefox

I usually take approach with invincible :before on parent with 100% of height and vertical-align: middle;. That way this :before justifies other inline-block content:
// I would apply this style everywhere
.card_header,
.card_header * {
font-family: arial;
box-sizing: border-box;
}
.card_header {
position: relative;
top: 110px;
width: 100%;
height: 75px;
text-align: center;
background-color: rgba(100, 0, 0, .1);
}
.card_header:before {
content: '';
height: 100%;
display: inline-block;
vertical-align: middle;
border-left: 1px solid blue;
}
.card_cost {
display: inline-block;
font-size: 60px;
height: 60px;
font-weight: bold;
vertical-align: middle;
background-color: rgba(0, 0, 100, .1);
}
<div class="card_header">
<div class="card_cost">1</div>
</div>

Related

Remove thin border around pseudo elements/images (only on mobile)

Having a little trouble removing a very thin border that is appearing around our :before and :after elements. This only seems to appear on a mobile device - doesn't even pop up in Chrome's device tools.
Problem:
Here's how the HTML/CSS looks.
.container {
position: relative;
display: flex;
flex-wrap: wrap;
justify-content: center;
list-style: none;
padding: 100px 0px;
margin-bottom: 56px;
width: 100%;
}
container:after {
content: "";
background-image: url("$asset");
background-size: cover;
background-position: bottom;
position: absolute;
left: 0;
top: -15px;
width: 100%;
height: 16px;
border: 0;
outline: 0;
}
<div class="container">
<div class="bg"></div>
<section>
//Headings and Links here
</section>
</div>
I've tried making absolutely sure borders and outlines are set to none - and also adding and taking away a pixel or two from the top and bottom margins, but nothing really seems to work. It's also a bit inconsistent, the lines don't necessarily show on every page that the component is on.
Replace border: 0; with: border: none; very simple CSS Code. Also, the outline code is just for things like text, this has nothing to do with the border.
It's a chrome bug lads. Second answer here nailed it.
The solutions is reducing the height/width to 0 and putting padding in to account for the space instead. Seems to have worked in my case.

Slanted Edge Buttons

I'm trying to build buttons that look like this:
I can accomplish this using :after and CSS triangles, but I can't get that working with variable height elements. Is there any way to accomplish this and keep variable height?
Fiddle: http://jsfiddle.net/AaP47/2/
You could use a skewed div in this case. The only issue here is that as your buttons get taller, due to the skew, they will get slightly wider. This may not be an issue if you are only dealing with 1 or 2 lines. If they get very tall it may cause things to noticeably not line up exactly:
http://jsfiddle.net/AaP47/3/
.button.triangle:after {
content: "";
background-color: red;
display: block;
height: 100%;
position: absolute;
right: -30px;
top: 0;
width: 60px;
transform: skewX(-10deg);
}
This is also not completely scalable. You would need to decide on the largest height you have to support and adjust accordingly. The taller you need to support, the wider the skewed div must be.
Result (without the red): http://jsfiddle.net/AaP47/4/
Just because I had fun tinkering in a different direction and to offer an option concept even though you apparently already got an answer;
a {
padding-right: 20px;
padding-left: 20px;
text-decoration: none;
color: white;
font-weight: bold;
display: inline-block;
border-right: 30px solid transparent;
border-top: 50px solid #4c4c4c;
height: 0;
line-height: 20px;
}
a p {margin-top: -45px;}
and;
<a href="#">
<p>this is a triangle button<br/>
with multiple lines!</p>
</a>
jfiddle: http://jsfiddle.net/AaP47/6/
Cheers!

Tooltips using only CSS

I am trying to make a tooltip for an anchor tag using only CSS. I have come this far. I am trying to achieve the functionality of having the box and the tip arrow positioned exactly at the center no matter what the length of the text is.
The above image is what I am trying to get at.
I've tried keeping the width:auto but it's not working either.
body
{overflow-x:hidden;}
div
{position:relative;width:700px;border:1px red solid;padding:20px;margin:0 auto;text-align:justify;}
a
{position:relative;white-space:nowrap;}
a > span.tooltip
{
position: absolute;
white-space: normal;
width: 100%;
top: 130%;
left: 0;
}
a > span.tooltip > span
{
position: absolute;
top: 0;
right: 0;
text-align: center;
bottom: 0;
left: -500%;
width: 1100%;
}
a > span.tooltip > span > span
{
display: inline-block;
background: black;
border-radius: 4px;
padding: 10px;
color: white;
max-width: 300px;
}
DEMO:
http://jsfiddle.net/b2Yqf/
works on msie 7 8 9 10, firefox, chrome
not what you might want... since markup is made with three nested <span>s... but YES. it could be done!
The main problem you're facing is that you need a white-space: nowrap this gets you about as far as hint.css by #robooneus. I can't figure out the centering either though. Any widths or margins are relative to the "Tooltip" link's width. A link to where you found the images might be helpful too so we can study the source.
EDIT1:
Additionally, a margin-left: -6px on the arrow (the :before) centers that on the word tooltip, it counteracts the move to the right by the border.
I don't think what you are trying to do (center the tooltip) is possible while having width:auto;.
If you declare a width, you can simple position the tooltip with:
.tooltip:hover:after {
width:100px; /* whatever you want */
left:50%;
margin-left:-50px; /* half the width */
}
EDIT
As #Alexander says in his answer, also repositioning your tooltip arrow using margin-left is a good idea, as it is slightly off center with just left:50%.

Why does Firefox interpret top offset differently from Chrome, Safari and IE?

Take the following example:
This is a textarea, with a background image (the grey bar) and a relative positioned div after the textarea with a top offset to move the text in place.
The Markup:
<textarea cols="40" rows="6" class="some_textarea">Hello</textarea>
<div class="message_text">This is a message</div>
The CSS:
.some_textarea {
background: transparent url(gray_bar.png) repeat-x 50% 100%;
width: 99%;
padding: 5px;
margin: 0;
font-family: Arial,Helvetica,sans-serif;
font-size: 13px;
border: 1px solid #C3C3C3;
}
.message_text {
display: inline;
color: #999;
font-size: 10px;
position: relative;
top: -21px;
padding: 0 6px;
}
The problem is that Firefox is the only browser that doesn't agree with the offset, and results in this very small pixel pushing annoyance:
What is causing this? How can I fix this for consistency? What non-clunky workarounds exist if it can't be fixed?
UPDATE
http://jsfiddle.net/UnsungHero97/maHkr/7/
How about something like this...
http://jsfiddle.net/UnsungHero97/maHkr/2/
What I did was wrap your textarea/message combo in a relatively positioned div and then absolutely positioned the message to the bottom left. You can play round with the exact positioning/margins/paddings to get it looking good across the browsers.
I hope this helps.
Hristo
use jQuery(window).load() instead of jQuery(document).ready()

How can I make a fieldset legend-style "background line" on heading text?

I'm attempting to style heading text similar to how your default legend text appears in fieldsets; that is to say, I'd like a strikethrough-like line to come up to, but not through, the text. I can't seem to find any information on how I might accomplish this, and since on numerous other questions Google's always directed me to Stack Overflow for answers, I thought someone here may be able to give me advice.
For greater clarity. I'm attempting to get this effect on header text:
Centered Header Text
Is there any way to do this?
See: http://jsfiddle.net/thirtydot/jm4VQ/
If the text needs to wrap, this won't work. In IE7, there will be no line.
HTML:
<h2><span>Centered Header Text</span></h2>
CSS:
h2 {
text-align: center;
display: table;
width: 100%;
}
h2 > span, h2:before, h2:after {
display: table-cell;
}
h2:before, h2:after {
background: url(http://dummyimage.com/2x1/f0f/fff&text=+) repeat-x center;
width: 50%;
content: ' ';
}
h2 > span {
white-space: nowrap;
padding: 0 9px;
}
Edit:
<h2><strike> </strike>Your Text Here<strike> </strike></h2>
Here's how you can do it with a few simple tags and non-breaking spaces.
I'd use an image and call it a day, but this seemed to work for me:
CSS
fieldset {
border-right: 0px;
border-left: 0px;
border-bottom: 0px;
width: 200px;
}
legend {
margin: 0 25%;
}
HTML
<fieldset>
<legend>My Text Here</legend>
</fieldset>
That's the only way I could figure out how to do it with css. Note the width is fixed. Once again I wouldn't do this myself.
I came up with a quick, image-less solution that seems to work pretty well in IE 8+ and other browsers, whilst gracefully degrading in IE 6/7:
<h1>CSS 2.1 EXAMPLE</h1>
h1 { position: relative; text-align: center; }
h1:first-line { background-color: white; }
h1:before {
position: absolute;
z-index: -1;
content: '';
left: 0px;
right: 0px;
height: 1px;
top: 50%;
background-color: black;
}
It does come with the following limitations, though:
The text must match the overall background colour exactly, otherwise it will look weird.
If you want any kind of padding on the text, you need to use non-breaking spaces at either side of the text (see demo).
Heading text must always be on one line (works best if fixed width).
Here's a demo: http://jsfiddle.net/AndyE/3tFQJ/​
With flexbox being supported by all the latest browsers out there, and it being five years since the IE8 requirement was mentioned by the author, I wanted to have some fun building a new solution using that.
A variety of examples getting more complicated:
https://jsfiddle.net/0mL79b4h/1/
https://jsfiddle.net/0mL79b4h/2/
CSS
div {
display: flex;
align-items: center;
}
div:before,
div:after {
border: 1px solid #000000;
border-radius: 2px;
height: 2px;
display: block;
content: "";
flex: 1;
width: 100%;
}
h1 {
text-align: center;
margin: 8px;
}
HTML
<div>
<h1>Example Text</h1>
</div>
<div>
<h1>Multi-Line<br>Example Text</h1>
</div>
Pros:
Uses flexbox!
Super simple HTML.
Left and right sides can be adjusted for asymmetry.
Zero background issues, no inheriting colors, etc.
Fluid width.
Multi-Line support.
Left/Center/Right/Custom Alignment: Just adjust the flex property separately for the before and after elements, higher numbers will dedicate more space to that side. Remove one entirely to left or right align it.
Interesting effects by playing with the border style (I actually chose a round border in this example). Set height to 0px and use border-top instead for a generic line.
Cons:
Uses flexbox. Call me lazy, but I didn't build in any backward compatibility in this example so it'll look odd on a browser that supports psuedo elements but doesn't support flexbox, although last I checked that was Chrome (Firefox, etc), which are all automatically updated anyway. Might want to use some Modernizr.
Here is what I am using on a client's site: http://jsfiddle.net/TPgE4/
Pros:
No images needed - renders instantly
Uses padding to control space on both sides of text
Text can be center aligned, or left/right aligned — just add, e.g., margin-left: 8px or margin-right: 8px on h2 span style definition to make it look good
Cons:
Requires use of additional tag such as <span>...</span> inside heading tag
Text must fit on one line for good appearance
Background color on <span> element must match surrounding background color, so if you have a non-solid background image, gradient or pattern it won't match perfectly
Kind of late to the party, but this is my solution: https://jsfiddle.net/g43pt908/
Requires no images, and doesn't depend on a background color.
HTML
<div class="hr-text">
<span>Some text</span>
</div>
CSS
.hr-text {
border-top: 1px solid #999;
text-align: center;
background-color: inherit;
}
.hr-text span {
display: inline-block;
position: relative;
height: 14px;
top: -12px;
font-size: 14px;
font-style: italic;
color: #666;
background-color: inherit;
padding: 0 10px;
}
I'm not sure if this would suit your need...
h1:before, h1:after {
content: " ------------- ";
}
This doesn't feel like a very good answer, but I'm posting it anyway.
See: http://jsfiddle.net/rFmQg/
<h2><span>Centered Header Text</span></h2>
h2 {
background: url(http://dummyimage.com/2x1/f0f/fff&text=+) repeat-x center;
text-align: center
}
h2 span {
background: #fff;
padding: 0 9px
}
I don't like it because:
You have to use an image.
This. (it only works if the backgrounds match)
body { padding-top: 100px; }
div.parent {
text-align: center;
border-top: 1px solid #ccc;
}
div.parent div {
display: inline-block;
margin-top: -0.8em;
padding: 0 0.5em;
background: #fff;
}
<body>
<div class="parent">
<div>My Text Here</div>
</div>
</body>
This is a fluid-width solution that matches your design and should be ok in IE7 (though I'll admit I didn't check). There are a couple of downsides:
You lose the fieldset/legend semantics.
You can't put a transparent background on the text.
If you don't need it to be fluid-width, onteria_'s solution is probably your best bet.

Resources