Here's what I can't do by any means, using only CSS:
Columns should have equal heights.
And, on a given column, a absolute positioned element should be present relative to that column:
The HTML:
<div class="wrapper">
<div class="inner">
<div class="column">
<img src="http://www.english3.com/wp-content/uploads/2013/05/DFI-Logo-300px-X-200px.png"/>
</div>
<div class="column info">
<p>Some text here yeah :).</p>
<p>Some text here yeah :)</p>
<p>Some text here yeah :)</p>
<a class="link" href="#">I should be absolute.</a>
</div>
</div>
</div>
THE CSS:
.wrapper {
overflow: hidden;
position: relative;
}
/*added */
.inner {
width: 100%;
display: table;
}
.column {
display: table-cell;
width: 50%;
vertical-align: top;
background-color:red;
}
.column img {
max-width:100%;
display: block;
}
.info {
background-color: blue;
padding-bottom: 25px;
}
.link {
display: block;
position: absolute;
left: 50%;
bottom: 3%;
color: yellow;
}
Fiddle to play:
Here's the try with table-cell; and a relative inner container:
http://jsfiddle.net/BuuFv/98/
TRIES AND FRUSTRATIONS:
1) - Display table
For equal heights I can't pull this out, due to FF issues.
Tried with an extra relative parent container
But left image doesn't shrink according to it's container on FF.
Tried giving height: 100%
http://davidwalsh.name/table-cell-position-absolute
But didn't work either, the image doesn't shrink or expands using max-width;
2 - Huge positive padding and negative margin values
Will not work, because the absolute positioned element will not stay in place.
3 - Faux Columns
Seems to be of any help, due to the fact that, we are not playing with solid background colours, and we have an image on the left column instead.
A picture:
Any help, please?
1)
On this case, adding an extra relative container with position relative attribute (.inner), did the trick.
2)
The fact that the image didn't shrink or grow on FF was because it wasn't considering the max-width declaration as it should.
Fix:
.inner {
width: 100%;
display: table;
table-layout:fixed; /* <<-- ADD */
}
the table-layout fixed algorithm made Firefox recognize the max-width in the cell and this let the image shrink.
Credits on this solution should be shared with Paul O'B.
Here is my take on it http://jsfiddle.net/E6UDD/
So basically, uncoment padding and negative margin hack, and add the height of the column to be the same amount.
Then, add relative positioning to the .column.
Then, position of the absolute positioned link should be top: 50% to have it at the very bottom, or 44% to mimic the 3% you originally indended.
DEMO
.wrapper {
position:relative;
overflow: hidden;
white-space:nowrap;
outline:1px solid red;
height:auto;
}
.column {
position:relative;
display:inline-block;
vertical-align:top;
background-color:red;
width:50%;
}
.column img {
max-width:100%;
min-width:30px;
min-height:20px;
}
.info {
position:absolute;
bottom:0;
top:0;
background-color: blue;
}
.link {
clear:left;
display: block;
position: absolute;
bottom: 3%;
color: yellow;
}
http://jsfiddle.net/BuuFv/75/
You can try changing the link from absolute positioned to another table-cell. Not 100% on your use case but it seems to accomplish what you are asking.
.link {
height:100px;
display:table-cell;
vertical-align:bottom;
color: yellow;
}
Related
I'm trying to understand CSS display: table. What happens when the cells/columns within the table don't make 100%? For example within the table in the JSFiddle:
.flag { max-width: 10%;}
.country_manager {max-width: 55%;min-width: 35%;}
.score1 { max-width: 5%;}
.score2 { max-width: 5%;}
At most that cover's 75% of the table width, so how is it decided where the remaining width goes?
In this JSFiddle I have blank cells at either side assuming one or both would take up the remaining space.
Without them, there isn't a lot of difference.
The reason I ask is that I'd like the country section to be slightly adjustable, and if it is smaller, I'd like the table contents to be centered with even spacing to either side.
I think this is no different from how browsers allocate width to actual table columns, and there is a prior question about this How is extra width in a table divided up among columns?. Alas, there is no good answer there either, but a link to further documentation.
Interestingly enough, this behaviour is inconsistent across two very good, standards-committed browsers -- Chrome and Firefox. Firefox appears to actually use the percentages you give, so if you have 75% of the width set in your containing elements, it'll only fill 75% of the table and center the elements in the middle. Chrome, on the other hand, will assume that the width is 100%, and represent the columns as filling the full width.
e.g. if you have two max-widths, both set at 5%, Firefox would show each at 5% width and have 45% empty each on the right and left. Chrome would be 100% full, and each element would be 50% width.
Based on the browser inconsistency alone, I'd avoid ever not letting them add up. Perhaps you could use a :before and :after pseudo-class to create a spacer area with the remaining with, and force it to be centered?
I would suggest using different code structure. You see, tables are useful in displaying chunks of data. But if you want to have a website layout I would split website into header / content / footer. And after that use divs with absolute positioning to represent those block you've shown
i think and test this css code.
<style>
.table {
margin-top:5%;
padding-top:5%;
padding-bottom:5%;
background-color: #ddd;
width: 70%;
height: 50%;
position: absolute;
display:table;
font-size: 2vh;
text-align: center;
overflow:hidden;
}
.row {
display:table-row;
width:100%;
height:40%;
}
.row_small {
display:table-row;
width:100%;
height:5%;
background-color: red;
padding:10px 0;
}
.blank {
display:table-cell;
}
.flag {
display:table-cell;
width:10%;
max-width:10%;
background-color: orange;
}
.country_manager {
display:table-cell;
max-width: 55%;
min-width: 35%;
}
.country {
display:table-cell;
width: 100%;
height:70%;
background-color: yellow;
float: left;
}
.manager {
display:table-cell;
height:30%;
width: 100%;
background-color: pink;
float: left;
}
.score1 {
display:table-cell;
width:5%;
max-width:5%;
background-color: blue;
}
.score2 {
display:table-cell;
width:5%;
max-width:5%;
background-color: green;
}
.title {
display:table-cell;
padding:10px 0;
color:#fff;
}
.ref_contain{
width: 100%;
position: absolute;
height: 15%;
}
.ref {
background-color: #800080;
color: #FFFFFF;
display: table-cell;
float: left;
padding: 10px 0;
position: absolute;
text-align: left;
text-indent: 133px;
width: 100%;
}
</style>
//write your html
<div class="table">
<div class="row_small">
<div class="blank">1</div>
<div class="title">2</div>
<div class="title">3</div>
<div class="title">AET</div>
<div class="title">Pens</div>
<div class="blank">blank1</div>
</div>
<div class="row">
<div class="blank">blank2</div>
<div class="flag">Flag</div>
<div class="country_manager">
<div class="country">Country</div>
<div class="manager">Manager</div>
</div>
<div class="score1">1</div>
<div class="score2">7</div>
<div class="blank">blank3</div>
</div>
<div class="row">
<div class="blank">blank4</div>
<div class="flag">Flag</div>
<div class="country_manager">
<div class="country">Country</div>
<div class="manager">Manager</div>
</div>
<div class="score1">1</div>
<div class="score2">7</div>
<div class="blank">blank5</div>
</div>
<div class="ref_contain">
<div class="ref">Ref</div>
</div>
</div>
I used the JsFiddle at jsfiddle.net/5tzk3/10. I changed it to display the div as square shaped dialog (both horizontally and vertically centered). The result is at jsfiddle.net/5tzk3/548.
As you see, centering horizontally was easy, but I could not get it centered vertically. Anyone who knows how to do that with pure CSS?
Edited code below:
<div class="blind">
<div class="wrapper">
<div class="main">
I'm your div with an aspect-ratio of 1:1!
</div>
</div>
</div>
html, body, .blind {
height: 100%;
width: 100%;
}
.blind {
left: 0;
position: fixed;
text-align: center;
top: 0;
}
.wrapper {
display: inline-block;
margin: auto;
position: relative;
width: 50%;
}
.wrapper:after {
content: '';
display: block;
padding-top: 100%;
}
.main {
background-color: rgb(0, 162, 232);
bottom: 0;
left: 0;
margin: auto;
position: absolute;
right: 0;
top: 0;
}
Use display: table for the parent div, and display:table-cell; vertical-align: middle for the content div which you want to vertically center.
The most common way of doing this if you've got an element with known dimensions is to use positioning to firstly position it top: 50% (which places the top edge of the element 50% of the way down) and then use a negative top-margin of half the height of the element (pulling it back up by half it's height).
To give you an example, to absolutely position a 200x200 element dead-centre on the page you would use:
.element{
display: block;
width: 200px;
height: 200px;
position: absolute;
top: 50%;
margin-top: -100px
}
Alternatively, you can use a combination of display: table and then display: table-cell on the parents to open up the ability to use vertical-align although this is a bit nasty when it comes to laying out elements around it.
you can drop absolute positionning and use either display:table or inline-block with pseudo elements.
here is a mixed of the 2 methods
1) html/body as a table one cell
2) inner content with ratio preserved and content as inline box set in the middle.
.ratio1-1 {
width:25%;
vertical-align:middle;
margin:auto;
background:turquoise;
}
.ratio1-1:before {
content:'';
padding:50% 0;
width:0;
display:inline-block;
vertical-align:middle;
}
.ib {
display:inline-block;
vertical-align:middle;
}
/* center body content as a table cell */
html {
height:100%;
width:100%;
display:table;
}
body {
display:table-cell;
vertical-align:middle;
text-align:center;
}
<div class="ratio1-1">
<div class="ib">content in middle</div>
</div>
demo: http://codepen.io/gc-nomade/pen/pubFm
I am trying to float some elements and apply clearfix so that the parent element can expand to the height and width of the children.
So, I simply set up the layout as per this fiddle: http://jsfiddle.net/fMjEx/
I then wanted to float the elements inside .bar. This is usually quite straight forward:
Float the elements.
Clear fix the parent using pie-clearfix or overflow: auto.
However, I ran into these problems:
If I use pie-clearfix, the element .picture which is next to .bar is also included in the clearing: http://jsfiddle.net/6C7WD/
If I use overflow: auto or overflow: hidden, the width of the .bar no longer spans the width of the document: http://jsfiddle.net/fv2gA/
Initially, one solution I had was to make .picture position: absolute. However, the problem with this approach is that the element is taken out of the flow.
In the layout, the height of .bar is variable depending on the content inside. I would like to give .bar and .picture a margin-bottom so that anything that comes after them is pushed downwards by that amount depending on whether .bar or .picture has a greater height.
This rules out using position: absolute on .picture as a solution.
Are there any solutions that satisfy the following?
Clear only floats within .bar.
Does not remove any elements from the flow.
This is the solution I ended up with:
Added a wrapper to the markup:
<div class="container">
<div class="group"> <-------------------------- This is the wrapper
<div class="picture"></div>
<div class="bar">
<div class="info"> some text goes here</div>
<div class="buttons">some other content goes here</div>
</div>
</div>
</div>
And the CSS:
.picture{
width: 100px;
height: 100px;
float: left;
background: green;
margin-left: 100px;
margin-top: 10px;
z-index: 2;
position: relative;
}
.bar{
background: blue;
margin-top: -80px;
overflow: auto;
width: 100%;
float: left;
z-index: 1;
position: relative;
}
.group{
margin-bottom: 10px;
}
.group:after {
clear: both;
content: "";
display: table;
}
.info, .button{
float: left;
margin-left: 200px;
}
.container{
overflow: auto;
}
Fiddle of the above: http://jsfiddle.net/c6Lng/
Here's my markup:
<div id="container">
<img id="image" src="image.jpg" />
<div id="contents">Contents</div>
</div>
The height of #container equals the height of #image.
All the heights are dynamic (they change on window resize).
The image can not be set via background property.
How can I have Contents over the image and vertically centered in #container?
Is the height of #contents known? In that case this should do it (jsfiddle demo):
#container{
position:relative;
/* For demo only */
height:500px;
border: 5px solid red;
}
#image{
position:absolute;
/* For demo only */
height:500px;
}
#contents{
position: absolute;
top:50%;
height:100px;
margin-top: -50px; /* Half of #contents height */
/* For demo only */
background-color: blue;
}
This ought to do what you are looking for. I have just set the height of the container and image in css, but if they are the same set in html or using javascript, the result should be the same. The background colour is just there for clarity.
#container {
background-color: #333;
height: 200px;
}
#image{
height: 200px;
float: left;
}
#contents{
line-height: 200px;
float: left;
position: fixed;
}
EDIT: Here is a fiddle of a solution using the old classic margin auto trick. The only thing that may cause problems here is that the parent needs to be position: fixed; which may cause issues for you elsewhere. The main thing is it works, and no heights are set using pixels.
link
Here is the code from the fiddle for a pure css solution with no fixed heights.
<div id="container">
<img id="image" src="https://www.google.co.uk/logos/2012/juan_gris-2012-hp.jpg" />
<div id="contents">Contents</div>
</div>
#container {
position: fixed;
}
#contents{
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
width: 50%;
height: 10%;
margin: auto;
}
If you know the height of #contents you can set up
#container{position:relative;}
#contents{
position:absolute;
top:50%; /*50% of parent*/
margin-top:/*negative one-half of container height i.e. if contaner is 4 em -2em*
}
You say you don't know the height of #contents, though.
Another option is to set the display: to table-cell and use vertical-align: middle
#container{
display: table-cell;
vertical-align: middle;
}
But depending on what browsers you are targetting for support, that may cause display issues as well.
The more sure fire way is to combine the first option with some jquery or javascript to find the element's height and set its margin-top:
content= document.getElementById('content')
content.style.marginTop = '-' + content.offsetHeight + 'px';
http://jsfiddle.net/h76sy/
EDIT: Sorry, had a bug in my javascript, try it now
I want the top lines of two DIVs (<div></div>) to be aligned horizontally, how to do it?
Steven,
In addition to T. Stone's suggestion to float both divs, a simple way to align two divs is to make both have the display: inline-block; CSS rule and give the lower div the vertical-align: top; CSS rule.
Take a look at this simple jsFiddle example to see how this works.
div {
display: inline-block;
}
div#tall {
height: 4em;
}
div#short {
height: 2em;
vertical-align: top;
}
In response to "is there another way to do it", sure you could use display: inline but you have a bunch of hacks to remember to get it to work in IE6/7. This way is generally better (but it all comes down to the individual circumstances)
<style type="text/css">
.keeper {
overflow: hidden; /* expand to contain floated children */
}
.keeper div {
width: 200px;
height: 30px;
float: left;
border-top: 1px solid red; /* so you can see the 'tops' */
}
</style>
<div class="keeper">
<div>
</div>
<div>
</div>
</div>
Float them in a container.
.parent div { float: left; width: 50%; }
<div class="parent">
<div>1</div>
<div>2</div>
</div>
Note: The sum of the width of the child divs can not be greater than 100% of the parent div, including margin and padding.
Alternative
If maintaining flow with the page isn't a requirement, and all that really matters is aligning, them, the divs can always be positioned absolutely.
.abs { position: absolute; top: 100px; width: 50px; }
.left { left: 0px; }
.right { left: 50px; }
<div class="abs left">1</div>
<div class="abs right">2</div>