Vertical Align to bottom with single Element - css

I have a holder div that has specific dimensions, and has a single child element of varying height, and I am trying to align it to the baseline. Currently, I have a second element that is the same fixed height as the container which makes it aligned to the bottom, but if it is on its own, it sticks to the top, regardless of what rules are applied.
So, how can I vertically align an element to the bottom of a container if it is the only child element?
EDIT
While in the process of putting up the code that I am using, I came up with a solution which I have posted. The initial problem is similar to that, but without the position rules, and display:inline-block on the child elements. That is pretty much the long and short of it...

Damn it, thought of a solution after posting the question which works nicely:
Parent Element:
.parent {
height:200px;
position:relative;
width:200px;
}
Child Element:
.parent > * {
bottom:0px;
left:0px;
position:absolute;
right:0px;
}
The height of the Child element is then defined by block elements within it, but it sticks to the bottom

One way using table-cell
Assuming the bare bones markup:
<div class="wrap">
<div>Some content...</div>
</div>
the following CSS will do it:
.wrap {
border: 1px solid red;
height: 200px;
width: 200px;
display: table-cell;
vertical-align: bottom;
}
Major advantage: works with both inline and block level elements.
Disadvantage: Older browsers don't recognize display: table-cell
Demo at: http://jsfiddle.net/audetwebdesign/eXKbt/
Alternate way using inline-block
You can also do it this way by applying the following CSS:
.wrap2 {
border: 1px solid red;
height: 200px;
width: 200px;
}
.wrap2:before {
content: "";
width: 0;
height: 190px;
display: inline-block;
}
.wrap2 div {
display: inline-block;
width: 190px;
border: 1px dotted red;
vertical-align: bottom;
}
However, this approach involved using a pseudo-element to define a fictitious inline block to set a baseline nearly the full height of the box and then using vertical-align on the child element. There were some issues related to the width but it can be made to work.
See earlier fiddle for demo.

Not much detail to go off of, but maybe something like this
.container {
position: relative;
}
.child-element {
position: absolute;
bottom: 0;
}

Related

Possible for an element to 'escape' the constrained boundaries of a div with fixed dimensions and overflow:hidden?

One for the CSS gurus - is it possible for a div to 'escape' the constrained in the boundaries of a div with fixed dimensions and overflow:hidden?
Ive recreated the example here: http://jsfiddle.net/Wt3q4/1/
Ive tried setting z-indexes on all the elements, and assigning the div with class b position:absolute with no joy.
Since .b is nested with an element that's position:relative;, setting .b to absolute won't do anything. That I know of, with the element structure you have defined, there isn't going to be a CSS work around.
Without knowing more about your layout and what you're trying to accomplish, it's difficult to advise. You could try setting up a "double container" if that makes sense, and use a jQuery function to move the element out of the overflow:hidden; element when you want to show it.
http://jsfiddle.net/Wt3q4/3/
HTML
<div class="a">
<div class="b">
<div class="c">
</div>
</div>
</div>
<div id="show" class="button">Show!</div>
<div id="hide" class="button">Hide!</div>
CSS
.a{
position:relative;
height:200px;
width:200px;
border:3px solid #f00;
background:#ccc;
}
.b{
position:relative;
height:200px;
width:200px;
background:#ccc;
overflow: hidden;
}
.c{
width:50px;
height:300px;
border:3px solid #00f;
background:#dad;
margin:30px;
position:absolute;
z-index:333;
}
.hidden{
display: none;
}
.button {
width: 50px;
padding: 5px;
text-align: center;
border: 3px solid #aaa;
background: #ddd;
margin: 20px;
float: right;
}
jQuery
$('#show').on('click', function(){
$('.c').prependTo('.a');
$('.b').addClass('hidden');
});
$('#hide').on('click', function(){
$('.c').prependTo('.b');
$('.b').removeClass('hidden');
});
Based on my understanding of CSS's block formatting context, your div.b is a child of div.a, which means that div.a sets the block formatting context for div.b. Once you set overflow: hidden on the parent element, any child content that flows out of the parent content box will not be visible.
This is more apparent if you set outline: 1px solid black on the parent container so that you can see the extend of the content box, both with overflow hidden and visible.
Your question does touch on the essentials of CSS's visual formatting model.
How about something like:
.menu > li > ul {
position: absolute; /* you still need this here */
background-color: #9F26B4;
width: 10000000000000000px;
margin-left: -100000px;
padding-left: 100000px;
list-style: none;
z-index: 1000;
top: 0;
left: 0;
}
This, for example, overflows the entire page from left to right (assuming that the body overflow-x is set to hidden) and then set element width to enormous width, margin it to negative left to fill any left content, and padding to the left to move object inside the element to desirable X position. What you think?

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.

float overflow and position conflict

I have a problem with a float which overflows (JSFiddle here).
HTML
<div id="father">
<div id="son">
gruik
</div>
<div id="dog">
gruikgruik gruik gruik gruikg ruik gruik gruikgr uikgruik gruik gruik gruik
</div>
</div>​
CSS
div { border: solid; }
#father { width: 300px; position: relative; }
#father:after { content: ""; display: block; clear: both; }
#son { width: 100px; float: left; border: solid red; }
#dog { float: left; border: solid blue; position: absolute; left: 105px; }
As you can see, #dog overflows from #father. I tried classical CSS techniques but they just do not work (neither the clearfix method, nor overflow:hidden; or overflow:auto;).
I think the problem appears because of the use of the position CSS properties but I need it.
position: absolute; is correctly positioning the #dog element relative to #father (because #father has position: relative;).
However it is only the #son element which is giving #father its height. Elements positioned absolutely are taken out of the flow and therefore if #dog increases in height, its parent container (#father) will not, and therefore #dog looks to be overflowing.
Why do you have to use position: absolute; on #dog?
Can you not just use float, and set its width? You are setting its parent and siblings widths anyway so you know what width it should be (if you specify the width of the borders too).
DEMO: http://jsfiddle.net/sgw4K/5/
EDIT/UPDATE: After discovering additional styling, thirtydot has recommended two sound fixes to the problem. See comment below or the following:
To fix that, you can remove float: left from #son and then pick one of
these two choices: margin-left: 52px or overflow: hidden; on the #son element.

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>

vertical alignment of image inside a div

I want to set vertical alignment of image inside a div. I use img { vertical-align:middle}
but it is not working.
Using the line-height property will solve the problem:
<style>
.someclass {
width: 300px;
height: 300px;
text-align: center;
line-height: 300px;
border: dotted;
}
.someclass img {
margin: auto;
vertical-align: middle;
}
</style>
<div class="someclass">
<img src="someimg.jpg" border="0" alt="">
</div>
This is a solution that doesn't require JavaScript (as my previous solution did).
You can achieve what you want by assigning display: table-cell to the containing div. Here's an example: http://jsbin.com/evuqo5/2/edit
I feel I must warn you that you will need to test this in every browser you intend to support. Support for the table-cell value is fairly new, particularly in Firefox. I know it works in Firefox 4, but I don't know about any of the 3.x iterations. You'll also want to test in IE (I've only tested in Chrome 10 and Firefox 4).
The CSS:
div#container {
width: 700px;
height: 400px;
position: relative;
border: 1px solid #000;
display: table-cell;
vertical-align: middle;
}
div#container img {
margin: 0 auto;
display: block;
}
You won't need the div#container img styles if you don't also want to horizontally align the image.
If you're trying to do what I think, vertical align isn't going to work; you'll need to use positioning.
In general, position the container relative, and then position the image absolute, with top and left set to 50%, and then move the image back to the center by setting negative margins equal to half the width / height.
Here's a working example: http://jsbin.com/evuqo5/edit
Basic CSS is this:
#container { position: relative; }
#container img {
position: absolute;
left: 50%;
top: 50%;
margin-top: /* -1/2 the height of the image */
margin-left: /* -1/2 the width of the image */
}
See this awser: How to vertical align image inside div
If you want to align horizontally also, add the right and left, like this:
div {
position:relative;
}
img {
position:absolute;
top:0;
bottom:0;
left:0;
right:0;
margin:auto;
}
The following post has some useful references:
Text Alignment w/ IE9 in Standards-Mode
Also, depending on which version of IE you are testing against, you may end up needing some browser-specific hacks or some jQuery/JavaScript code.
If you have to, use a one-row-one-cell table and take advantage of the vertical-align property. This is brute-force, not overly semantic, but it works.
If you set the div display attribute to table-cell then vertical-align: middle; will work.
The vertical-align rule only affects table cells or elements with display: table-cell.
See this article from SitePoint for a detailed explanation.
<style>
/* change body to .someClasses's parent */
body {
width: 100%;
height:  100%;
display: table;
}
body > .someclass {
width: 300px;
height: 300px;
text-align: center;
border:dotted;
margin: 0 auto
display: table-cell;
vertical-align: middle;
}
</style>
<body>
<div class="someclass">
<img src="someimg.jpg" border="0" alt="">
</div>
</body>

Resources