How to TRULY vertically center text with flexbox? - html

So vertically centering text seemed simple enough with justify-content and align-items center but when I looked closely I can see that the text isn't truly centered. It has less spacing at the top of the character. I tried to investigate further by searching online and I found this https://iamvdo.me/en/blog/css-font-metrics-line-height-and-vertical-align but there must be a simpler solution to this.
Example
https://jsfiddle.net/z7cy487o/
html,
body {
height: 100%;
}
.box {
height: 10%;
width: 400px;
background: #000;
font-size: 11vh;
color: #FFF;
text-align: center;
padding: 0 20px;
margin: 20px;
display: flex;
justify-content: center; /* align horizontal */
align-items: center; /* align vertical */
}
<div class="box">
C
</div>

The way you perceive that depends on which characters you are using. I copied your example twice to show different situations:
In the second version I only used the letter "y", which has a descender, i.e. a part that extends below the baseline, to the lower border of the area which is defined as line-height. On the other hand, it doesn't go up the whole way, so it seems exactly the opposite of the first version (letter "C") concerning vertical alignment.
In the third version I used both of those letters combined in a word. Here you can see that the different characters/letters together indeed do extend across the whole width, so the vertical centering is correct as it is.
Line-height (and in relation to that, vertical alignment of letters) does not depend on which letters are used - it always applies to all possible letters/characters, even if they are not used in that particular situation.
html, body { height: 100%; }
.box
{
height: 10%;
width: 400px;
background: #000;
font-size: 11vh;
color: #FFF;
text-align: center;
padding: 0 20px;
margin: 20px;
display: flex;
justify-content: center; /* align horizontal */
align-items: center; /* align vertical */
}
<div class="box">
C
</div>
<div class="box">
y
</div>
<div class="box">
Cyborg
</div>

This solution based off a modified version of Center text character ☢ vertically and horizontally within a circle (CSS)
It seems to work with dynamic heights, but as Johannes mentions in the comment of his answer. I believe the solution will only work well with my situation.
html,
body {
height: 100%;
}
.box {
height: 10%;
width: 400px;
background: #000;
font-size: 11vh;
color: #FFF;
text-align: center;
padding: 0 20px;
margin: 20px;
display: flex;
justify-content: center; /* align horizontal */
align-items: center; /* align vertical */
}
.char {
line-height: 1px;
font-family: sans-serif;
font-weight: 500;
position: relative;
top: 0.05em;
}
<div class="box">
<span class="char">C</span>
</div>

Related

CSS prevent smaller font sizes from not centering

I'm having trouble vertically centering 2 elements (svg + text). I used flexbox to center these elements, and they are perfectly centered if I do not precise any font-size. But when I put a smaller font-size on the text (0.8em instead of 1em), it creates a small space on top of the text instead of centering it. Horrible colors are to show the blue space on top of the text. Does anyone know how to fix this ?
I've already tried adding text-align: center; vertical-align: middle;
The parent div (blue) centers elements with flex: display: flex; align-items: center;
Thanks a lot
Edit: Here is a snippet, I somehow can't find how to link a file (the svg) ?
a {
text-decoration: none;
}
/*Parent div*/
.parent {
width: 20vw;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 1vw;
background-color:skyblue;
}
/*Svg*/
.parent img {
width: auto;
height: 3vh;
margin-right: 10px;
background-color: rosybrown;
}
/*Text*/
span {
font-size: 0.8em;
background-color: seagreen;
}
<div class="parent">
<div>
<img src="https://cdn0.iconfinder.com/data/icons/feather/96/heart-512.png"><span>Favoris</span>
</div>
</div>
I would try to set the line-height of the text element to the same value as your font-size. I would also not define a height for the text element (I am not sure if you are doing this or not, since you did not provide your code).
So something of the sort:
div.container {
display: flex;
align-items: center;
padding: 10px;
background-color: #4169E1;
}
div.container img {
width: 40px;
height: 40px;
margin-right: 20px;
background-color: #BC8F8F;
}
div.container span {
font-size: 20px;
line-height: 20px;
color: #4B565C;
background-color: #2E8B57;
}
<div class="container">
<img src="https://cdn0.iconfinder.com/data/icons/feather/96/heart-512.png"/>
<span>Favoris</span>
</div>
Found the problem:
<a href="#">
<div class="parent">
<img src="img/coeur.svg">
<span>Favoris</span>
</div>
</a>
I just had to invert the <a> tag and <div> and everything is well centered.

Best way to vertically-align children in an inline-block

I’m trying to vertically align the content in the cyan div without using one of the following methods:
Vertical align (as it requires displaying as a table & will have knock-on effects on the parent div padding etc)
Line height (as there’s more than 1 line with 3 actual spans)
Table (due to knock-on effects like with vertical align)
Absolute positioning (as some other cyan divs will have more text than others, meaning some will have more lines than others)
Equal top & bottom padding (same reason as abs positioning)
Flexboxes (I forbid these as they have serious knock-on effects!)
The cyan div is an inline-block. What would be the best way to achieve this? I want to be able to set the padding between each of the 3 spans to space them out nicely.
NOTE:
I've updated my answer to include flex positioning but on mobile view the 2nd cyan div below is not aligned centrally
.sections {
background: #f2f2f2;
width: 100%;
height: auto;
text-align: center;
padding: 100px 10%;
box-sizing: border-box;
}
h1 {
font-size: 62px;
text-transform: uppercase;
font-weight: 400;
}
p {
font-size: 22px;
font-weight: 300;
padding-top: 10px;
}
.foster-cta {
box-sizing: border-box;
width: 250px;
height: 200px;
background: cyan;
display: inline-block;
border: 1px solid grey;
margin-top: 30px;
/* adding display flex makes the 2nd cyan div below not aligned centrally on mobile view */
display: flex;
flex-direction: column;
justify-content: space-evenly;
align-items: center;
display: inline-flex;
}
.foster-top {
display: block;
font-size: 30px;
}
.foster-middle {
display: block;
text-transform: uppercase;
font-size: 22px;
}
.foster-bottom {
display: block;
font-weight: 300;
font-size: 16px;
}
<section class="sections">
<h1>header 1 tag</h1>
<p>some random text to go here lorem ipsum sit semei geono wfnwoenfowe fwenfuowe ffe efnpi enfo wfeonwofun weofun weofnwe ofunwe foiej.</p>
<div class="foster-cta">
<span class="foster-top">icon</span>
<span class="foster-middle">some random text here</span>
<span class="foster-bottom">a load more random text goes here that will be more descriptive and longer.</span>
</div><!--
--><div class="foster-cta" style="margin-left:50px;">
<span class="foster-top">icon</span>
<span class="foster-middle">text</span>
<span class="foster-bottom"> a load more random text goes here that will be more descriptive and longer a load more random text goes here that will be more descriptive and longer.</span>
</div>
</section>
Flexbox is your best bet when doing any sort of aligning in CSS. The code is also very simple:
.div-parent {
display: flex;
}
.div-child {
align-self: center;
}
This will align vertically centered only

CSS: centering text within flex-wrapped buttons

I have a several buttons on a page and I am suing flex and flex-wrap to give them spreading ability. I cannot however get the text within the elements to center in their 100x100 px boxes (the size is an attribute of the .
I tried some solutions here, but none of them seem to work for my situation: CSS Center text (Horizontal and Vertical) inside a DIV block
The Line-height solution does not work, as some of the text takes more than one line.
The absolute positioning solution also does not work as it places the buttons all on top one of another.
The table approach is undesirable as it does not allow the buttons to wrap. Also I am going to have over 30 of these buttons.
HTML:
<section id="directory">
Jaguar Chagra
A marriage breaks up
Amasanga warmi
Anaconda caught
Big Water Killing
</section>
CSS:
#directory {
display: flex;
flex-wrap: wrap;
}
#directory a {
background-color: #BFBDAF;
width: 100px;
height: 100px;
margin: 10px;
padding: 20px;
text-decoration: none;
color: black;
text-align: center;
vertical-align: middle; /* does nothing */
Here is an image of what it looks like so far:
You need to add align-items: center; to #directory a and make it a block-level element with display: flex.
#directory a {
display: flex;
background-color: rgb(191, 189, 175);
width: 100px;
height: 100px;
margin: 10px;
padding: 20px;
text-decoration: none;
color: rgb(0, 0, 0);
text-align: center;
align-items: center;
}

How to implement this notification design and have it sensibly responsive

I am attempting to implement this, simple enough design for a notification block.
Including the ability to respond by wrapping the text block on smaller screens, similar to the below;
The intention here is to center align the notification to the parent row, and preferably when the viewport is too small, have the text wrap and height of the horizontal banner on which it sits increase in height accordingly. This will be included in a bootstrap project (may affect floats etc).
Here is a pen showing one of the more simple approaches (and probably closest so far) I've been trying to achieve this.
*,
html {
font-family: arial;
font-size: 20px;
}
.extra-row {
text-align: center;
padding: 1em;
border: 1px solid #eee;
background-color: #ccc;
}
.notification {
text-align: center;
color: #fff;
white-space: nowrap;
}
.notification-circle {
width: 150px;
height: 150px;
background-color: #3D7A1A;
-moz-border-radius: 75px;
-webkit-border-radius: 75px;
border-radius: 75px;
position: relative;
display: -webkit-flexbox;
display: -ms-flexbox;
display: -webkit-flex;
display: inline-flex;
-webkit-flex-align: center;
-ms-flex-align: center;
-webkit-align-items: center;
align-items: center;
justify-content: center;
}
.notification-icon {
font-size: 5em;
}
.notification-block {
min-height: 150px;
line-height: 150px;
display: inline-block;
margin-left: -30px;
vertical-align: top
}
.notification-block span {
background-color: #54A127;
padding: 1em;
padding-left: 50px;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container">
<div class="row extra-row">
<div class="col-lg-12">
<p>This is a row above</p>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div class="notification">
<div class="notification-circle"><span class="notification-icon">i</span>
</div>
<p class="notification-block"><span>Lorem ipsum dolor sit amet, consectetur adipiscing elit. </span>
</p>
</div>
</div>
</div>
<div class="row extra-row">
<div class="col-lg-12">
<p>This is a row below</p>
</div>
</div>
</div>
There's quite a few suggestions for vertically centering text in this manner, most appear to rely on line-height which is an issue here with wrapping the text.
This may not be the best approach due to using line-height, but the problems here are;
Preventing the circular container and text container from
wrapping.
Wrapping the text within the container while still
maintaining the overall height/vertically centered position of the text block.
Wrapping the text with a sensible line-height.
Adding white-space: nowrap; to the .notification element does prevent #1, but prevents the text from wrapping, which simply extends past the viewport.
Can anyone shed any light on a better approach? Any thoughts would be appreciated.
Many thanks,
Baps.
Hopefully this sets you on the right path.
I've removed a lot of unnecessary code. I've also removed the prefixes for the demo.
This adjustment may be all you need:
.notification {
display: flex; /* 1 */
align-items: center; /* 2 */
color:#fff;
}
.notification-circle {
flex: 0 0 150px; /* 3 */
height: 150px;
background-color: #3D7A1A;
border-radius: 75px;
display: flex;
align-items: center;
justify-content: center;
}
.notification-block {
margin-left: -50px; /* 4 */
background-color: #54A127; /* 5 */
padding: 1em; /* 5 */
padding-left: 75px; /* 5 */
z-index: -1; /* 6 */
}
.notification-block span { }
.notification-icon { font-size: 5em; }
Revised Codepen
Notes:
Make wrapper a flex container
Vertically center both flex children (.notification-circle and .notification-block)
Don't grow. Don't shrink. Remain fixed at 150px width.
Changed from margin-left: -30px
Relocated code from span child
Ensure .notification-block doesn't overlap .notification-circle

Line segment won't stay under h2 tag

So, I've just started learning HTML/CSS and I've been trying to figure out how to 'stick' a line under an h2 tag. What I mean by this is that in the HTML there is an h2 tag called Instructions followed by a div tag that contains 3 other divs that make up a line segment. By default the line is on the left side (naturally), but what I want to do is have the line stuck under the h2 tag so when the browser is extended or shrunk the line stays directly under the h2 tag instead of moving across the screen by itself.
I came across this site: http://www.barelyfitz.com/screencast/html-training/css/positioning/ and I was using it to try and see if absolute/relative positioning would help here. I guess I'm doing it horribly wrong since it doesn't seem to help.
I'm providing HTML/CSS and a jsfiddle below (The jsfiddle doesn't show how the line moves around when the browser is extended/shrunk, though so I'm hoping you get what I mean). If you can help guide me or give me some resources to understand what I need to do better that would be great :D
I'm sure this is trivial, but I'm trying to do my due diligence in learning it. There were a lot of different methods (I think) I found, but they seemed kinda complex.
HTML
<div id="instructions_box">
<h2>Instructions</h2>
<div class="line_divider">
<div class="blue_line"></div>
<div class="yellow_line"></div>
<div class="blue_line"></div>
</div>
</div>
CSS
#instructions_box{
display: inline-block;
//position: relative;
}
.line_divider{
background-color: aqua;
//position: absolute;
//bottom: 0;
//right: 2rem;
}
.blue_line{
height: 2px;
width: 50px;
background-color: rgb(0,0,139);
float: left;
}
.yellow_line{
height: 2px;
width: 90px;
background-color: yellow;
float: left;
}
#instructions_box h2{
text-align: center;
}
https://jsfiddle.net/10szzwvs/1/
Thanks
The wrapping you're seeing is, I think, due to the fixed widths you're using. Change your line width to percentages and it wont wrap on any size screen. Note you'll need to add your visual spacing elsewhere, e.g. on the h2 itself.
#instructions_box{
display: inline-block;
}
#instructions_box h2{
text-align: center;
padding: 0 25px 0; /* visual spacing */
margin: 0;
}
.line_divider{
background-color: aqua;
}
.blue_line{
height: 2px;
width: 30%; /* dynamic width here */
background-color: rgb(0,0,139);
float: left;
}
.yellow_line{
height: 2px;
width: 40%; /* dynamic width here */
background-color: yellow;
float: left;
}
<div id="instructions_box">
<h2>Instructions</h2>
<div class="line_divider">
<div class="blue_line"></div>
<div class="yellow_line"></div>
<div class="blue_line"></div>
</div>
</div>
You can always use CSS3 Flexbox. You've got to have the div of lines and the h2 in the same container as you already do. And then.
#instructions_box{
display: -webkit-flex;
display: flex;
-webkit-flex-direction: column;
flex-direction: column;
-webkit-align-items: center;
align-items: center;
-webkit-justify-content: center;
justify-content: center;
}