I am looking to vertically center a <div> in the viewport (browser window) without resorting to Javascript (pure HTML and CSS only). I have several constraints:
The div must be centered vertically in the viewport. Methods I have seen only support centering inside another <div>, which is not what I want.
The height of the div is not known.
Other constraints:
The div must be aligned to the right.
The div has a constant width.
The div must support padding.
Other elements will be placed on the web page. The div acts as a menu.
The div must support a background colour/image.
This gets me close to what I want, but not exactly:
#nav {
position: fixed;
right: 0;
top: 50%;
}
However, the top of the nav is in the middle, not the middle of the nav.
Is there some technique which allows me to center my div with these constraints?
What's that? Taking 8 years to get the answer to a problem is too much?
Well, better late than never!
You got really close to the solution. I'd do it with transform: translate():
#nav {
position: fixed;
right: 0;
top: 50%;
transform: translateY(-50%);
}
According to Can I use?, it is supported by everything except for IE8- and Opera Mini (which, to be honest, is a pretty good support).
I'd recommend you overkill it a bit and just add all of the vendor prefixes (just to make sure!):
#nav {
position: fixed;
right: 0;
top: 50%;
-webkit-transform: translateY(-50%);
-moz-transform: translateY(-50%);
-ms-transform: translateY(-50%);
-o-transform: translateY(-50%);
transform: translateY(-50%);
}
Here's a snippet to show it to you in action:
#nav {
right: 0;
top: 50%;
position: fixed;
-webkit-transform: translateY(-50%);
-moz-transform: translateY(-50%);
-ms-transform: translateY(-50%);
-o-transform: translateY(-50%);
transform: translateY(-50%);
background-color: #ccc;
padding: 20px;
}
<div id="nav">
ABC<br/>
DEFGH<br/>
IJKLMNO<br/>
PQRS<br/>
TUVWXYZ
</div>
Hopefully it's still relevant to you! (who am I kidding, it's been 8 years)
you can use this as one of the solution.
<style>
#containter {
height: 100vh; //vh - viewport height
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
#content {}
</style>
<div id="containter">
<div id="content">
any text<br>
any height<br>
any content, for example generated from DB<br>
everything is vertically centered
</div>
</div>
If the item is set to position: fixed or position: absolute:
top: 50%; left: 50%; transform: translate(-50%, -50%)
If the item is set to position: relative, use:
margin-top: 50%; margin-left: 50%; transform: translate(-50%, -50%)
(More info at the source.)
Example:
Run the snippet and then resize this page (or rotate device). The box stays centered in the "snippet viewport".
.myContainer {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border: 5px solid RebeccaPurple;
}
.myThing {
width: 100px;
height: 100px;
background-color: CornflowerBlue;
}
<div class="myContainer">
<div class="myThing myContents">
</div>
</div>
The easiest way is not to use a div - use a table with one row and one cell. Vertical alignment is woefully unsupported in CSS and you will find yourself coding up the wall and across the ceiling to accomplish it.
I understand the semantic argument against what I have just proposed - I am a proponent of semantic markup in most cases. However I also believe in using the right tool for the right job. I believe it is best to sacrifice a little purity in this case for a simple solution that will work.
Related
I need to render a frame (ie, a picture frame around a picture) by rotating an image:
0 degrees for the left
90 for the top
... and so on.
As far as I can tell there isn't a border-image-left|right|top|bottom property, although this would work too - please correct me if I'm wrong.
It seems I'll need to use the border-image property. Does anyone know if possible to rotate the image depending on the side?
I guess the other messy options would include
Creating four div's around the image
Manually generating a frame border image (this won't really work as 1. we've got over 300 images, and 2. the frames need to be used on images with different aspect ratios... )
Edit: 'depending on the side' = 0 degrees for left, 90 degrees for top, 180 degrees for right, 240 for bottom... See image below for an example.
Left hand border image
Partially forced, but wrapping it in a div and span and playing with pseudo elements and transforms seemed to work.
The image is wrapped in an .img-container div and a span, and the ::before and ::after elements are absolute positioned around the image.
Here's the markup:
<div class="img-container">
<span>
<img src="https://unsplash.it/300/300?image=200">
</span>
</div>
And the styling:
.img-container, span, img{
display: block;
position: relative;
}
/* Image border general */
.img-container::before,
.img-container::after,
span::before, span::after{
content: "";
position: absolute;
left: -30px;
top: 50%;
width: 30px;
height: 100%;
transform: translateY(-50%);
background-image: url("https://i.stack.imgur.com/0UI1w.png");
background-size: 100% 100%;
z-index: 2;
}
/* Specific to the right border */
.img-container::after{
left: auto;
right: -30px;
top: 50%;
transform: translateY(-50%) rotate(180deg);
}
/* Top and bottom border general */
span::before,
span::after{
top: 0;
left: 50%;
transform: translate(-50%, -50%) rotate(90deg);
}
/* Just the bottom */
span::after {
top: 100%;
left: 50%;
transform: translate(-50%, -50%) rotate(270deg);
}
May be a little much
Here's a fiddle
I'm trying to vertically center a box by using display: flex;, while it's working when the box is small enough, but when the box exceeds the window height, part of the content will be cut off.
Working example: http://codepen.io/woutr_be/pen/bVQXLe
Example with large height: http://codepen.io/woutr_be/pen/KdrOZm
It seems to be related to the body: { height: 100%; }, but when I remove that, the box isn't centered anymore: http://codepen.io/woutr_be/pen/MazNrE
I can't figure out how to make it work when the box has a large height.
This is generally what I tend to use when I need to align an element vertically. Try changing the height and width and you will notice how it automatically calculates to center the element.
div.container{
width: 300px;
height: 300px;
position: relative;
background: salmon;
}
div.container > div.wrapper{
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
-moz-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
background: red;
}
<div class='container'>
<div class='wrapper'>
<label>Some text</label>
<label>Some more text</label>
</div>
</div>
You could simply add max-height: 90% to .modal-box. The 90% is a bit arbitrary, but will give you some padding around the modal.
I have a centered form on my page positioned using top and left values and css3 transformations.
<div class="middle">
<h1>This is blurry, or should be.</h1>
</div>
.middle {
position: absolute;
top: 50%;
left: 50%;
min-width: 390px;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
/** backface-visibility: hidden; **/
}
h1 {
padding-bottom: 5px;
border-bottom: 3px solid blue
}
Notice backface-visibility. When set to hidden, all problems are solved for me using chrome 42. It doesn't render blurry. For others however using the same chrome version, it renders blurry with it.
Here's what it looks like without BV: http://jsfiddle.net/mzws2fnp/
To you it may be blurry, to others it may not.
Here's what it looks like with BV: http://jsfiddle.net/mzws2fnp/2/
For some reason people see the border blurry however I do not. I know backface-visibility: hidden is meant to fix that, and it does for me, just not for others using the same browser as I. Strange.
Try -50.1%
transform: translateY(-50%) translateX(-50.1%);
EDIT:
I have found out, they are blurred when chrome dev tools are opened, try to close them and refresh
This is a bug in Google Chrome. I reported this issue to Google:
Rendering bug in css transform: it blurrs borders
<div class="middle">
<input type="text" />
</div>
.middle {
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translateY(-50%) translateX(-50%);
transform: translateY(-50%) translateX(-50%);
}
input {
border: 1px solid black;
border-radius: 4px;
}
var middle = document.querySelector('.middle');
setInterval(function(){
middle.style.paddingTop = middle.style.paddingTop === "0px" ? "1px" : "0px";
}, 1000);
Animated bug demonstration
When you use percentage, will play an odd number. will blurry borders,
using parseInt to assign the value is integer.
$(document).ready(function(){
$('.middle').css({
'top':parseInt($('.middle').position().top)+ 'px',
'left': parseInt($('.middle').position().left)+'px',
'transform':'none',
'-webkit-transform':'none'
});
});
.middle {
position: absolute;
top: 30%;
left: 50%;
min-width: 390px;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);}
h1 {
padding-bottom: 5px;
border-bottom: 4px solid blue}
.middle2 {
position: absolute;
top: 70%;
left: 50%;
min-width: 390px;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);}
h1 {
padding-bottom: 5px;
border-bottom: 4px solid blue}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="middle">
<h1>This is blurry, or should be.</h1>
</div>
<div class="middle2">
<h1>This is blurry, or should be.</h1>
</div>
In this specific case where you're using a solid border, you can try using a box-shadow instead of a border as a workaround. For example, replace: border-bottom: 3px solid blue; with box-shadow: 0px 3px 0px blue;
Use even number (2px or 4px) for the border. Odd number (3px or 5px) is giving that blur.
border-bottom: 4px solid blue;
there is little hack that can help to get any block as center middle.
in parent <div> where we add position: relative add below properties,
display: flex;
justify-content: center;
now add align-self: center; property with the block which we want to make center middle make sure that this block is absolute position.
Because translated element height is odd number. This will not occur when element height is even number.
This problem occurs when we add
transform: translateY(-50%) translateX(-50%);
OR
transform: translate(-50%, -50%);
it is still as an open issue in chromium bugs list.
My intention is to center a header <div>, but i'm not able to do it.
header {
height: 54px;
margin:0px auto;
width: 1150px;
background: #13171B;
position: fixed;
left: 0;
top: 0;
z-index: 990;
margin-bottom:10px;
}
Please help me.
margin: 0 auto can center elements in static or relative position only. Since your div is in fixed position you may try with
header {
position: fixed;
height: 54px;
width: 1150px;
...
left: 50%;
margin-left: -575px; /* 1150px/2 */
top: 0;
}
if you don't know in advance the width, a better solution involves css3 transformations, e.g.
header {
position: fixed;
height: 54px;
...
left: 50%;
transform: translateX(-50%);
top: 0;
}
My go to solution for centering is thus;
.parent {
position: relative;
}
.toCenter {
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%,-50%);
-moz-transform: translate(-50%,-50%);
-o-transform: translate(-50%,-50%);
-ms-transform: translate(-50%,-50%);
transform: translate(-50%,-50%);
}
This positions the .toCenter element vertically and horizontally centered to it's .parent.
If you needed to position only horizontally, each 'translate(-50%-50%)' in the element's style would become 'translateX(-50%)'. Similarly, if vertical alignment was required, you could use 'translateY(-50%)' instead.
The important thing here is that there is a limit to browser support. Essentially everything except IE will work fine, with anything from IE9 backwards causing issues. There are poly fills and hacks to get things to work however, and they're usually neater than having to create additionally classes or style sheets just for one piece of functionality.
It's because of the fixed position. Add/change the properties below:
left: 50%;
-webkit-transform: translateX(-50%);
-moz-transform: translateX(-50%);
transform: translateX(-50%);
I'm trying to have a popup that auto sizes to fit content based on screen resolution, while also remaining in the dead center of the screen both horizontally & vertically.
This is where I'm at so far:
.reveal-modal {
background: none no-repeat scroll 0 0 #eee;
border-radius: 5px;
width: 50%;
height: 50%;
left: 25%;
top: 25%;
padding: 2%;
position: absolute;
visibility: hidden;
z-index: 101;
}
.reveal-child {
display: block;
position: relative;
width: 100%;
height: 100%;
}
The effect is close, but still doesn't work in certain resolutions. In some places the container is too large while others it is too small. I'd ideally like the container to be only as big as the content requires.
The demo can be viewed on 104.131.228.107 and clicking the Register button
I dont understand you, but if u want something like this site you linked, than watch here how to do popup.
u can use jQuery for that.
$('.button').click(function(){
$(".content").animate({opacity:"0.3"},500,function(){
$(".popup").fadeIn();
});
});
$(".popup").click(function(){
$(".popup").fadeOut(function(){
$(".content").animate({opacity:"1"},500);
});
});
This may be what you're looking for?
I made a fiddle where I made the width static so there is no unnecessary whitespace in the modal.
This one scales to the 50% width and height just as you had it and stops at the minimum for your content using the "min-width" and "min-height" properties.
If you want to create different styles for different screen resolutions use media queries
Hope it helped
#myModal {
position: absolute;
width: 50%;
height: 50%;
min-width:500px;
min-height:230px;
left: 50%;
top:50%;
border-radius: 5px;
background-color: #fff;
-webkit-transform: translate(-50%, -50%);
-moz-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
-o-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}