Aligning HTML elements to the middle of the parent without JavaScript - html

I want to place a <div> in the middle of an element. Aligning it horizontally is easy, and of course the vertical alignment can be done with JS, but I'm sure that there's a better way of doing this with CSS. What's the trick?
P.S. I need this for an application with the HTML5 <canvas> element, so I don't mind if the solution only works in browsers that support canvas and in IE 7,8 (which support canvas when using a plugin).
edit: the height (and width) of the div are resizable in browsers that support the CSS3 property resize. However, I don't mind about it too much.
another edit: I also don't know the height of the div (even if it hasn't been resized).
edit: see live demo
here
this example uses JS. (Loktar - thanks for the link).
Thanks();

Live Demo
One way to align vertically is to set the line-height to the height of the container.
#parent{
width: 200px;
height: 300px;
line-height: 300px;
text-align:center;
}

If the element you want to align has a fixed size, give it absolute position and make its top and left 50%. Then subtract half its height for its margin-top and half its width for margin-left. e.g.
html:
<div id="container">
<div id="alignedcontainer">content</div>
</div>
css:
#container {
position: relative;
}
#alignedcontainer {
position: absolute;
width: 500px;
height: 400px;
top: 50%;
left: 50%;
margin-top: -200px;
margin-left: -250px;
}

You can also use display:table, display:table-cell, and vertical-align:center like here to center. It will adjust to fit content, but unfortunately the width will remain 100% of the container. You can see it used here

This works in Chrome
<html>
<head>
<style>
#outer
{
position: relative;
border: 1px solid #000;
width: 400px;
height: 400px;
margin: 20px;
padding: 20px;
}
#inner
{
position:absolute;
top:25%;
right:25%;
bottom:25%;
left:25%;
width: 200px;
height: 200px;
background-color: #ccc;
}
</style>
</head>
<body>
<div id="outer">
<div id="inner"></div>
</div>
</body>

If the element does not need to wrap, a quick and dirty way is to set the line height equal to the div height (assuming it's a static height).

Related

Adjust size of centered div with fixed div at the left on pure CSS

How to automatically adjust size of the div which is horizontally centred, using another div which has position: fixed property?
To better understand what I mean please take a look at the picture below. Div A is a fixed div with a fixed size and div B is a div which is horizontally centred. I want div B to resize (when I resize browser window) in a such way so right border of A and left border of B never overlap (ideally, if the distance between the borders kept the same).
I know that this can be fairly easy done using JavaScript by reacting on resize events, but I'm wondering is there any way to achieve this in pure CSS?
Here's another way. This should work in older browsers too.
<style>
div {
border: 1px solid red;
height: 100px; }
#A {
position: fixed;
width: 150px; }
#B {
margin: 0px 155px; }
</style>
<div id="A">Stuff</div>
<div id="B">Stuff</div>
How about this:
#a{
width:200px;
}
#b{
width:calc(100% - 400px);
}
Just set the width of B to be 100% of screen width minus twice the width of A and their borders will touch.
When an element is given the settings position: absolute or position: fixed You can change the width of an element by using the left and right properties.
Simply add the same amount to the right as you would to the left
#left {
position: absolute;
width: 150px;
}
#middle {
position: absolute;
left: 165px;
right: 165px;
overflow: auto;
}
/* For demo purposes */
html, body, div { height: 100%; margin: 0; } div { background: red; } #overflow { height: 200%; }
<div id="left"></div>
<div id="middle">
<div id="overflow"></div>
</div>

Css: Position element by it's bottom relative to it's container's top

I have an div element with variable height which I need to be positioned by it's bottom relative to the containers top.
This must be done without changing the html.
e.g.
<div id="container">
<h1>Some Text<br/>more...</h1>
</div>
h1's bottom should be 100px below #container's top.
Thanks a lot
EDIT:
So by Request what I did (or didn't) tried:
Searching with Google for css bottom top position relative but that's not the best search terms in the world...
Normally I would put a container around h1 and give it a height of 100px but then I would need to change the html and that I can't
using bottom: somevalue but that positions the element's bottom relative to the container's bottom.
slain some vampires
You could make use of transform: translateY(-100%), to make the bottom of the element relative when you apply margin-top: 100px to h1.
#container {
width: 200px;
height: 200px;
background: tan;
overflow: hidden;
}
#container h1 {
transform: translateY(-100%);
margin-top: 100px;
background: papayawhip
}
<div id="container">
<h1>Some Text<br/>more...</h1>
</div>
Depending on browser support requirements:
#container {
position: relative;
}
#container h1 {
position: absolute;
bottom: calc(100% - 100px);
}
Example
Only way through it is to add a height to the h1 unless you want to go with calc which isn't supported yet by some browsers. Then set your top margin to be top: 100px - h1's height. Hope this works
<div id="container">
<h1>Some Text<br/>more...</h1>
</div>
#container {
width: 300px;
height: 300px;
background: #222;
overflow: hidden;
}
#container h1 {
background: #444;
position:relative;
height:80px;
top:20px;
}
http://jsfiddle.net/ms889w57/
#container
{
position: absolute;
height: 100px;
bottom:0px;
}
This code is not affecting html at all. I added css for id-container.
An absolute position element is positioned relative to the first parent element that has a position other than static. You can change it to fixed it you wants to.
Height of the container, help you to calculate spacing from bottom.

How to position a div to the bottom of the container, without using absolute positioning?

I have a really difficult CSS problem. I have the following layout (this is just a fast mockup in Paint):
I need to float the red box to the bottom of it's container. Normally I would use position: absolute; bottom: 0; but that results in the text overlapping with the div, which I don't want. I want the box to behave like in the second image (same situation, but with more text)
Is this even possible? I don't mind dumping support for very old browsers.
Don't abandon position: absolute. Simply add padding to the bottom of the container equal to the height of the footer div.
#outer{
position: relative;
padding-bottom: 55px;
}
#foot{
position: absolute;
height: 55px;
width: 100%;
bottom: 0;
left: 0;
}
Without padding: http://jsfiddle.net/cG5EH/2
With padding: http://jsfiddle.net/cG5EH/1
Try this. calc allows you to make calculations within your css. In the example I am forcing the height to be 100% but this can be any value it could even be height: calc(100% + 80px). Note the spaces around the maths operator.
see http://css-tricks.com/a-couple-of-use-cases-for-calc/ for more details
<html>
<header>
<style type="text/css">
.container{
height:100%;
padding-bottom: 80px;
box-sizing: border-box; //ensures the padding is part of the 100% height.
position:relative;
background-color: blue;
}
.base{
position:absolute;
top:calc(100% - 80px);/*80px arbitary height of the element*/
height:80px;
width:100%;
background-color: yellow;
}
</style>
</header>
<body>
<div class="container">
<div class="base">
sdfgsdfg
</div>
</div>
</body>

Centering <div> without using "margin: auto;"

I'm looking for a way to center a div horizontally in the page on Google Chrome.
I tried using margin: auto; but I've read that this function is not supported in Google Chrome. As a result my div stays aligned to the left side of the screen.
If I use, for example, margin-left: 100px; the div does move toward the center of the page, but I don't want to center it manually.
HTML:
<body>
<div id="header">
<p>John Doe</p>
<p>email</p>
</div>
</body>
CSS:
body
{
background-color: #f0f0f0;
}
div
{
border-radius: 5px;
}
#header
{
position: fixed;
background-color: #3399ff;
color: white;
width: 60%;
margin: auto;
}
#header p
{
display: inline;
}
margin: auto will not work on a fixed (or absolute) position div. Instead you need to set left: 50% and the left margin to negative half of the element width.
#header
{
position: fixed;
width: 60%;
left: 50%;
margin-left: -30%;
}
http://jsfiddle.net/ZAqJM/
UPDATE: as of now most browsers will support transfrom: translate so you can comfortably do:
{
position: fixed;
left: 50%;
transform: translateX(-50%);
}
I know this is quite old but I think is worth mentioning that the following works like magic:
#header {
left: 50%;
transform: translateX(-50%);
}
For future references.
Centering a <div> using margin: auto; works cross browsers. You need to make sure the div that you're trying to center is contained in a block-level element.
<div class="headerContainer">
<div id="header">
<p>John Doe</p>
<p>email</p>
</div>
</div>
To properly center, your div#header needs to be block-level and must have a width and is a child element of a block-level element. (Technically <body> is block-level but you might want to maintain your header's "containership")
Therefore, remove the position: fixed from #header { ... }. Please see working example: http://jsfiddle.net/amyamy86/2sXdC/
margin:auto is for the object that has width and set the left-right margin equally.
Div is basically BLOCK with FULL-WIDTH (100%) so set margin:auto is doesn't get anything since the width is full to the parent.
To make it work, you can did that by 2 ways,
use text-align:center for div -> this will align text inside div center
include width property in div (i.e. width:200px) and it will work fine.

How to set the margin or padding as percentage of height of parent container?

I had been racking my brains over creating a vertical alignment in css using the following
.base{
background-color:green;
width:200px;
height:200px;
overflow:auto;
position:relative;
}
.vert-align{
padding-top:50%;
height:50%;
}
<!-- and used the following div structure. -->
<div class="base">
<div class="vert-align">
Content Here
</div>
</div>
While this seemed to work for this case, i was surprised that when i increased or decreased the width of my base div, the vertical alignment would snap. I was expecting that when I set the padding-top property, it would take the padding as a percentage of the height of the parent container, which is base in our case, but the above value of 50 percent is calculated as a percentage of the width. :(
Is there a way to set the padding and/or margin as a percentage of the height, without resorting to using JavaScript?
The fix is that yes, vertical padding and margin are relative to width, but top and bottom aren't.
So just place a div inside another, and in the inner div, use something like top:50% (remember position matters if it still doesn't work)
An answer to a slightly different question: You can use vh units to pad elements to the center of the viewport:
.centerme {
margin-top: 50vh;
background: red;
}
<div class="centerme">middle</div>
Here are two options to emulate the needed behavior. Not a general solution, but may help in some cases. The vertical spacing here is calculated on the basis of the size of the outer element, not its parent, but this size itself can be relative to the parent and this way the spacing will be relative too.
<div id="outer">
<div id="inner">
content
</div>
</div>
First option: use pseudo-elements, here vertical and horizontal spacing are relative to the outer. Demo
#outer::before, #outer::after {
display: block;
content: "";
height: 10%;
}
#inner {
height: 80%;
margin-left: 10%;
margin-right: 10%;
}
Moving the horizontal spacing to the outer element makes it relative to the parent of the outer. Demo
#outer {
padding-left: 10%;
padding-right: 10%;
}
Second option: use absolute positioning. Demo
#outer {
position: relative;
}
#inner {
position: absolute;
left: 10%;
right: 10%;
top: 10%;
bottom: 10%;
}
To make the child element positioned absolutely from its parent element you need to set relative position on the parent element AND absolute position on the child element.
Then on the child element 'top' is relative to the height of the parent. So you also need to 'translate' upward the child 50% of its own height.
.base{
background-color: green;
width: 200px;
height: 200px;
overflow: auto;
position: relative;
}
.vert-align {
position: absolute;
top: 50%;
transform: translate(0, -50%);
}
<div class="base">
<div class="vert-align">
Content Here
</div>
</div>
There is another a solution using flex box.
.base{
background-color:green;
width: 200px;
height: 200px;
overflow: auto;
display: flex;
align-items: center;
}
<div class="base">
<div class="vert-align">
Content Here
</div>
</div>
You will find advantages/disavantages for both.
This can be achieved with the writing-mode property. If you set an element's writing-mode to a vertical writing mode, such as vertical-lr, its descendants' percentage values for padding and margin, in both dimensions, become relative to height instead of width.
From the spec:
. . . percentages on the margin and padding properties, which are always calculated with respect to the containing block width in CSS2.1, are calculated with respect to the inline size of the containing block in CSS3.
The definition of inline size:
A measurement in the inline dimension: refers to the physical width (horizontal dimension) in horizontal writing modes, and to the physical height (vertical dimension) in vertical writing modes.
Example, with a resizable element, where horizontal margins are relative to width and vertical margins are relative to height.
.resize {
width: 400px;
height: 200px;
resize: both;
overflow: hidden;
}
.outer {
height: 100%;
background-color: red;
}
.middle {
writing-mode: vertical-lr;
margin: 0 10%;
width: 80%;
height: 100%;
background-color: yellow;
}
.inner {
writing-mode: horizontal-tb;
margin: 10% 0;
width: 100%;
height: 80%;
background-color: blue;
}
<div class="resize">
<div class="outer">
<div class="middle">
<div class="inner"></div>
</div>
</div>
</div>
Using a vertical writing mode can be particularly useful in circumstances where you want the aspect ratio of an element to remain constant, but want its size to scale in correlation to its height instead of width.
Other way to center one line text is:
.parent{
position: relative;
}
.child{
position: absolute;
top: 50%;
line-height: 0;
}
or just
.parent{
overflow: hidden; /* if this ins't here the parent will adopt the 50% margin of the child */
}
.child{
margin-top: 50%;
line-height: 0;
}
This is a very interesting bug. (In my opinion, it is a bug anyway) Nice find!
Regarding how to set it, I would recommend Camilo Martin's answer. But as to why, I'd like to explain this a bit if you guys don't mind.
In the CSS specs I found:
'padding'
Percentages: refer to width of containing block
… which is weird, but okay.
So, with a parent width: 210px and a child padding-top: 50%, I get a calculated/computed value of padding-top: 96.5px – which is not the expected 105px.
That is because in Windows (I'm not sure about other OSs), the size of common scrollbars is per default 17px × 100% (or 100% × 17px for horizontal bars). Those 17px are substracted before calculating the 50%, hence 50% of 193px = 96.5px.
A 50% padding wont center your child, it will place it below the center. I think you really want a padding-top of 25%. Maybe you're just running out of space as your content gets taller? Also have you tried setting the margin-top instead of padding-top?
EDIT: Nevermind, the w3schools site says
% Specifies the padding in percent of the width of the containing element
So maybe it always uses width? I'd never noticed.
What you are doing can be acheived using display:table though (at least for modern browsers). The technique is explained here.
CSS Grid with empty row
This approach probably only makes sense if you're already using css-grid for the container in question, but if you are you can create an empty row with a percentage that (because it is a row) will be a percentage of the height.
.wrapper
{
border: 2px solid red;
width: 400px;
height: 200px;
display: grid;
grid-template-rows: 10% 1fr;
}
.child
{
background: orange;
width: 50px;
height: 50px;
grid-area: 2/1;
}
<div class="wrapper">
<div class="child">
</div>
</div>