Vertically center elements in CSS - css

I have two elements side-by-side. Element 2 is smaller than Element 1. Both elements do not have a fixed height. I need to vertically center Element 2. How do I achieve this using CSS?
Edited:
This is what I have so far:
<div id="container" style="width: 100%;">
<div id="img1" style="float: left;">
<img src="image1.jpg".../>
</div>
<div id="img2" style="float: right;">
<img src="image2.jpg".../>
</div>
</div>
img1's height will always be greater than img2's height. I want img2 to be aligned vertically-center. Hopefully this clarifies what I am trying to accomplish.

The most straightforward and clean way to do it is to use display: table and vertical-align. However, IIRC (it's been a while since I was up on browser compatibility issues) support for display: table and friends is absent from ... some common-then version of IE, perhaps? Anyway, adding other rules to make an adequate fallback if the display: table is ignored might be good.
<div id="container" style="display: table;">
<div id="div1" style="display: table-cell; vertical-align: middle;">
<img id="img1" src="image1.jpg" />
</div>
<div id="div2" style="display: table-cell; vertical-align: middle;">
<img id="img2" src="image2.jpg" />
</div>
</div>
(Of course the styles ought to be in a stylesheet; this is just matching your original example and not knowing the use case.)
The display values table, table-row, and table-cell basically perform exactly like HTML table, tr, and td, but you are permitted to omit any of them (as I do here, using table-cells directly within tables) and the layout engine will do the sensible thing.

Not easily. Some popular hacks include using display: table-cell and a parent using display: table (I don't remember if the valign="center" attribute is needed), or using absolute positioning with top: 45% or so (not precise, but OK for small elements).
To determine the best method, we need to know more about your layout. What are they centered within? Will/can there be a large Y-distance between elements 1 and 2? Does their parent have a fixed height? Do they both have the same parents, or is one a sibling of the other? What method are you using to place them side by side?
Keep in mind that many tricks require additional hacking to work in IE, and that using Javascript is just cheating and will make your site inaccessible/annoying to people with low vision (who may be using script-unaware screen readers), people with scripts disabled (esp. on mobile or command-line browsers that may not support them well if at all), search engines, etc. It's possible using only CSS (though you may have to add some container elements), but the exact method depends what exactly you're doing.

If you only need to support new browsers like Safari (e.g., building webapp for the iPhone), CSS3 offers an elegant approach with no floats or negative margins. All details here: http://www.html5rocks.com/en/tutorials/flexbox/quick/#toc-center

I don't think you can do this reliably without a table. Kevin's solution would probably work, unless you need to support IE (which most of us do). And, in this case, the table markup might actually be smaller than the div-based markup.

Put them both inside another element, give it a min-width and set the left and right margins to auto.

Related

Re-ordering div using CSS

I would like to re-order some div using only CSS if possible.
Here is the HTML sample I want to re-order:
<div class="block1">
Block1
</div>
<div class="block2">
<div class="subblock1">S-Block1</div>
<div class="subblock2">S-Block2</div>
<div class="subblock3">S-Block3</div>
</div>
And this is the graphical result I want:
S-Block1
S-Block2
Block1
S-Block3
I already tried playing with display: flex; and order: X but with no success. The main problem lays in the fact that I want to split the block2 before and after the block1. The flex display only allow me to change order of block of the same "level".
I would really like to have a solution that doesn't not use JavaScript to re-write the DOM (by taking subblock3 and putting it elsewhere to please my CSS) if possible.
It appears this is not possible and javascript is not an option for my problem.
Here is the sample code I used (jQuery needed).
$(".subblock2").prependTo(".form-wrapper");
$(".subblock1").prependTo(".form-wrapper");

How do you make a floated element fill the remaining horizontal space when it is between its fixed width siblings?

I am trying to create an accordion menu with multiple floated elements. I want all of the inactive menu items to collapse to a small fixed width (40px or so) and the active item to expand to the remaining width. I want the menu to be responsive/elastic, so only the inactive menu items will have fixed widths.
Below is an example of what I want my menu to look/function like (without using jQuery to set the widths)...
Accordionza - CodeCanyon.com
I was able to accomplish the desired effect when only two menu items are displayed by floating one of the elements and giving it a fixed width, while NOT floating the elastic item and giving it a width of 100%.
Two Columns (Works)
<style type="text/css">
#one {
float:left;
width:40px;
}
#two {
width:100%;
}
</style>
<div class="row">
<div class="col" id="one">One</div>
<div class="col elastic" id="two">Two</div>
</div>
Four Columns - Elastic In Between (Does Not Work)
<style type="text/css">
#one, #three, #four {
float:left;
width:40px;
}
#two {
width:100%;
}
</style>
<div class="row">
<div class="col" id="one">One</div>
<div class="col elastic" id="two">Two</div>
<div class="col" id="three">Three</div>
<div class="col" id="four">Four</div>
</div>
Please note: applying float:right; to the elements to the right of the elastic item did not work either...
The problem is that if the elastic element is NOT on the end of the row, then the menu items do not remain on a single row. Please examine the fiddle below to see what I mean...
jsfiddle
So how do I apply this desired elasticity to the elements that reside in between their siblings? I really really want to keep the markup as simple as possible. Thanks in advance!
Update: I am getting close to a solution, however there is a slight problem with every method I've attempted. I will break them down, along with the issues I'm running into with each one.
METHOD 1: display: table-cell; (Suggested by onetrickpony)
Seemed like the answer, however there will not always be contents (text or html) inside the slide elements, and elements formatted with the display: table-cell; property do not recognize applied widths unless there is content inside of them. So this only works if I have content inside the slide... (I could modify the markup of my slider, but I would like to keep it the way I have it).
METHOD 2: CSS calc() (Also suggested by onetrickpony)
Not supported by some of the browsers I would like it to be... CaniIUse.com Browser Support Chart for calc(). Another excellent possibilty! One I did not know existed, and could be utilized if I made a fallback JS script for older browsers (want to avoid).
METHOD 3: Flexbox (Also suggested by onetrickpony)
Probably my favorite solution, but limited support is making me timid. Also could be used along with a fallback script. I learned about this a while back, and this is the future of CSS and layouts. Our salvation! Can't wait for full support...
METHOD 4: jQuery (Suggested by Tomasz Golinski)
What I was originally going to use, but decided I wanted to see if there was a CSS method that could be used instead. I have had some issues when using jQuery to set the width of elements. Mainly when the container is resized, and the script calculates the appropriate width while the container is resized.
So, the kind people who responded to my question have provided me with viable solutions to this issue. Any of the below is certainly an acceptable method to do what I am asking. I am simply seeking an answer that is more of a common CSS method. I am hoping that it is possible to accomplish this with some combination of styles I have not tried. I will admit I think Tomasz is correct- it cannot be done. I am leaving this question open just in case someone has a solution for me. Both Tomasz and onetrickpony have given me great answers. But I am still seeking a CSS-only solution that is widely supported by older browsers- and new, that I do not need to include a secondary script for, and that works without the need for characters inside the elements. Just want to see someone prove us wrong (that it is possible with good old fashioned CSS). If this magic answer does not come, I will be marking onetrickpony's answer as the best solution due to the fact it is CSS based, and he provided multiple solutions that are clean and simple. A combination of his flexbox CSS and Tomasz jQuery (as the secondary script) will most likely be what I use. Thanks!
If you're set to use floats, calculate the width of your "elastic" column by subtracting the widths of other columns from 100%. Example:
<div class="row cols-4">
<div class="col" id="one">One</div>
<div class="col" id="two">Two</div>
<div class="col elastic" id="three">Three</div>
<div class="col" id="four">Four</div>
</div>
CSS:
.cols-4 .elastic{
width: calc(100% - 45px * 3);
}
/* add more rules for other possible variations here */
http://jsfiddle.net/QM4LZ/
But a cleaner and easier approach is to use flexible boxes. This is exactly what they were designed for.
.row{
display: flex;
}
.col{
flex: none; /* <- don't flex */
width: 45px;
}
.elastic{
flex: auto; /* <- flex */
width: 100%;
}
http://jsfiddle.net/F7sxU/
It's also possible to achieve this with tables (fiddle), but you'll most likely run into some limitations when adding the real content and you need more wrapper elements.
the previous answer does resolve the issue however there are some problems with #onetrickpony's solution
example #1 will not work properly with dynamic number of items.
example #2 in most browsers it will work but not all browsers do support flexible boxes.
here is simple javascript code
jsFiddle: http://jsfiddle.net/aQEt3/5/
var count = $('.row').children().length; // counts how many items are in the entire row
var totWidth = $('.row').width(); // checks total width of the row
var elWidth = totWidth - ((count - 1) * 45); // counts how wide should be the elastic it
$(document).ready(function () {
$('.elastic').css('width', elWidth); // when document is ready, apply the new width to the elastic
});
beware, this is very simple code and there will be some issues if:
*there are 2 or more .row items
*you have more than one elastic class

Responsive Designs Foundation/Bootstrap height setting best practice

Just wondering what exactly is the best practice for say, setting the height of a header in a responsive layout. Would you set it to the column, the row, or perhaps the element(s) nested inside the row. I know its a pretty basic question and there may not be a correct answer, but I am having trouble finding a consensus on this.
Is it best to use the framework in a completely detached way from other elements, eg, never add custom css to a row/col tag just use inner containers? What is preferred?
I usually let the content set the height.
<header>
<div class="container">
<div class="row">
<div class="span12">
<h1 class="padding_min-height_etc"><!-- h1 with a height / margin / padding etc -->
Although I have noticed others using classes set on the header itself.
<header id="overview" class="jumbotron subhead">
<div class="container">
<h1>Components</h1>
I was always taught to not use HTML tags to style content thought...

display:table-cell not working on an input element

I want to do a portion of a form look like a spreadsheet.
There are several forms and <table> is thus not viable (though I'm not against it when you do are printing semantically tabular data, as it is the case).
So I tried to simply use a CSS2.1 layout directly with the form input elements, eg.
<div class="table">
<form class="tbody">
<div class="tr">
<label class="td">Label</label>
<input class="td" name />
<input class="td" name />
</div>
</form>
</div>
Full example in the fiddle.
But it looks like display:table-cell does not work on <input> elements!
If you check in Chrome "Computed Style" the display will be "inline-element".
But I did not find anywhere why it shouldn't:
Mozilla Dev Network CSS:display
W3C CSS 2.1 Recommendation Visual Formatting Model
W3C Tables Recommendation
Any idea?
It sounded so much better than having some <div class="cell"> around the <input> and then having to play with box-model to get it look nice...
From W3.org:
"CSS 2.1 does not define which properties apply to form controls and frames, or how CSS can be used to style them. User agents may apply CSS properties to these elements. Authors are recommended to treat such support as experimental. A future level of CSS may specify this further."
Sorry, but display: table-cell on input elements is treated experimental. Try to avoid it, use wrapper-elements for the positioning for example.
I've made an example with div elements. You can now have multiple forms within a table, however it only works when the form element spans full rows. Otherwise your nesting will be broken.
EDIT:
Updated the fiddle with a version where border-collapse is added to avoid double borders.
JSFiddle example

how to make three inside divs the same height?

I have a container div#content, which contains three divs inside. Now, how could I make sure that three divs inside have the same height? Of course, I hope each div's height could be expanded according to its content. For example:
here is what I tried
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
<title></title>
<style type="text/css">
#content{background-color:#DDDDD;width:100%;overflow:auto;clear:both;height:100%;}
#col1{background-color:yellow;width:10%;float:left;height:100%;}
#col2{background-color:red;width:30%;float:left;height:100%;}
#col3{background-color:#AAAAAA;width:10%;float:left;;height:100%;}
</style>
</head>
<body>
<div id="content">
<div id="col1">
<script language="javascript">
for(i=0;i<1000;i++){
document.write(i+"<br />");
}
</script>
</div>
<div id="col2">
<script language="javascript">
for(i=0;i<100;i++){
document.write(i+"<br />");
}
</script>
</div>
<div id="col3">
<script language="javascript">
for(i=0;i<10;i++){
document.write(i+"<br />");
}
</script>
</div>
I regularly get bashed by the CSS purists for this suggestion, but whenever I run into a problem like this for which – to the best of my knowledge – CSS simply doesn't offer a solution (no, "change your design" doesn't count!)...
I recommend using a table for that part of your layout.
Tables do equal vertical sizing easily and correctly across all major browsers. I'll continue to recommend them until CSS offers workable solutions for those problems.
A very useful technique for creating divs of equal height is to emulate it with a technique called "Faux Columns". This was an idea first suggested by Dan Cederholm (You can read his original article here), and has since evolved. You can see a good tutorial here. If you need it in a liquid layout environment, you might want to read this article.
Basically, the idea builds on NOT trying to force the divs to be of equal height, but have a wrapper of the three divs with a background-image that simulates the background of the columns. This approach works consistently among all modern browsers (ie6 even counts as modern in this context). The negative part is that you'll need a background image that is at least as wide as the page is allowed to expand. i.e. X pixels wide and 1px high.
First of all: if you have an equal attribute on different elements, please adhere to the DRY principle (Don't Repeat Yourself) and write it like so:
.content div{
border:1px solid #404040
}
That way you'll only have to change it in one place.
Now about your question. For a dynamic height, I'd specify that the div's should have a height of 100%, so they fill all the vertical space. This doesn't work nicely cross-browser so look for a hack that does this. If you don't want the div's to fill up the content div, put another div inside the content div and put that around the 3 divs.
So:
<div id="content">
<div class="innerContent">
<div class="1">Lorem Ipsum</div>
<div class="2">Lorem Ipsum</div>
<div class="3">Lorem Ipsum</div>
</div>
</div>
I may be wrong, but I think you either put the same values for the heights in the divs (either in percent or px) or you'll have to do some script (for example in JavaScript) that will check on the content height and set the other heights. I don't think it's doable with CSS. If I'm wrong I'd like to know the answer though:P
You could try it using css for modern browsers (display:table-cell, etc.), however, that will not work in IE6 and IE7.
If IE6 and IE7 are a requirement (I suppose it is...), you can include some javascript just for them using conditional statements and have that javascript set the height of all columns to the tallest. Not really pretty, but the percentages of IE6 and 7 should be going down fast anyway.
By the way, Machine's solution (faux columns) is another solution that works for a lot of designs.

Resources