Tricky vertical align center with css - html

I found different suggestions on how to vertically align stuff using css. However, none of those could handle what I wanted. Here is what I want:
In general I have some text that should fill the left half of some space and a picture that should be in the right half of the space.
If the height of the text is smaller than the picture both text and picture should vertically align at top of the space:
TextTextText PicturePicture
TextTextText PicturePicture
PicturePicture
If the height of the text is greater than the height of the picture, then the the text should vertically align on top and the picture at the middle relative to the text.
TextTextText
TextTextText PicturePicture
TextTextText PicturePicture
TextTextText PicturePicture
TextTextText
Here is one straight forward way I tried (text-version without picture):
<div style="width: 100%">
<div style="width: 50%; display: inline-block; vertical-align: top;">
TextTextText <br>
TextTextText <br>
TextTextText
</div><div style="width: 50%; display: inline-block; vertical-align: middle;">
PicturePicture <br>
PicturePicture
</div>
</div>
However, the effect I intended was not achieved. The right inner div (Picture) is just aligned on top rather than in the middle relative to the text. There is no difference between setting vertical-align: middle and vertical-align: top. However, interestingly setting vertical-align: bottom makes a difference.
The outer div is contained in some other element of a certain width. However, I cannot specify this width by any fixed measure, e.g. px. Same for the two inner divs with equal width.
Making the inner divs table cells achieved the right vertical effect. However, I cannot use display: table-cell, since I need to make sure that the left inner div maintains its width even though the right inner div could have content that overflows to the right, like PicturePicturePicturePicturePicture.... This would lead to shrinking the width of the left cell, which I don't want.
Furthermore, I do not know the height of the content, so none of the tricks for vertical alignment that use a fixed height works.
It seemed not an too uncommon task, but I was unable to find any solution. Is it possible to do this?

It's not clear to me what behaviour you want when the picture is too wide for the right inner div, other than it should not affect the width of the left inner div, but does this meet your requirements?
HTML.
<div class="container">
<div class="caption cell">
Text Text Text <br/>
Text Text Text <br/>
Text Text Text <br/>
Text Text Text <br/>
Text Text Text <br/>
Text Text Text
</div>
<div class="picture cell">
<div>
<img src="http://placehold.it/500x50" />
</div>
</div>
</div>
CSS
.container {display:table; table-layout: fixed; width:100%; }
.cell { display: table-cell; width:50%; }
.caption { vertical-align: top; }
.picture { vertical-align: middle; }
.picture div { overflow-x:hidden; }
JSFiddle at http://jsfiddle.net/92wcy/1/

If you don't want the left column to shrink then add a min-width to it.
http://jsfiddle.net/pUbWt/1/
.container {
display: table;
width: 100%;
}
.container .caption, .container .picture {
display: table-cell;
}
.container .caption {
vertical-align: top;
min-width: 10em;
}
.container .picture {
vertical-align: middle;
}
Flexbox would also work, but its a little early to start using in production sites.

Vertical alignment is always tricky as CSS wasn't made to accomplish that.
Still, is this what you were after? http://jsfiddle.net/N7px2/
If so, read on.
First, I removed your inline styles as this is bad practice. Simply use <style>...</style> in the head of your HTML, or even better: Use an external CSS file.
Then, I floated your divs #b and #c to align them like in your example. See the background-color and border to get a quick idea where each element is placed.
Because floats let the parent element collapse, I used a clearfix to fix that. Read more about that here.
Now the vertical alignment: I positioned the image in #c absolute and gave it a margin top: 50%. Obviously that pushed the image too much, but that's how it works. After that, I applied a negative margin-top: -25% to pull the image back in place. Please take note that this only works if the parent element is relative positioned.
The browser support for negative margins is really good and as long they aren't used to fix a bad layout it's alright to use them.
And another note: Because position: absolute takes an element out of the flow, #c collapses. If you wanted to give #c a background-image or something similar, you need a bit more markup to fix that - simply add another div.
Hope that helped you in any way!
Edit: Sorry, I just realised that this code isn't exactly what you were after I believe.

Related

Block to the right with text align to the left (no float, one div only)

I want a container block with the same width as that of its longer child. The block most be posionated to the right with its content align to the left (as in the image). Is there a way to accomplish this with no float property and using only one div?
try this and check this fiddle
.box {
width: 40%;
margin-left: auto;
}
I'm not 100% on what you are asking for, but here is a JSFiddle using p elements inside of one div.
https://jsfiddle.net/3ct2syhp/
CSS
.box {
display: inline-block;
margin-left: 50%;
}
HTML
<div>
<p>
I want a container block with the same width as that of its longer child. The block most be posionated to the right with its content align to the left (as in the image). Is there a way to accomplish this with no float property and using only one div?
</p>
<p class="box">
I want a container block with the same width as that of its longer child. The block most be posionated to the right with its content align to the left (as in the image). Is there a way to accomplish this with no float property and using only one div?
</p>
<p>
I want a container block with the same width as that of its longer child. The block most be posionated to the right with its content align to the left (as in the image). Is there a way to accomplish this with no float property and using only one div?
</p>
</div>
The elegant way:
div {display: table; margin-left: auto; text-align: left;}

CSS increase container width when text inside overflows to the right?

When you do something like:
.container {
column-width: 200px;
height: 300px;
}
<div class="container">
... a lot of text...
</div>
If the text is large enough it will cause that the corresponding text overflows the container width to the right. That's awesome if you want an horizontal layout, however, the div width won't grow because the text has "overflow" the container. If you put a background to the div you will see that the background won't be there after the end of the screen (if the text is sufficienty large). That why, if you put a second div next to this one in an horizontal fashion, the second will be over the overflowed content of the first div, which is undesirable.
The question is: how can I make the first div be adjusted to the content inside him no matter how large it becomes in the horizontal line?
I would probably do it like this (if i understood what you want)
.container {
width: auto;
height: 300px;
}
.text{
Padding-left: 10%;
Padding-right: 10%;
}
<div class="container">
<div class="text">
... a lot of text...
</div>
</div
The container should now change size depending on the text. :)
With CSS3 Intrinsic Sizing, you can use this: width: max-content which expands the width of the parent container based on text it encloses.
Caution - not supported in IE. Check this: https://caniuse.com/#search=max-content

Why inline-block container cause scrollbars on auto overflow?

This is a very simple case:
http://jsfiddle.net/8j6rt02h/
<div class="outerContainer">
<div class="innerContainer-inlineBlock">
<div class="content">
</div>
</div>
</div>
css:
.outerContainer{
width: 100px;
height:100px;
overflow: auto;
}
.innerContainer-inlineBlock{
display: inline-block;
}
.content{
background-color: blue;
width: 100px;
height:100px;
}
The outer container is having auto overflow while the inner container is having inline-block display. Then even if the content size is the same or even a little bit smaller than the containers, the scrollbars still show.
If I use block display for the inner container, it behaves as expected.
I have tried on both Chrome and IE, both have this issue.
Anyone can give a little bit explanation?
The inner container, being an inline-block, sits on a baseline which is raised slightly above the bottom edge of the outer container (to make room for descenders). Since the outer container is exactly the same height as the inner container, there isn't enough space to accommodate the area below the baseline, resulting in overflow.
Changing the inner container to a block does away with the baseline entirely, because there is no other inline content.
inline-block elements have margins on them so causing that scrollbar to appear. If you set -4px margin on them you won't see the scrollbar.
.innerContainer-inlineBlock{
display: inline-block;
margin: -2px;/*left and right -2-2=-4px*/
}
demo
If you consider using float instead of inline-block then you won't see the scrollbar because there is no margin space on them. demo

Vertical centering of multiple images inside one DIV

I have a simple DIV with a fixed height like and several images with individual heights inside (their height is equal or less the height of the outer DIV):
<div>
<img src="..">
<img src="..">
...
</div>
This markup is as-is and can not be changed. I need to display all images side by side and all images should be vertically aligned with the middle of the DIV (so the padding top and bottom is identical per-image).
How to do that without changing the markup? Various answers deal with a markup where the image is placed itself inside a DIV which is not the case here.
After re-reading your question, that the <div> is at least as high as the highest image, simply do this:
CSS
img {
vertical-align: middle;
}​
Try it here: http://jsfiddle.net/AsD9q/
You can also prevent the div from breaking (when the viewport is to small) by setting an explicit width or using white-space: nowrap; on the container: http://jsfiddle.net/MvDZJ/ (using width) or http://jsfiddle.net/xMtBp/ (using white-space)
That's the outcome:
First answer, which works with every height of the div:
As you said nothing about container itself, I assume, that it's not wider than the viewport. Than you could simply do something like this:
HTML
<div>
<img src="http://lorempixel.com/200/100/">
<img src="http://lorempixel.com/200/80/">
<img src="http://lorempixel.com/200/120/">
<img src="http://lorempixel.com/200/60/">
</div>​
CSS
​div {
display: table-cell;
vertical-align: middle;
/* only added for demonstration */
height: 200px;
border: 1px solid red;
}
img {
vertical-align: middle;
}
This won't work in IE7 though, as it can't handle display: table-cell. You can try it here: http://jsfiddle.net/3vXXy/.
This can be done with jQuery, the problem is you have no explicit selectors to work with so it would affect every image in every div on the page.
First you need to set the images to the top of the div like this in the CSS:
div img{vertical-align:top;}
Then take each image in succession, get it's height and set it's top padding to half the difference between the height of the div and the height of the image.
​$(document).ready(function(){
$("img").each(function(){
var margin= ($(this).parent().height() - $(this).height())/2;
$(this).css('margin-top',margin);
});
});​
Again, not an ideal solution without good solid selectors, but it does work. http://jsfiddle.net/calder12/H4Wkw/

Float right without changing order, forced shrink

This problem is probably quite easy to solve but I'm not sure what I do wrong.
I have the following code:
HTML:
<div class='absolute'>
<div class='container'>
<span>blabla</span>
unknown number of spans..
</div>
</div>
CSS:
.absolute{
position: absolute;
bottom: 0px;
right: 0px;
}
.container{
float: right;
}
span{
display:block;
float: left;
}
Basically what I want is to have all the spans in one straight line at the bottom right. The absolute div works perfectly and container div float right exactly like I want. The problem is that the spans refuse to line up in one row. I get the following look:
The red is absolute div, the blue the container div and the green the spans. Well you see my problem..
I have tried to give the container div a width. This result in a straight horizontal line, like the one I want, except that the spans float to the left as far as the width of the blue container div. And I can't calculate the width because I don't know the number of spans.
So how do I solve this without changing any order and without setting a width to the container div? Or rather, why does the container div shrink at all and not just stay as wide as the floats wants it to be?
Thanks for any answer!
change display:block to display:inline-block?
Change you span to:
display: inline-block;
should make them go next to each other.
This isn't supported in IE7 or earlier though, if that's important to you, you can do this:
display: inline-block; *display: inline;
Oh and remove the float left on the span.