I'm building a website within a CMS. There are quite a few elements that require vertically centered content. However, since I don't have the final content (and whatever content can and will be change in the future) I cannot set a fixed height to those containers.
I just spent a good few minutes trying to figure out why my elements won't vertically align using flexbox...until I found out it's for the lack of a fixed height.
In the past I built such layouts using the display:table/table-cell combination. I started using flexbox models more and more lately and really start to like those and would rather stop using table/table-cell.
Now I wonder how (or if) I could use flexbox to vertically align content no matter what height a container will have.
If your flex container is flex-direction: row (the default orientation), to vertically center content you can use:
align-items: center; /* for a single line of flex items */
align-content: center; /* for multiple lines of flex items */
If your flex container is flex-direction: column, to vertically center content you can use:
justify-content: center;
These methods work without the need to define any heights.
For more details, illustrations, and live demos, see my answer here: https://stackoverflow.com/a/33049198/3597276
From that answer:
Below are two general centering solutions. One for vertically aligned flex items (flex-direction: column) and the other for horizontally aligned flex items (flex-direction: row). In both cases the height of the centered divs can be variable, undefined, unknown, whatever. The height of the centered divs doesn't matter.
May I suggest you use both, like this, as there are still a few IE8/9 users out there and this fallback variant will make it work for them too.
And for other older browser versions that require prefix or use the older flexbox model (like IE10, Safari8/7/6 and some mobile version such as Android, Blackberry, UC Browser), the table version kicks in. More on flexbox support here
html, body {
margin: 0;
height: 100%;
}
.parent {
display: table;
display: flex;
justify-content: center;
/* for this demo */
width: 50%;
height: 50%;
border: 1px solid black;
}
.child {
display: table-cell;
vertical-align: middle;
text-align: center;
display: flex;
align-items: center;
}
<div class="parent">
<div class="child">Centered<br>content</div>
</div>
To vertically center content (or totally centered), you can use CSS transform with translate property. With that method, you don't need to know the size of the element, and combined with a relative parent you achieve a perfect vertical center or horizontal center. See the snippet:
.relative {
position: relative;
width: 400px;
height: 300px;
background-color:yellow;
border: 1px solid black;
margin: 20px 0;
}
.relative .center {
position: absolute;
background-color: black;
color: white;
width: 120px;
height: 150px;
}
.relative .center.vertical {
top: 50%;
-ms-transform: translateY(-50%); /* ie9/ie10 */
-webkit-transform: translateY(-50%); /* safari ios */
transform: translateY(-50%); /* standard */
}
.relative .center.horizontal {
left: 50%;
-ms-transform: translateX(-50%);
-webkit-transform: translateX(-50%);
transform: translateX(-50%);
}
.relative .center.total {
top: 50%;
left:50%;
-ms-transform: translate(-50%, -50%);
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
<div class="relative">
<div class="center vertical">Vertical center</div>
</div>
<div class="relative">
<div class="center horizontal">Horizontal center</div>
</div>
<div class="relative">
<div class="center total">Total center</div>
</div>
Related
I am working on a website: http://felipewarrener.55freehost.com
As you can see there is a content slider, I've added media queries to make the text smaller and the boxes scale in width (I will eventually make the text small enough so that it wont make the boxes bigger than the containter div.
However, I don't know how I can vertically center these boxes? When I scale it down they will need to be vertically centered or else they will just float down.
They are positioned relatively as i felt that was the best option
Could anyone suggest or tell me what method I should use?
Thanks for taking the time to read
Felipe
you can use flex
.container {
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
align-content: center;
width: 400px;
height: 400px;
border: 1px solid black;
}
.content {
width: 200px;
height: 200px;
background-color: green;
}
<div class="container">
<div class="content">
</div>
</div>
If you're talking about your "A new dimension to colouring PVC",
What you could do is have the header container be relatively positioned, and then give your text this class:
.vert-centered{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
Pretty sure your text is floating down to prevent overlap though. You might as well just hide it when the screen width gets too small.
im trying to change the custom CSS of my page headers, but every time i try to add a top-margin to one of the nested divs, it moves the entire background image down.
Current code (abridged):
<header id="fancy-header" style="
background-color: #ffffff; background-size: cover;
background-repeat: no-repeat;
background-image: url(http://thegsc.co.il/wp-content/uploads/2014/07/about-header.jpg);
background-position: center center; min-height: 150px">
<div class="wf-wrap">
<div class="wf-table" style="
background:rgba(32,117,200, .6) !important;
margin-top:25px;">
<div class="title">title</div><div class="breadcrumbs">breadcrumbs</div>
</div>
</div>
</header>
Ideally, all Im trying to do is have a background image that spans the entire header (150px), and then a transparent-color overlay on the background text.
Using margin-top:25px because when i tried adding a vertical-align:middle to .wf-table, nothing happened.
Suggestions?
The trouble is that your .wf-table element was not respecting #fancy-header as its parent. The trick is to add float: left and it'll behave in this case as you expect. Check it out here - https://jsfiddle.net/96hf0nqa/
Floats are a little tricky but super important for effective CSS. You can read a lot about them here. Good luck!
If your <header> is the main container to be full-screen then ideally you should be using a grid approach.
Not sure if you use a grid or not? In this case the wf-wrap is your grid-row:
.wf-wrap {
box-sizing: border-box; /* box model fix */
max-width: 94rem; /* 960px - gutter */
padding: 0 1rem; /* grid gutter */
margin: 0 auto; /* to center */
height: 100%;
position: relative; /* to init the absolute offset of it's children */
}
Then your wf-table should be positioned absolute to have full control:
.wf-table {
position: absolute; /* to control top left right bottom */
top: 2.5rem; /* default offset */
z-index: 1 /* if overlap requires it */;
}
DEMO
Typically a grid-row is divided into columns. The position relative belongs on a column actually.
.column {
box-sizing: border-box;
padding: 0 1rem;
float: left;
height: 100%;
position: relative;
}
.g50 { max-width: 50%; width: 100%; }
So your HTML can be made a little bit more generic to gain control on the position of elements inside columns.
<div class="header">
<div class="row">
<div class="column g50">
<div class="wf-table"><!--content here--></div>
</div>
<div class="column g50"></div>
</div>
</div>
DEMO
Additionally there is a way to vertically align a block element in CSS3:
.middle-y {
position: absolute;
top: 50%;
-webkit-transform: translateY(-50%);
-moz-transform: translateY(-50%);
-o-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
}
One very common question on CSS is how to vertically center an element. With CSS3 being able to do so many special effect, why they are not including the vertically center function into CSS3?
I don't believe it is a difficult function to add if even a beginner developer can make a function to center things with javascript. And with so many hacks for different situations, it is clear that with CSS alone it is possible to center things vertically. So maybe there are other reasons that they decide not to make it a standard property?
That is because how layout is performed with CSS — CSS is predominantly arranging items on the x-axis, like how 100% width works as expected but not 100% height. This is likely due to the possible "calculation/logic loop" that happens as width is dependent on height and vice versa, so one axis must always be prioritized when it comes to calculation.
Extra info by #BoltClock:
The x-axis thing has to do with the natural flow of text in a
document. Remember that the Web started off as a series of pages, so
HTML and CSS were originally built around this fundamental premise -
it has since evolved into an application platform, but the legacy is
still there. Flexbox is the CSS3 way to vertically center boxes - the
only issue is cross-browser support, but since the question is about
CSS3 anyway, that's to be expected.
Similarly, in terms of dictating alignment, horizontal alignment is easy because the width of an element is often implicitly or explicitly stated, like how a block element automatically has a implicit width of 100% unless otherwise stated, allowing for easy calculation of a center position along the horizontal axis.
However, this does not work for the case of vertical alignment, where often than not the vertical dimension is dependent on the amount, length and size of the content. In the case where vertical height is explicitly stated, this can actually be easily done:
by using the CSS flexbox method
The good: standards compliant and very simple, dimension of element of interest does not have to be fixed
The bad: lack of extensive cross-browser support, but appears very promising today
body {
margin: 0;
padding: 0;
}
.box {
background-color: #eee;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100vh;
}
.box > .content {
background-color: #333;
color: #eee;
padding: 1em 2em;
}
<div class="box">
<div class="content">I am centered</div>
</div>
by using absolute positioning and CSS transforms
The good: extensive cross-browser support, dimension of element of interest does not have to be fixed
The bad: fuzzy text rendering (occasionally) due to sub-pixel translation
body {
margin: 0;
padding: 0;
}
.box {
background-color: #eee;
position: relatve;
width: 100%;
height: 100vh;
}
.box > .content {
background-color: #333;
color: #eee;
padding: 1em 2em;
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
<div class="box">
<div class="content">I am centered</div>
</div>
by using absolute positioning and negative margins
The good: extremely straightforward
The bad: dimension of element of interest MUST be fixed
body {
margin: 0;
padding: 0;
}
.box {
background-color: #eee;
position: relative;
width: 100%;
height: 100vh;
}
.box > .content {
background-color: #333;
color: #eee;
width: 200px;
height: 100px;
position: absolute;
top: 50%;
left: 50%;
margin-top: -50px;
margin-left: -100px;
}
<div class="box">
<div class="content">I am centered</div>
</div>
I need to centralize a block made by a div, for instance, in the middle of the screen of a fluid grid layout. Inside this block, I want to put an image, a password field and a submit button. When I do this in a non-responsive layout with the following code, it works perfect but, in a fluid grid layout it doesn't:
#block-login {
width: 650px;
height: 378px;
float: left;
clear: both;
margin-top: -189px;
margin-left: -325px;
position: absolute;
top: 50%;
left: 50%;
text-align: center;
}
the fluid div I refer is one like this:
<div class="gridContainer clearfix">
<div id="div1" class="fluid"></div>
</div>
thanks in advance.
There are a few methods of doing so: CSS tables, CSS transforms and CSS flexbox. I typically avoid using CSS tables, though. Both CSS transforms and flexbox solutions, unlike the fixed negative margin solution, is that they are child-dimension agnostic (size of child does not matter, fixed or fluid).
For CSS transforms, a major caveat is that the parent's dimensions (that of .gridContainer) has to be explicitly predefined. The trick is to position it's child absolutely, but offset by 50% to the left and from the top. In order to take into account the child's own computed dimensions, we use CSS transforms to fix that. You might want to add vendor prefixes to the transform property though.
.gridContainer {
position: relative;
width: (have to declare);
height: (have to declare);
}
.gridContainer > div {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
The other solution (which I feel is way more elegant, but lacks cross-browser support in older browsers) is to use CSS flexbox:
.gridContainer {
display: flex;
align-items: center;
justify-content: center;
}
You can view the demo of both solutions here: http://jsfiddle.net/teddyrised/B7PVh/
This is a possible solution for you :
FIDDLE
CSS :
body,html,.gridContainer{
width:100%;
height:100%;
margin:0;
position:relative;
}
#div1 {
width: 80%;
height: 80%;
margin:0;
position: absolute;
top: 10%;
left: 10%;
text-align: center;
background:gold;
}
If you don't need to support IE9 and below, you can get a fixed-wdith, fixed-height div centered in a fluid container by using relative positoining and the new CSS calc() function:
<div class="gridContainer">
<div id="#block-login">
</div>
</div>
#block-login {
position:relative;
top:calc(50% - 189px); /* 50% - 1/2 of it's own height */
left:calc(50% - 325px); /* 50% - 1/2 of it's own width */
}
A jsfiddle demo
Note: caniuse.com lists "partial support" for calc() with ie-9
I have the following HTML:
<div class="outer">
<div class="inner rotate">Centered?</div>
</div>
div.outer is a narrow vertical strip. div.inner is rotated 90 degrees. I would like the text "Centered?" to appear centered in its container div. I do not know the size of either div in advance.
This comes close: http://jsfiddle.net/CCMyf/2/. You can see from the jsfiddle that the text is vertically centered before the transform: rotate(-90deg) style is applied, but is somewhat offset after. This is particularly noticeable when div.outer is short.
Is it possible to center this text vertically without knowing any of the sizes in advance? I haven't found any values of transform-origin that solve this problem.
The key is to set position top and left to 50% and then transformX and transformY to -50%.
.inner {
position: absolute;
top: 50%;
left: 50%;
}
.rotate {
transform: translateX(-50%) translateY(-50%) rotate(-90deg);
}
see: http://jsfiddle.net/CCMyf/79/
It may be a bit late for answering that question, but I stumbled on the same issue and found some way of achieving it, by adding another div in the way.
<div class="outer">
<div class='middle'><span class="inner rotate">Centered?</span></div>
</div>
and applying a text-align: center on that middle element, along with some positioning stuff:
.middle {
margin-left: -200px;
width: 400px;
text-align: center;
position: relative;
left: 7px;
top: 50%;
line-height: 37px;
}
The .inner also gets a display: inline-block; to enable both rotate and text-align properties.
Here is the corresponding fiddle : http://jsfiddle.net/CCMyf/47/
The another option to rotate text 90 degree and center on axis Y is:
.rotate-centered {
top: 50%;
right: 50%;
position: absolute;
transform: scale(-1) translate(-50%, 50%);
writing-mode: vertical-lr;
}
<span class="rotate-centered">Text<span>
Example: https://codepen.io/wwwebman/pen/KKwqErL
But because of bad support in IE/EDGE writing-mode does NOT work there:
https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode
Can you add margin: 0 auto; to your "rotate" class to center the text.
.rotate {
-webkit-transform: rotate(-90deg);
-ff-transform: rotate(-90deg);
transform: rotate(-90deg);
width: 16px; /* transform: rotate() does not rotate the bounding box. */
margin: 0 auto;
}
The answer from 'bjnsn' is good but not perfect as it fails when the text contains space in it. For example he used 'Centered?' as text but if we changed the text to let suppose 'Centered? or not' then it will not work fine and will take the next line after space. Ther is not width or height defined for the inner div block.
.inner {
font-size: 13px;
font-color: #878787;
position: absolute;
top: 50%;
left: 50%;
background: #DDD;
}
https://jsfiddle.net/touqeer_shakeel/f1gfy1yy/
But we can make the whole text centered align properly, by setting the inner div width equal to height of the outer div, line-height of inner div equal to the width of the outer div and setting the display flex property for inner div with align-items:center and justify-content:center properties.
.inner {
font-size: 13px;
font-color: #878787;
position: absolute;
top: 50%;
left: 50%;
display: flex;
justify-content:center;
align-items:center;
line-height:40px;
}
$('#height').on('change', function(e) {
$('.outer').css('height', $('#height').val() + 'px');
$('.inner').css('width', $('#height').val() + 'px');
});
updated fiddle https://jsfiddle.net/touqeer_shakeel/cjL21of5/
Removing : margin-top: -7px; from .inner made the vertically rotated text centered for me. It also made the horizontal text not centered.
Just remove the above code?
You could add this:
$('.inner').css('margin-top', $(this).parent().height() - 2*$(this).height());
To your .on('change') function, as you can see here: http://jsfiddle.net/darkajax/hVhbp/