Vertically centering text within circles created with border-radius - css

Today I was having an awful lot of trouble getting some small text vertically centered within elements that were circle which were created using border-radius.
Some of the elements looked fine, but one in particular (a lowercase e was too close to the bottom); I had 2px of padding and it seemed to look fine; however once viewed on a mobile device it was slightly lower.
Here is some code that is as close of a replica as I could come up with to show the issue; you will notice this text has a similar issue with the lowercase e being too close to the bottom.
HTML:
<div class="option">
<span class="icon">t</span>
<span class="text">123456789</span>
</div>
<div class="option">
<span class="icon">f</span>
<span class="text">123456789</span>
</div>
<div class="option">
<span class="icon">e</span>
<span class="text">moo#moo.com</span>
</div>
CSS:
.option {
margin-bottom: 10px;
font-family: 'Source Sans Pro', sans-serif;
font-size: 14px;
}
.option .icon {
display: inline-block;
text-align: center;
width: 24px;
height: 24px;
line-height: 24px;
color: #fff;
border-radius: 50%;
background-color: blue;
}
.option .text {
padding-left: 10px;
}
JSFiddle: http://jsfiddle.net/7bygsgn1/7/
Whilst I haven't tried them with the particular code on jsfiddle, when I was having the issue today I tried a whole range of centering techniques including:
Using line-height
Using absolute positioning
Using vertical-align: middle; in conjunction with display: table-cell;
Negative Margins
Using the method explained here.
Either it had no affect on the centering or caused the shape of the circle to change.
Is there any way you can reliably vertically center in situations such as this?

You may use an inline-block pseudo-element with an height of 24px / 100% , and vertical-align it to middle.
.option {
margin-bottom: 10px;
font-family: 'Source Sans Pro', sans-serif;
font-size: 14px;
}
.option .icon {
display: inline-block;
text-align: center;
width: 24px;
height: 24px;
color: #fff;
border-radius: 50%;
background-color: blue;
}
/* here the pseudo-element method */
.option .icon:before {
content: '';
display: inline-block;
padding-top: 100%;/* cause here we have a square and width for percentage vertical (padding/margin) is the reference , height:100%; or height:24px; will do as well */
vertical-align: middle;
}
/* end update */
.option .text {
padding-left: 10px;
}
<div class="option">
<span class="icon">t</span>
<span class="text">123456789</span>
</div>
<div class="option">
<span class="icon">f</span>
<span class="text">123456789</span>
</div>
<div class="option">
<span class="icon">e</span>
<span class="text">moo#moo.com</span>
</div>
or display:flex; , the most simple:
.option {
margin-bottom: 10px;
font-family: 'Source Sans Pro', sans-serif;
font-size: 14px;
}
.option .icon {
/* next-three lines to center content both axis */
display: inline-flex;
justify-content:center;
align-items:center;
/*text-align: center;*/
width: 24px;
height: 24px;
color: #fff;
border-radius: 50%;
background-color: blue;
}
.option .text {
padding-left: 10px;
}
<div class="option">
<span class="icon">t</span>
<span class="text">123456789</span>
</div>
<div class="option">
<span class="icon">f</span>
<span class="text">123456789</span>
</div>
<div class="option">
<span class="icon">e</span>
<span class="text">moo#moo.com</span>
</div>

Vertically/Horizontally center anything inside a parent element without knowing the heights/widths of either:
/* This parent can be any width and height */
.parent {
text-align: center;
/* May want to do this if there is risk the container may be narrower than the element inside */
white-space: nowrap;
}
/* The ghost, nudged to maintain perfect centering */
.parent:before {
content: '';
display: inline-block;
height: 100%;
vertical-align: middle;
margin-right: -0.25em; /* Adjusts for spacing */
}
/* The element to be centered, can also be of any width and height */
.centered {
display: inline-block;
vertical-align: middle;
}
Essentially this creates a ghost element inside the parent that allows the child to be positioned relative to it. The height: 100% allows the vertical-align: middle to do its job properly.
Hope this helps!
Edit: Credit to https://css-tricks.com/centering-in-the-unknown/

Related

CSS Flex and transformed text

I am trying to get this kind of effect to display a date
I am using flex and text transform, but am struggling to get it right. I cannot get rid of the extra width to the right of the year.
This is my current result.
Here is my code:
.event {
display: flex;
gap: 20px;
margin-bottom: 5px;
}
.date {
border-radius: 5px;
letter-spacing: 1.2px;
background-color: #f6f5f0;
color: #d8d6c8;
padding: 5px;
}
.date .dayAndMonth {
display: inline-block;
}
.date .month {
text-align: center;
font-size: 13px;
}
.date .day {
text-align: center
}
.date .year {
display: inline-block;
transform-origin: 0 0;
transform: rotate(-90deg);
position: relative;
top: 18px;
}
.event_details {}
<article class="event">
<div class="date">
<div class="dayAndMonth">
<div class="month">Feb</div>
<div class="day">04</div>
</div>
<div class="year">2022</div>
</div>
<div class="event_details">
<div class="title">Event Title</div>
</div>
</article>
I would recommend to use writing-mode: vertical-lr; for more details
.event {
display: flex;
gap: 20px;
margin-bottom: 5px;
}
.date {
border-radius: 5px;
letter-spacing: 1.2px;
background-color: #f6f5f0;
color: #d8d6c8;
padding: 5px;
/*Added css*/
display: flex;
align-items: center;
}
.date .dayAndMonth {
display: inline-block;
}
.date .month {
text-align: center;
font-size: 13px;
}
.date .day {
text-align: center;
}
.date .year {
display: inline-block;
writing-mode: vertical-lr; // use this css
position: relative;
}
.event_details {}
<article class="event">
<div class="date">
<div class="dayAndMonth">
<div class="month">Feb</div>
<div class="day">04</div>
</div>
<div class="year">2022</div>
</div>
<div class="event_details">
<div class="title">Event Title</div>
</div>
</article>
It's because of position relative that anchors .year in the .date container. It will still take space there as it is relative to that position making the container adjust it's dimension to accommodate the .year. There're two ways that I can think of. First, is fix the dimensions of .date: height and width then reposition the right and top of the .year. Or you could just use position: absolute; on .year, just set the parent container's width: 50; and adjust the top property to reposition. See the snippet below:
*{
box-sizing: border-box;
margin: 0;
padding: 0;
}
.event {
display: flex;
gap: 20px;
margin-bottom: 5px;
padding: 1rem;
}
.date {
border-radius: 5px;
letter-spacing: 1.2px;
background-color: #f6f5f0;
color: #d8d6c8;
padding: 5px;
width: 50px;
}
.date .dayAndMonth {
display: inline-block;
}
.date .month {
text-align: center;
font-size: 13px;
}
.date .day {
text-align: center
}
.date .year {
display: inline-block;
transform-origin: 0 0;
transform: rotate(-90deg);
position: absolute;
top: 55px;
}
.event_details {}
<article class="event">
<div class="date">
<div class="dayAndMonth">
<div class="month">Feb</div>
<div class="day">04</div>
</div>
<div class="year">2022</div>
</div>
<div class="event_details">
<div class="title">Event Title</div>
</div>
</article>
More on positions here.
Solution
Add a value for width to .year in your CSS. That is
.date .year {
/* ... (other styles) */
width: 20px; /* newly added value for width */
}
Explanation
On rendering your HTML/CSS code, the browser kind of calculates the widths of elements. At this point, the width of the .year div (containing 2022) has been set. After the rotation is rendered, the width was still retained hence the extra space at the right.
So explicitly setting the width removes the extra space to the right of the vertical 2022.
Note
You may want to set the font sizes of .month, .day, and .year to be sure that their values are not distorted or superimposed on each other when your page is rendered in a browser where the user has scaled up font sizes.

How to vertically align lower case text in mobile safari?

With a div that has
height: 15px;
line-height: 15px;
I get these results:
what css can I use to make it v-align the text to middle regardless of its case?
You can also use table-cell display, which is compatible in most of the browsers versions.
You then just need to use text-align and vertical-align to make it perfectly centered.
body, html {
height: 100%;
}
body {
margin: 3rem;
}
span {
background-color: #4900CE;
color: white;
border-radius: 500px;
padding: 1rem;
min-width: 2.5rem;
text-align: center;
display: table-cell;
vertical-align: middle;
}
<span>ONE</span>
<br>
<span>one</span>
I've went ahead and tested this code in most of the iOS browsers with Browserstack. You can find all the results here (some of their hosts are broken, thus the white shots).
You can alternatively use flexbox with something like
span {
display: flex;
justify-content: center;
align-items: center;
}
I think your best bet would to be to work with em and ex here.
I have noticed that uppercase letters seem to be vertically centered by default. Most of the time, they have a height of around two thirds of 1em, while the height of lowercase letters is almost always exactly 1ex.
Knowing these things, you can give the lowercase letters an offset of calc(((-1em / 1.5) + 1ex) / 2), this moves the text up with half the size of the uppercase letters, and down half the size of the lowercase letters.
To be able to do this, you'll have to do some padding trickery, or simply wrap the text into another element, like a span.
Check out this Fiddle
html, body { height: 100% } *, ::before, ::after { position: relative }
.flex {
display: flex;
align-items: center;
justify-content: center;
}
.flex.sans {
font-family: sans-serif;
}
.flex div {
font-size: 17vh;
background-color: #40C;
color: white;
border-radius: 1000px;
padding: .5em 1em;
margin: .25em;
}
#media (max-width: 200vh) { .flex div { font-size: 8.5vw } }
.flex div::after {
content: '';
display: block;
position: absolute;
top: calc(50% - .5px);
left: 0;
right: 0;
height: 1px;
background-color: #FFF;
}
.flex.centered div:last-child span {
top: calc(((-1em / 1.5) + 1ex) / 2);
}
<div class="flex">
Not centered<div><span>ONE</span></div><div><span>one</span></div>
</div>
<div class="flex centered">
Centered<div><span>ONE</span></div><div><span>one</span></div>
</div>
<div class="flex sans">
Not centered<div><span>ONE</span></div><div><span>one</span></div>
</div>
<div class="flex centered sans">
Centered<div><span>ONE</span></div><div><span>one</span></div>
</div>
There's a big chance this will work right away. If it doesn't, you can try changing 1.5 to some other value like 1.4 or 1.75.
See below example:
.capsule{
border-radius:30px;
height:30px;
background:blue;
position: relative;
display:inline-block;
padding:0 15px;
text-align:center;
color:#fff;
font-family:Arial;
}
.capsule>span{
position:absolute;
width:100%;
left:0;
top:50%;
transform: translateY(-50%);
-webkit-transform: translateY(-50%);
-moz-transform: translateY(-50%);
}
.capsule > i {
opacity:0;
}
<div class="capsule">
<span> ONE </span>
<i> ONE </i>
</div>
<hr/>
<div class="capsule">
<span> one </span>
<i> one </i>
</div>
<hr/>
<div class="capsule">
<span> TWO </span>
<i> TWO </i>
</div>
<hr/>
<div class="capsule">
<span> two </span>
<i> two </i>
</div>
This will work on all browsers except IE 8. You can see working example here.
What if your word would have ascenders ( the part of the letters going higher to the letter x like ftlkidhjb ) or descender (like jyqp) then the text will poke out of the edges of your button. That's why it seems not centered. The only solution to make it feel centered is to make the button as high as 2 or 3 times the line height.
You can use flex:
.badge {
width: 100px;
height: 50px;
border-radius: 50px;
background: blue;
color: white;
display: flex;
display: -webkit-flex; /* Safari prefix */
justify-content: center;
-webkit-justify-content: center; /* Safari prefix */
flex-direction: column;
-webkit-flex-direction: column; /* Safari prefix */
font-family: Arial;
font-size: 14px;
text-align: center;
}
.badge.large {
font-size: 24px;
}
<p>Large badge:</p>
<div class="badge large">
ONE
</div>
<p>Normal badge:</p>
<div class="badge">
two
</div>
JSFiddle
Here is the solution. The problem is basically font Vertical Metrics which is actually issue.
I recommend use google font if you can if not than,
Go to http://www.fontsquirrel.com/tools/webfont-generator
Note: Do not use blacklisted font. If you want, go for license.
Upload the font you want to use;
choose “EXPERT…”
Select EOT Lite if you require IE support;
In Rendering section, check “Fix Vertical Metrics”; (This is Important)
This will fix Vertical Metrics which will fix your line-height issue.
CSS Recommendation:
Use default body line-height 1.4 or 1.42857143 do not relay on line-height: normal because different browser has different default value.
To make lower case text aligned you have to offset it manually to compensate for the extra height that would have to be occupied by upper case text, but that would make uppercase text misaligned. You can make your divs look inline or inline-flex and then you can simply force all text in these badges to be uppercase:
.up div {
height: 15px;
line-height: 15px;
background-color: blue;
color: white;
border-radius: 500px;
padding: 0.3em 0.7em;
display: inline;
font-family: arial;
text-transform: uppercase;
}
<div class="up">
<div>ONE</div> <div>One</div> <div>one</div>
</div>
Or lowercase+offset:
.low div {
height: 15px;
line-height: 15px;
background-color: blue;
color: white;
border-radius: 500px;
padding: 0.2em 0.7em 0.4em 0.7em;
display: inline;
font-family: arial;
text-transform: lowercase;
}
<div class="low">
<div>ONE</div> <div>One</div> <div>one</div>
</div>
Here's the output on iPhone 5:

text background new line padding issue

I am dealing with text blocks (background blocks over text) and face some issues with paddings on new line. The problem occurs when the browser(e.g. mobile) cuts the text into to two lines due to lack of width. text then looks like this:
I don't really know how to set a padding css on the end of the new lines, since it could break up anywhere of the sentence. You could say put a span on it with padding, but it is not fixed where the line will break down. It depends on the width. Any recommendations?
You could apply display: inline-block but that will turn the background color into an ugly box which doesn't look as nice as having an exact width background for each line. Unfortunately CSS doesn't let us target individual lines except for the first one.
If you don't mind getting a little "creative" (or hacky) you could wrap each word in its own element in the backend or using JavaScript and apply the background color to those elements. Adjust the parent's word-spacing accordingly to eliminate gaps.
.main {
font-family: sans-serif;
font-weight: bold;
background-color: #99c;
display: flex;
height: 400px;
flex-direction: row;
align-items: center;
}
.text-container {
max-width: 500px;
display: inline-block;
word-spacing: -15px;
position: relative;
padding-left: 20px;
overflow: hidden;
}
.text-container::before {
content: '';
background-color: black;
position: absolute;
top: 0;
left: 0;
width: 20px;
height: 100%;
z-index: 1;
}
span {
font-size: 36px;
line-height: 1.5em;
color: white;
background-color: black;
padding: 0.25em 0.5em 0.25em 0;
max-width: 360px;
}
<div class="main">
<div class="text-container">
<span>A</span> <span>Movie</span> <span>in</span> <span>the</span> <span>park:</span> <span>Kung</span> <span>Fu</span> <span>Panda</span>
</div>
</div>
You can use box-shadow for this issue and display inline:
<div class="text">
<span class="text-container">A Movie in the park: Kung Fu Panda</span>
</div>
And css:
.text > span {
display: inline;
box-shadow: 25px 0 0 black, -10px 0 0 black;
background-color: black;
color: white;
}
Try to add after "Park:" and before "Kung"
padding workded!!!
change width by console browser and see result:
h1{
background-color: #ff6a6a;
padding: 33px;
display: inline-block;
word-wrap: break-word;
width:300px
}
<h1>rert ert erttttttttttttttt 00000000000000000000 dfgdfgd dfgdfgdft ertert </h1>
Use <p> tag to wrap up the text and it apparently works demo
<div class="main">
<div class="text-container">
<p id="test">A Movie in the park: Kung Fu Panda</p>
</div>
</div>
css
.main {
font-family: sans-serif;
font-weight: bold;
background-color: #99c;
display: flex;
height: 400px;
flex-direction: row;
align-items: center;
}
.text-container {
max-width: 400px;
}
p {
font-size: 36px;
line-height: 2em;
color: white;
background-color: black;
padding: 0.5em;
max-width: 360px;
}

How to vertical align this span element?

This should be very simple, and apologies if it's a duplicate. I can't get some text in a span to vertically align beside an icon.
Example:
.box {
width: 100px;
text-align: center;
background-color: #f0f0f0;
margin: 50px auto;
padding: 20px;
font-family: sans-serif;
cursor: pointer;
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" />
<div class="box">
<a>
<span>Search</span>
<i class="fa fa-search fa-2x" aria-hidden="true"></i>
</a>
</div>
CSS I've tried:
Setting the span to display: inline-block and assigning padding and margin. This also moves the icon up.
Setting the link to position: relative and positioning the span. This causes the icon to move, as the span is now taken out of the flow.
Adjusting the line-height of the span. Again, this affects the icon.
Floating the span. This doesn't work.
Is there something I'm missing? I'm not very familiar with flex, would that be a solution? (Note I have to support very old browsers...)
Suggestions much appreciated!
Add following css:
.box a i,
.box a span {
display: inline-block;
vertical-align: middle;
}
.box {
width: 100px;
text-align: center;
background-color: #f0f0f0;
margin: 50px auto;
padding: 20px;
font-family: sans-serif;
cursor: pointer;
}
.box a i,
.box a span {
display: inline-block;
vertical-align: middle;
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" />
<div class="box">
<a>
<span>Search</span>
<i class="fa fa-search fa-2x" aria-hidden="true"></i>
</a>
</div>
Give the <i> an id (or class, I named it #k), then add this ruleset:
#k { vertical-align: middle; }
.box {
width: 100px;
text-align: center;
background-color: #f0f0f0;
margin: 50px auto;
padding: 20px;
font-family: sans-serif;
cursor: pointer;
}
#k {
vertical-align: middle;
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" />
<div class="box">
<a href='#/'>
<span>Search</span>
<i id='k' class="fa fa-search fa-2x" aria-hidden="true"></i>
</a>
</div>
Use CSS Flexbox. Apply display: flex property to .box a and use align-items: center (this will align your items vertically centered).
Have a look at the snippet below:
.box {
width: 30%;
text-align: center;
background-color: #f0f0f0;
margin: 50px auto;
padding: 20px;
font-family: sans-serif;
cursor: pointer;
}
.box a {
display: flex;
align-items: center;
justify-content: center;
}
.box a span {
padding-right: 10px;
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" />
<div class="box">
<a>
<span>Search</span>
<i class="fa fa-search fa-2x" aria-hidden="true"></i>
</a>
</div>
Hope this helps!
You can easily adjust the positioning of your text in the span if you first make it a block element, and then apply a float. Once this is done, you can apply line-height as you initially mentioned, but without affecting the icon.
Here is a JSFiddle to show what to do. Incredible easy, and you don't have to touch your original CSS: https://jsfiddle.net/pgkjaa8c/
Solution using Floats
.box span {
display: block;
float: left;
line-height: 40px;
}
And you can change the float from left to right if you want the text on the right. Additionally, you can apply left and right padding to push the text away from the icon if you so desire: https://jsfiddle.net/rz4y4696/
.box span {
padding-left: 15px;
display: block;
float: right;
line-height: 40px;
}
Additionally, I advise against using flex. People are constantly pushing flex as a solution, but it eliminates many legacy browsers from support. This would be one of the more traditional ways of implementing this, with fully cross browser, and legacy browser support.
Solution without using Floats
If you want a solution that does not require floats, and will work for varying widths, then you'd have to remove the <i> tag and add your FontAwesome icon to your CSS. You can see the solution here: https://jsfiddle.net/rwkypte8/2/
You can get the value of the FontAwesome search icon here: http://fontawesome.io/icon/search/
The HTML and CSS is below:
HTML
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" />
<div class="box">
<a>
<span>Search</span>
</a>
</div>
CSS
.box {
width: 50%;
text-align: center;
background-color: #f0f0f0;
margin: 50px auto;
padding: 20px;
font-family: sans-serif;
cursor: pointer;
}
.box span {
display: block;
line-height: 40px;
text-align: center;
}
.box span:after {
padding-left: 20px;
font-family: 'FontAwesome';
font-size: 30px;
content: '\f002';
}

Unfixed Responsive design styling

Updated!!!
I've still facing the same error each time I view the page on landscape screen devices.
CSS:
f5 {
text-transform: uppercase;
color: #fff;
font-size: 30px;
font-weight: bold;
}
about.us
<div class="containerpreview">
<br>
<f5>Check out our products</f5>
<br>
<f6>and Experience no-frills delivery</f6>
<div style="margin-top:40px">
<div class="buttoneshop">Eshop</div>
</div>
</div>
is there a way to make the spacing in between closer? When I command out
text-transform: uppercase;
the spacing is fine.
Aside of that, is there a way to make an image inside src under href to be centered?
css
.images_1_of_4 img {
max-width: 100%;
<!-- height: 200px; -->
width: 200px;
align: middle;
}
.img {
display: block;
width: 100%;
max-width: 100%;
height: auto;
}
.grid_preview {
height: 200px;
}
shop.php
<div class="grid_1_of_4 images_1_of_4">
<div class="grid_preview">
<img src="..." alt="">
</div>
</div>
Try to change alignment text-align : justify; to text-align : left.
Or, if this is not what you like to do, letter-spacing is a CSS attibute to change space between charagcters, and word-spacing to change space between words
As other users suggested, consider forcing alignment on the left using text-align : left, you probably have text-align : justify; on a wrapper element or setted in another part of your css as depicted the example below.
https://jsfiddle.net/s5p9872t/
.f5 {
text-align : justify;
width: 250px;
}
.f5 {
text-transform: uppercase;
font-size: 30px;
font-weight: bold;
text-align: left;
}

Resources