Center an element vertically HTML - css

I am trying to vertically center a header element in my nav element, and I tried to calculate the height of the <h1> using this CSS:
.navbar {
display: table;
width:90%;
height: 3em;
background-color: #7f8c8d;
border-radius: 10px;
.nav-title {
display: table-cell;
vertical-align: middle;
text-align: center;
}
.nav-dropdown {
display: table-cell;
vertical-align: middle;
text-align: center;
}
}
It worked, and I don't understand how. I was also wondering if there were any better ways to center an element vertically. TL;DR: How does this work? What are other ways to accomplish what this code accomplishes.

This works because you are setting the display to table and table-cell. Table cells natively allow for vertical centering.
Without using tables you still have lots of other options (though none of them seem to be as simple).
CSS-Tricks has a handy writeup of various centering methods.

See it as a table, you create a table cell of your .nav-title. You are able to vertically align them, that's how it works.
Are there any easy ways to center vertically? A few, but in a lot of occassions some of them don't work.
Here is one:
.element {
position: relative;
top: 50%;
transform: translateY(-50%);
}

Related

CSS. Remove Overflow-y. Nowrap. Keep Elements Inline

What is wrong with this? Ive read a couple of posts which suggest that in order to have inline-block elements all on the same line with only overflow-x, the following CSS is all that is required on the parent:
div {
overflow-x:scroll;
overflow-y:hidden;
white-space:nowrap;
}
This is my CSS, straight from my firebug for both the parent, and the elements which i need on the same line. The elements are wrapping with only a vertical overflow. Im confused. Any suggestions?
.elementsRequiredOnSameLine {
background: none repeat scroll 0 0 white;
display: inline-block;
float: left;
height: 10em;
text-align: center;
width: 6em;
}
.parent{
display: inline-block;
margin: 10px auto;
min-height: 12em;
overflow-x: scroll;
padding: 10px;
white-space: nowrap;
width: 95%;
}
Using float: left on the elements will cause them to ignore the nowrap rule. Since you are already using display: inline-block, you don't need to float the elements to have them display side-by-side. Just remove float: left
Was because of the float:left;, once i removed that, fine. Spotted it after typing out question sorry.

Set line-height as a percentage relative to the parent element

I have a responsive element where it's width and height will both scale. Inside this I have some text which I want to center vertically.
How can I set the text's line-height to be the same as it's parent if I don't know the parent's height?
line-height: 100% is relative to the font's regular height so this doesn't help...
Here's another way to center an element vertically. I came across this technique some time ago. Basically it uses a pseudo element and vertical-align: middle.
.block::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;
width: 300px;
}
Since it's 2019 already, you could also use flexbox to achieve this :)
To do so, add the following classes to the parent element:
display: flex;
flex-direction: column;
justify-content: center;
See this Fiddle
I'd try putting the text inside another element, of which you know (or set) the size. Then setting relative positioning to it, top, left 50% and negative left and right margins.
See this Fiddle
The only problem is that this relies on a known/fixed textblock. If the text is variable, I'm afraid you will have to resort to using Javascript..
Regarding hyperlinks:
I was having this problem regarding links in main menu. And since it was <a> in <li> tags I needed some surface for the links to be clickable/touchable(see touch target size).
So what I did was for the <ul> I set a fixed height(through it's parent in this case), the <li>-s are a percentage of it and the <a>-s have a min-height and line-height properties set to them and it's easy from there to set the top. The code:
.menu-header-main-container{
position: fixed;
top: 0;
bottom: 160px;
}
.menu-header-main-container ul.menu {
height: 100%; }
.menu-header-main-container ul.menu li {
height: 33.33%;
max-height: 110px; }
.menu-header-main-container ul.menu li a {
line-height: 40px;
min-height: 40px;
top: calc(50% - 20px);
position: relative; } }
You cannot set the line-height to 100% of the parent element's height with only CSS. Rather, you can use CSS to center an element vertically.
.parent {
height:150px;
position:relative;
border:1px solid #FDD;
}
.position-center {
position:absolute;
top:50%;
transform:translateY(-50%);
}
<div class="parent">
<span class="position-center">I am vertically centered element</span>
</div>
Wow, 2022 and I don't think we have a decent way to do this still. What I used to do and I think is the less painful idea is to use a table for layout. Tables will naturally center text vertically, or you can use "vertical-align"
<table style="width: 100%; height: 100%; text-align: center">
<tr><td>Your text</td></tr>
</table>
Not great, but at least you can center text without ever having to specify fixed heights.

line-height as a percentage not working

I am having an issue with line-height that I cannot quite get my head around.
The following code will center an image within a div:
CSS
.bar {
height: 800px;
width: 100%;
line-height:800px;
background-color: #000;
text-align: center;
}
.bar img {
vertical-align: middle;
}
HTML
<div class="bar">
<img src="http://27.media.tumblr.com/yHWA4oxH870ulxnoH7CkOSDR_500.jpg" alt="Foo Image" />
</div>
However, if I change the line height to 100%, then the line height does not take effect (or at least does not become 100% of the div).
Example jsfiddle
Does anyone know what I am doing wrong?
line-height: 100% means 100% of the font size for that element, not 100% of its height. In fact, the line height is always relative to the font size, not the height, unless its value uses a unit of absolute length (px, pt, etc).
I know this question is old, but I found what for me is the perfect workaround.
I add this css to the div that I want to center:
div:before {
content: "";
display: inline-block;
height: 100%;
vertical-align: middle;
}
This works every time and it is clean.
Edit:
Just for completion's sake, I use scss and I have a handy mixin that I include on every parent who's direct children I want to have vertically centered:
#mixin vertical-align($align: middle) {
&:before {
content: "";
display: inline-block;
height: 100%;
vertical-align: $align;
// you can add font-size 0 here and restore in the children to prevent
// the inline-block white-space to mess the width of your elements
font-size: 0;
}
& > * {
vertical-align: $align;
// although you need to know the font-size, because "inherit" is 0
font-size: 14px;
}
}
Full explanation:
div:before will add an element inside the div, but before any of its children. When using :before or :after we must use a content: declaration otherwise nothing will happen, but for our purpose, the content can be empty. Then we tell the element to be as tall as its parent, as long as its parent's height is defined and this element is at least inline-block. vertical-align defines the vertical position of self related to parent, as opposed to text-align that works differently.
The #mixin declaration is for sass users and it would be used like this:
div {
#include vertical-align(middle)
}
When you use percentage as the line-height it is not based on the div container, rather its based on the font-size.
line-height: 100% would be an easy way to vertically center elements, if it was calculated in relation to the container, but that would be too easy, hence it doesn't work.
So instead, it is just another way of saying line-height: 1em (right?)
Another way of vertically centering an element would be:
.container {
position:relative;
}
.center {
position:absolute;
top:0; left:0; bottom:0; right:0;
margin: auto;
/* for horiz left-align, try "margin: auto auto auto 0" */
}
might not be pretty, but it's working, and its semantic;
<div class="bar" style="display: table; text-align: center;">
<img style="display: table-cell; vertical-align: middle;" src="http://27.media.tumblr.com/yHWA4oxH870ulxnoH7CkOSDR_500.jpg" alt="Foo Image" />
</div>
display: table-cell gives an element the unique table ablillity to align verticaly (atleast i think its unique)
This is a very late answer, however in modern browsers, assuming that the parent element is 100% of the screen height as well, you can use the vh viewport unit.
FIDDLE
line-height: 100vh;
Browser support
A more modern approach is to use flexbox for this, it is simpler and cleaner. However, flexbox is an entirely different paradigm from what inline-block, float or position used to be.
To align items inside .parent you do:
.parent {
display: flex;
align-items: center;
}
That is about it. Children of flex parents are automatically converted to flex child items.
You should read more about flexbox, a good place to start is this cheat sheet: https://css-tricks.com/snippets/css/a-guide-to-flexbox/
This is the modern solution in which you need to set the following CSS in the container div or outer div.
.outer-div {
display: flex;
justify-content: center;
align-items: center;
}
Another following solution may be applied to the element which you want to make centered vertically. Note that the outer or container div should be
.inner-div {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
text-align: center;
}
Note that the outer or container div position should be relative.
This solution works in IE9 and above. First we set the child's top position to 50% (middle of the parent). Then using translate rule, shift the child up by a half of its actual height. The main benefit is that we don't need to define child's height, it's calculated by the browser dynamically. JSFiddle
.bar {
height: 500px;
text-align: center;
background: green;
}
.bar img {
position: relative;
top: 50%;
transform: translate(0, -50%);
}
You can set line-height based on that element height. If the element height 200px means you need to set line height to 200px to center the text.
span {
height: 200px;
width: 200px;
border: 1px solid black;
line-height: 200px;
display: block;
}
<span>Im vertically center</span>

Flowing items horizontally w/ center alignment within a container

My dilemma is this (and should be simple, I suspect): I have a container and a set of items (both divs). The following CSS applies:
.container {
float: left;
width: 100%;
}
.item {
margin: 32px;
text-align: center;
position: relative;
float: left;
}
The .item itself is a container that could have almost any set of arbitrary elements, but they need to be center aligned inside of it (in my case, it typically contains a thumbnail image and a small caption of text beneath it). While the above CSS allows each .item to flow horizontally the way I like, I can't figure out how to make the whole set center aligned (as opposed to flowing from left to right like it does now).
edit
Change .item { display: block; } to .item { display: inline-block; }, take away .item { float:left; } and add text-align: center; to .container
You can see it here: http://jsfiddle.net/JMC_Creative/RQrRb/
You could also put an .inner div with width:75%; margin: 0 auto; and then put your .items in that, if you are looking to have some space on the sides.
You'll want to take a look at this tutorial from Mozilla. It can be center aligned by just setting the parent container to text-align:center;
Cross Browser Inline Block
.container {
width: 100%;
}
.item {
margin: 32px;
text-align: center;
}

Vertically aligning CSS :before and :after content [duplicate]

This question already has answers here:
How do I vertically center text with CSS? [duplicate]
(37 answers)
Closed 3 years ago.
I am trying to centre the link with the image, but can't seem to move the content vertically in any way.
<h4>More Information</h4>
File Name
The icon is 22 x 22px
.pdf {
font-size: 12px;
}
.pdf:before {
padding:0 5px 0 0;
content: url(../img/icon/pdf_small.png);
}
.pdf:after {
content: " ( .pdf )";
font-size: 10px;
}
.pdf:hover:after {
color: #000;
}
Answered my own question after reading your advice on the vertical-align CSS attribute. Thanks for the tip!
.pdf:before {
padding: 0 5px 0 0;
content: url(../img/icon/pdf_small.png);
vertical-align: -50%;
}
You can also use tables to accomplish this, like:
.pdf {
display: table;
}
.pdf:before {
display: table-cell;
vertical-align: middle;
}
Here is an example: https://jsfiddle.net/ar9fadd0/2/
EDIT:
You can also use flex to accomplish this:
.pdf {
display: flex;
}
.pdf:before {
display: flex;
align-items: center;
}
Here is an example: https://jsfiddle.net/ctqk0xq1/1/
I'm no CSS expert, but what happens if you put vertical-align: middle; into your .pdf:before directive?
I think a cleaner approach is to inherit the vertical alignment:
In html:
<div class="shortcut">Download</div>
And in css:
.shortcut {
vertical-align: middle;
}
.shortcut > a:after {
vertical-align: inherit;
{
This way the icon will align properly in any resolution/font-size combination. Great for use with icon fonts.
Using flexboxes did the trick for me:
.pdf:before {
display: flex;
align-items: center;
justify-content: center;
}
Messing around with the line-height attribute should do the trick. I haven't tested this, so the exact value may not be right, but start with 1.5em, and tweak it in 0.1 increments until it lines up.
.pdf{ line-height:1.5em; }
This is what worked for me:
.pdf::before {
content: url('path/to/image.png');
display: flex;
align-items: center;
justify-content: center;
height: inherit;
}
I spent a good amount of time trying to work this out today, and couldn't get things working using line-height or vertical-align. The easiest solution I was able to find was to set the <a/> to be relatively positioned so it would contain absolutes, and the :after to be positioned absolutely taking it out of the flow.
a{
position:relative;
padding-right:18px;
}
a:after{
position:absolute;
content:url(image.png);
}
The after image seemed to automatically center in that case, at least under Firefox/Chrome. Such may be a bit sloppier for browsers not supporting :after, due to the excess spacing on the <a/>.
I just found a pretty neat solution, I think. The trick is to set the line-height of image (or any content) height.
text
Using CSS:
div{
line-height: 26px; /* height of the image in #submit span:after */
}
span:after{
content: url('images/forward.png');
vertical-align: bottom;
}
That would probably also work without the span.
I had a similar problem. Here is what I did. Since the element I was trying to center vertically had height = 60px, I managed to center it vertically using:
top: calc(50% - 30px);

Resources