Verticaly centered equal height columns when some divs are nested? - css

I need equal height columns which vertically centre there content. When each column div is a direct descendant of a container this is easy to do with display table: http://codepen.io/anon/pen/XKzOrv
However I have nested divs. Is it still possible to achieve this layout without modifying my markup?
UPDATE - As I'm supporting IE9+ I cant use flexbox.
.cont {
width: 500px;
}
.depth1 {
width: 50%;
float: left;
display: table;
}
.depth2 {
display: table-cell;
width: 50%;
vertical-align: middle;
}
.a {
background: blue;
}
.b {
background: green;
}
.c {
background: orange;
}
.d {
background: grey;
}
<div class="cont">
<div class="depth1">
<div class="depth2 a">
A
</div>
<div class="depth2 b">
B
<br>Wrap
</div>
</div>
<div class="depth1">
<div class="depth2 c">
C
<br>
<br>
<br>Wrap
</div>
<div class="depth2 d">
D
</div>
</div>
</div>

Yes it is possible with Flexbox, just use display: flex on all child div elements except on .c and add align-items: center on .depth2
.cont {
width: 500px;
display: flex;
}
.depth1 {
width: 50%;
display: flex;
}
.depth2 {
width: 50%;
}
.depth2:not(.c) {
display: flex;
align-items: center;
}
.a {
background: blue;
}
.b {
background: green;
}
.c {
background: orange;
}
.d {
background: grey;
}
<div class="cont">
<div class="depth1">
<div class="depth2 a">
A
</div>
<div class="depth2 b">
B
<br>Wrap
</div>
</div>
<div class="depth1">
<div class="depth2 c">
C
<br>
<br>
<br>Wrap
</div>
<div class="depth2 d">
D
</div>
</div>
</div>

Related

How do I mimic floats with flexbox?

I am trying to use flexbox like floats. I would like 1 child to form a column on the right and the remaining children to form another column on the left. I can't add in additional HTML -- I can only work with CSS.
I've figured out how to do this, but I just need both columns to align at the top. My current code has the left column slightly below the right column.
https://jsfiddle.net/o2fbtuLc/
.parent {
display: flex;
flex-wrap: wrap;
flex-direction: column;
}
.child {
max-width: 48%;
}
.right {
margin-left: auto;
}
<div class="parent">
<div class="child right">Right</div>
<div class="child">Left</div>
<div class="child">Left</div>
<div class="child">Left</div>
</div>
You can use order. Also I removed flex-direction: column and added max-width: 100% for elements after second element.
.parent {
display: flex;
flex-wrap: wrap;
}
.child {
width: 100%;
max-width: 48%;
}
.child:nth-child(2) {
order: 1;
}
.child:nth-child(3) {
order: 3;
}
.child:nth-child(4) {
order: 4;
}
.right {
order: 2;
}
.child:nth-child(n + 3) {
max-width: 100%;
}
<div class="parent">
<div class="child right">Right</div>
<div class="child">Left</div>
<div class="child">Left</div>
<div class="child">Left</div>
</div>
If .right is taller, we can consider using grid-area.
.parent {
display: grid;
grid-template-areas: "left1 right"
"left2 right"
"left3 right";
}
.child {
width: 100%;
background: blue;
height: 30px;
}
.child:nth-child(2) {
grid-area: left1;
}
.child:nth-child(3) {
grid-area: left2;
}
.child:nth-child(4) {
grid-area: left3;
}
.right {
background: red;
height: 80px;
grid-area: right;
}
<div class="parent">
<div class="child right">Right</div>
<div class="child">Left</div>
<div class="child">Left</div>
<div class="child">Left</div>
</div>
CSS-Grid can do that:
.parent {
display: grid;
grid-template-columns: auto auto;
grid-auto-flow: column;
}
.child {
max-width: 48%;
grid-column: 1;
border: 1px solid green;
}
.right {
grid-column: 2;
}
<div class="parent">
<div class="child right">Right</div>
<div class="child">Left</div>
<div class="child">Left</div>
<div class="child">Left</div>
<div class="child right">Right</div>
</div>
If you want to avoid grid (IE 11 involved maybe ?) , the old way via the table-display, can do too :
.parent {
display: table;
width: 100%;
direction: rtl;/* alike a flow column reverse here */
text-align: left;
border: solid;
}
.child {
direction: ltr;/* ! reset flow direction ;)*/
border: solid;
}
.right {/* i will also expand if first col is longer than myself */
display: table-cell;
width: 50%;/* set column width here ! left over will be for the other one(s). */
}
/* margins ? */
.bis {border-spacing:2px;}
.bis .child {margin-right:2px;}
.bis .right + .child ~ .child {margin-top:2px;}
.bis .right{text-align:center;vertical-align:middle;
<div class="parent">
<div class="child right">Right</div>
<div class="child">Left</div>
<div class="child">Left</div>
<div class="child">Left</div>
</div>
<hr>
<div class="parent bis">
<div class="child right">possible gaps / VH-align</div>
<div class="child">Left</div>
<div class="child">two<br>lines</div>
<div class="child">Left</div>
</div>
just use flexbox as it was intended!
.parent {
display: flex;
justify-content:space-between;
}
<div class="parent">
<div>
<div class="child">Left</div>
<div class="child">Left</div>
<div class="child">Left</div></div>
<div class="child right">Right</div>
</div>

How to set equal width for flex elements?

Why blocks .b have different width? How to set it equal?
.parent {
display: flex;
}
.parent>div {
flex: 1 1 auto;
}
.parent .b {
display: flex;
}
<div class="parent">
<div class="cell">
<div class="b"></div>
</div>
<div class="cell">>
<div class="b"></div>
</div>
<div class="cell">>
<div class="b"></div>
</div>
<div class="cell">>
<div class="b"></div>
</div>
<div>
Why blocks <div class="cell"> have different width?
Edit: use CSS grid and auto-fit:
.parent {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
}
.parent {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
}
.parent>div {
background-color: lightblue;
margin-left: 5px;
}
<div class="parent">
<div class="cell">
<div class="b"></div>
</div>
<div class="cell">>
<div class="b"></div>
</div>
<div class="cell">>
<div class="b"></div>
</div>
<div class="cell">>
<div class="b"></div>
</div>
</div>
Second re-edit**
First choice you can do is just set a flex on the parent element as this will only effect the first element below that, which in this case is the cell class, i will add a border on the cell class so you can see this in effect
<div class="parent">
<div class="cell">
<div class="b"></div>
</div>
<div class="cell">
<div class="b"></div>
</div>
<div class="cell">
<div class="b"></div>
</div>
<div class="cell">
<div class="b"></div>
</div>
<div>
.parent {
display: flex;
width: 70%;
}
.cell {
width: 20%;
height: 100px;
border: 1px solid orange;
}
here you can set the size of your parent width which will be the size across your screen, you can then set the width of the .cell childs and they will all then be the same, but only at a maximum of the parent
** second option you can do
Here is a simpler version, and i have added 3 different classes to show how you can choose the sizing you want
<div class="parent">
<div class="a"></div>
<div class="b"></div>
<div class="c"></div>
<div>
.parent {
display: flex;
width: 80%;
height: 100px;
}
.a {
flex: 40%;
border: 1px solid greenyellow;
}
.b {
flex: 20%;
border: 1px solid orange;
}
.c {
flex: 20%;
border: 1px solid blue;
}
Of course you can change them back and have them all be called the same class, and just assign one width and again they will all be the same... i hope this helps
I think they all are in same width. You need to use this css instead of the .parent>div selector
.cell {
flex: 1 1 auto;
}
.parent {
display: flex;
}
.cell {
flex: 1 1 auto;
}
.parent .b {
display: flex;
align-items: center;
justify-content: center;
}
.b {
height: 50px;
}
.cell:nth-child(1) {
background: red;
}
.cell:nth-child(2) {
background: yellow;
}
.cell:nth-child(3) {
background: green;
}
.cell:nth-child(4) {
background: teal;
}
<div class="parent">
<div class="cell">
<div class="b">hi</div>
</div>
<div class="cell">
<div class="b">hi</div>
</div>
<div class="cell">
<div class="b">hi</div>
</div>
<div class="cell">
<div class="b">hi</div>
</div>
<div>

CSS How do I force a container to be displayed underneath a preceding container whose elements float left

I want the div which displays "D" to appear beneath that one which displays "A" so that divs with matching background colours appear stacked over one another. However, I am getting this:
Where exactly in my CSS code must I clear my float?
#container {
background-color: #333333;
width: 990px;
}
#left {
background-color: red;
width: 300px;
float: left;
}
#splitter {
background-color: green;
width: 90px;
float: left;
}
#right {
background-color: blue;
width: 200px;
float: left;
}
<div id="container">
<div id="left">A</div>
<div id="splitter">B</div>
<div id="right">C</div>
</div>
<div id="container">
<div id="left">D</div>
<div id="splitter">E</div>
<div id="right">F</div>
</div>
You have to deal with floats and for this you need to understand what floats and BFC are :
a few ways to do this, that you should understand once you been reading a bit about floats, clearing and Block formating context.
(last example in the snippet below, oldish, even avoids the floats but does the layout)
/* DEMO purpose : Show the id or class being used on that container*/
section:before {
content: attr(id)' 'attr(class);
display: table;
background: #177EE5;
padding: 5px;
margin: 5px;
color: #fff;
text-shadow: 0 0 1px black, 0 0 1px black, 0 0 1px black, 0 0 1px black, 0 0 1px black, 0 0 1px black;
letter-spacing: 1px;
font-variant: small-caps;
}
/* your css turned into class to be valid since used for many tags */
.container {
background-color: #333333;
width: 990px;
}
.left {
background-color: red;
width: 300px;
float: left;
}
.splitter {
background-color: green;
width: 90px;
float: left;
}
.right {
background-color: blue;
width: 200px;
float: left;
}
/* wrapper for each examples */
section {
clear: both;
overflow: hidden;
margin: 1em;
}
/* different ways shown, usefull for testing only if you read about floats and dig a bit */
/* table */
.table .container {
display: table;
}
/* overflow */
.overflow .container {
overflow: hidden;
}
/* float */
.float .container {
float: left;
}
/* flex */
.flex .container {
display: flex;
}
/* inline-block */
.inline-block .container {
display: inline-block;
vertical-align: top;
}
/* last examples without floats */
/*no float & ie8 */
#table div {
float: none
}
#table #first-row,
#table > div {
display: table-row;
}
#table > div > div {
display: table-cell;
}
#table {
background-color: #333333;
width: 990px;
table-layout: fixed;
}
#left {
width: 300px;
}
#splitter {
width: 90px;
}
#right {
width: 200px;
}
#table > div > div {
background-color: red;
}
#table > div > div + div {
background-color: green;
}
#table > div > div + div + div {
background-color: blue;
}
#table:before {
display: table-caption;
width: 100%;
margin: 0;
}
#table > div:after {
content: "Notice there's a gap to fill here since cols do not cover the 990px";
display: table-cell;
}
<section class="your CSS :-: no BFC involved">
<div class="container">
<div class="left">A</div>
<div class="splitter">B</div>
<div class="right">C</div>
</div>
<div class="container">
<div class="left">D</div>
<div class="splitter">E</div>
<div class="right">F</div>
</div>
</section>
<section class="table">
<div class="container">
<div class="left">A</div>
<div class="splitter">B</div>
<div class="right">C</div>
</div>
<div class="container">
<div class="left">D</div>
<div class="splitter">E</div>
<div class="right">F</div>
</div>
</section>
<section class="overflow">
<div class="container">
<div class="left">A</div>
<div class="splitter">B</div>
<div class="right">C</div>
</div>
<div class="container">
<div class="left">D</div>
<div class="splitter">E</div>
<div class="right">F</div>
</div>
</section>
<section class="float">
<div class="container">
<div class="left">A</div>
<div class="splitter">B</div>
<div class="right">C</div>
</div>
<div class="container">
<div class="left">D</div>
<div class="splitter">E</div>
<div class="right">F</div>
</div>
</section>
<section class="flex">
<div class="container">
<div class="left">A</div>
<div class="splitter">B</div>
<div class="right">C</div>
</div>
<div class="container">
<div class="left">D</div>
<div class="splitter">E</div>
<div class="right">F</div>
</div>
</section>
<section class="inline-block">
<div class="container">
<div class="left">A</div>
<div class="splitter">B</div>
<div class="right">C</div>
</div>
<div class="container">
<div class="left">D</div>
<div class="splitter">E</div>
<div class="right">F</div>
</div>
</section>
<p>another way without float including IE8 ?</p>
<section id="table" class="table">
<div id="first-row">
<div id="left">A</div>
<div id="splitter">B</div>
<div id="right">C</div>
</div>
<div>
<div>D</div>
<div>E</div>
<div>F</div>
</div>
</section>
There could be more examples from the same chunks of code and floatting children.
Clear the floats in the container.
You have 3 simple ways to do that:
1. Float
#container {
clear: both;
}
2. Overflow
#container {
overflow: hidden;
}
3. Micro clearfix hack
Link
Here is what you want done bro..
this one is by using display:inline-block https://jsfiddle.net/p4domjrb/
this one is by using float:left https://jsfiddle.net/p4domjrb/1/
.container {
background-color: #333333;
width: 990px;
display: block;
position: relative;
}
.left {
background-color: red;
width: 300px;
display: inline-block;
margin-left: -4px;
}
.splitter {
background-color: green;
width: 90px;
display: inline-block;
margin-left: -4px;
}
.right {
background-color: blue;
width: 200px;
display: inline-block;
margin-left: -4px;
}
don't use id I suggest use class isntead because idis called only once.
<style>
.container{
background-color: #333333;
width:990px;
display:block;
clear:both;
}
#left{
background-color: red;
width:300px;
float:left;
}
#splitter{
background-color: green;
width:90px;
float:left;
}
#right{
background-color: blue;
width: 200px;
float:left;
}
</style>
<body>
<div class="container">
<div id="left">A</div>
<div id="splitter">B</div>
<div id="right">C</div>
</div>
<div class="container">
<div id="left">D</div>
<div id="splitter">E</div>
<div id="right">F</div>
</div>
</body>
result is

How can I alternate the float of my content?

I want to create a layout for an itemised list of content like below:
Each item is a container that has an image and block of text.
I have attempted to use nth-child and set different css float values based on if it is an odd or even child, but you can't set child properties using the nth-child selector.
HTML:
<div class="flex-container">
<div class="media-container ">
<img src="img/image.png">
</div>
<div class="text-container">
<div class="titles">
<h2>Title #1</h2>
</div>
<p>lots of words</p>
</div>
</div>
<div class="flex-container">
<div class="media-container ">
<img src="img/image.png">
</div>
<div class="text-container">
<div class="titles">
<h2>Title #1</h2>
</div>
<p>lots of words</p>
</div>
</div>
<div class="flex-container">
<div class="media-container ">
<img src="img/image.png">
</div>
<div class="text-container">
<div class="titles">
<h2>Title #1</h2>
</div>
<p>lots of words</p>
</div>
</div>
CSS:
.flex-container {
width: auto;
margin: 10px auto;
padding: 0 15px;
display: inline-flex;
}
.flex-container:nth-child(odd) {
.media-container {
float: left;
}
.text-container {
float: right;
}
}
.flex-container:nth-child(even) {
.media-container {
float: right;
}
.text-container {
float: left;
}
}
.media-container {
position: relative;
display: inline-block;
}
.media-container img {
width: 100%;
height: auto;
}
.text-container {
width: 30%;
margin: 0 10px;
align-self: center;
position: relative;
display: inline-block;
}
What is the easiest/neatest solution for creating this layout using CSS?
Something like this:
Use the nth-child on your "row" flex-containers and alternate the flex-direction.
.flex-container {
padding: 0 15px;
display: flex;
width: 80%;
border: 1px solid grey;
margin: 1em auto;
}
.flex-container:nth-child(odd) {
flex-direction: row;
}
.flex-container:nth-child(even) {
flex-direction: row-reverse;
}
.media-container img {
width: 100%;
height: auto;
}
.text-container {
width: 30%;
margin: 0 10px;
}
<div class="flex-container">
<div class="media-container ">
<img src="http://www.fillmurray.com/300/200">
</div>
<div class="text-container">
<div class="titles">
<h2>Title #1</h2>
</div>
<p>lots of words</p>
</div>
</div>
<div class="flex-container">
<div class="media-container ">
<img src="http://www.fillmurray.com/300/200">
</div>
<div class="text-container">
<div class="titles">
<h2>Title #1</h2>
</div>
<p>lots of words</p>
</div>
</div>
Take A Look At This:
.item {
width: 305px;
height: 70px;
background: black;
margin: 5px;
padding: 5px;
}
.item .title {
width: 200px;
height: 70px;
background: crimson;
}
.item .img {
width: 100px;
height: 70px;
background: #09f;
}
.item:nth-child(even) .img {
float: right;
}
.item:nth-child(even) .title {
float: left;
}
.item:nth-child(odd) .img {
float: left;
}
.item:nth-child(odd) .title {
float: right;
}
<div class='item'>
<div class='title'></div>
<div class='img'></div>
</div>
<div class='item'>
<div class='title'></div>
<div class='img'></div>
</div>
<div class='item'>
<div class='title'></div>
<div class='img'></div>
</div>
Is it necessary that it is display:inline-flex? If you change it to inline-block, I believe you'll get your intended display:
.flex-container {
display: inline-block;
...
}
https://jsfiddle.net/4rcdqy4f/
You can use the Javascript querySelectorAll() method. Then, loop through the list of your items and add the specific CSS property based on whether it is odd or even.

Align <div> elements side by side

I know this is a rather simple question, but I can't figure it out for the life of me. I have two links which I've applied a background image to. Here's what it currently looks like (apologies for the shadow, just a rough sketch of a button):
However, I want those two buttons to be side by side. I can't really figure out what needs to be done with the alignment.
Here's the HTML
<div id="dB"}>
Download
</div>
<div id="gB">
Gallery
</div>
Here's the CSS
#buyButton {
background: url("assets/buy.png") 0 0 no-repeat;
display:block;
height:80px;
width:232px;
text-indent:-9999px;
}
#buyButton:hover{
width: 232px;
height: 80px;
background-position: -232px 0;
}
#buyButton:active {
width: 232px;
height: 80px;
background-position: -464px 0;
}
#galleryButton {
background: url("images/galleryButton.png") 0 0 no-repeat;
display:block;
height:80px;
width:230px;
text-indent:-9999px;
}
#galleryButton:hover{
width: 230px;
height: 80px;
background-position: -230px 0;
}
#galleryButton:active {
width: 230px;
height: 80px;
background-position: -460px 0;
}
Beware float: left… 🤔
…there are many ways to align elements side-by-side.
Below are the most common ways to achieve two elements side-by-side…
Demo: View/edit all the below examples on Codepen
Basic styles for all examples below…
Some basic css styles for parent and child elements in these examples:
.parent {
background: mediumpurple;
padding: 1rem;
}
.child {
border: 1px solid indigo;
padding: 1rem;
}
Using the float solution my have unintended affect on other elements. (Hint: You may need to use a clearfix.)
html
<div class='parent'>
<div class='child float-left-child'>A</div>
<div class='child float-left-child'>B</div>
</div>
css
.float-left-child {
float: left;
}
html
<div class='parent'>
<div class='child inline-block-child'>A</div>
<div class='child inline-block-child'>B</div>
</div>
css
.inline-block-child {
display: inline-block;
}
Note: the space between these two child elements can be removed, by removing the space between the div tags:
html
<div class='parent'>
<div class='child inline-block-child'>A</div><div class='child inline-block-child'>B</div>
</div>
css
.inline-block-child {
display: inline-block;
}
html
<div class='parent flex-parent'>
<div class='child flex-child'>A</div>
<div class='child flex-child'>B</div>
</div>
css
.flex-parent {
display: flex;
}
.flex-child {
flex: 1;
}
html
<div class='parent inline-flex-parent'>
<div class='child'>A</div>
<div class='child'>B</div>
</div>
css
.inline-flex-parent {
display: inline-flex;
}
html
<div class='parent grid-parent'>
<div class='child'>A</div>
<div class='child'>B</div>
</div>
css
.grid-parent {
display: grid;
grid-template-columns: 1fr 1fr
}
Apply float:left; to both of your divs should make them stand side by side.
keep it simple
<div align="center">
<div style="display: inline-block"> <img src="img1.png"> </div>
<div style="display: inline-block"> <img src="img2.png"> </div>
</div>
.section {
display: flex;
}
.element-left {
width: 94%;
}
.element-right {
flex-grow: 1;
}
<div class="section">
<div id="dB" class="element-left" }>
Download
</div>
<div id="gB" class="element-right">
Gallery
</div>
</div>
or
.section {
display: flex;
flex-wrap: wrap;
}
.element-left {
flex: 2;
}
.element-right {
width: 100px;
}
<div class="section">
<div id="dB" class="element-left" }>
Download
</div>
<div id="gB" class="element-right">
Gallery
</div>
</div>

Resources