3 expandable column landscape page in pure CSS - css

If this can be achieved in CSS:
When not hovered: 3 columns split in average width
When hovered on one of the column: that column expands and squeezes other 2 columns
Here's what I've been trying:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* vertical 1:2:1 */
html,
body {
height: 100%;
}
.vertical-divider {
display: flex;
flex-flow: column nowrap;
height: 100%;
}
/* container in page center */
.container {
display: flex;
flex-flow: row nowrap;
background-color: #eee;
flex: 2;
}
.container>.item {
display: flex;
flex-flow: column;
justify-content: left;
align-content: left;
align-items: left;
transition: .3s;
max-width: 50%;
padding-top: 24px;
padding-left: 12px;
background-color: #ccc;
min-width: 10%;
flex: 1;
text-align: left;
}
.container>.item:hover {
transition: .3s;
max-width: 80% !important;
background: #333;
flex: 4;
cursor: pointer;
color: #fff;
}
<!doctype html>
<html>
<head>
</head>
<body>
<div class="vertical-divider">
<div class="container">
<div class="item">
Column 1
</div>
<div class="item">
Column 2
</div>
<div class="item">
Column 3
</div>
</div>
</div>
</body>
</html>
But responsive design (e.g. If I want to just put them vertically if the screen is narrow) seems hard to achieve. So I'm asking if there is a better solution.

Flexbox offers a clean, modern solution. We can transition on the flex property. If you want to make the hovered div take up more room, simply adjust the value to a higher number.
.container {
display: flex;
}
.container > div {
flex: 1;
border-right: 2px solid black;
height: 300px;
padding: 10px;
transition: 0.5s flex;
}
.container > div:hover {
flex: 3;
}
.container > div:last-child {
border-right: 0;
}
<div class="container">
<div>col 1</div>
<div>col 2</div>
<div>col 3</div>
</div>
Edit A new requirement has emerged: make it responsive. Flexbox makes this an easy addition by changing the flex-direction property inside a simple media query.
#media screen and (max-width: 700px) {
.container {
flex-direction: column;
height: 100vh;
}
.container > div {
border-right: none;
border-bottom: 2px solid;
}
}
With the media query in place, our example is now complete.
Have a look.

Related

flexbox how to achieve this specific layout?

Like in the image - http://i65.tinypic.com/aa7ndw.png Examples and live flex configurators are explain only simple examples, or I just don't get it.
Will I be able to use media queries to for example not display a4 when < 800px?
I have always used float and flex is somehow 'different' anyway I would like to know it better, so any help is appreciated.
flex specific example
Apply display: flex to a container and its child elements will be displayed in flex. For this layout, you will want to wrap the elements when width is already filled for the current row.
The header and footer will be width: 100%, taking a full row. #a3 and #a4 will have flex: 1 to distribute the width of their row, taking each one 50% of the width.
div.flex-container{
width: 200px;
height: 300px;
background-color: black;
display: flex;
flex-flow: row wrap;
}
#a1, #a2{
width: 100%;
}
#a3, #a4{
flex: 1;
}
#a5, #a6, #a7{
height: 50px;
width: 80%;
margin: auto;
margin-bottom: 1rem;
}
/* Example styles */
div{
text-align: center;
}
#a1{
background-color: red;
}
#a2{
background-color: limegreen;
}
#a3{
background-color: royalblue;
}
#a4{
background-color: cyan;
}
#a5, #a6, #a7{
background-color: fuchsia;
}
<div class="flex-container">
<div id="a1">a1</div>
<div id="a3">a3</div>
<div id="a4">a4
<div id="a5">a5</div>
<div id="a6">a6</div>
<div id="a7">a7</div>
</div>
<div id="a2">a2</div>
</div>
And yeah, you can use media queries as normal
div.flex-container{
width: 200px;
height: 300px;
background-color: black;
display: flex;
flex-flow: row wrap;
}
#a1, #a2{
width: 100%;
}
#a3, #a4{
flex: 1;
}
#a5, #a6, #a7{
height: 50px;
width: 80%;
margin: auto;
margin-bottom: 1rem;
}
#media (max-width: 800px){
#a4{
display: none;
}
}
/* Example styles */
div{
text-align: center;
}
#a1{
background-color: red;
}
#a2{
background-color: limegreen;
}
#a3{
background-color: royalblue;
}
#a4{
background-color: cyan;
}
#a5, #a6, #a7{
background-color: fuchsia;
}
<div class="flex-container">
<div id="a1">a1</div>
<div id="a3">a3</div>
<div id="a4">a4
<div id="a5">a5</div>
<div id="a6">a6</div>
<div id="a7">a7</div>
</div>
<div id="a2">a2</div>
</div>

How can I place two divs in one row of a vertically sorted flex div?

Here is my code snippet:
.container {
display: flex;
flex-direction: column;
}
.container > div {
padding: 20px;
color: #fff;
margin: 5px;
text-align: center;
font-size: 30px;
}
.fruits {
order: 2;
background: #ff5423;
}
.container :not(.fruits) {
order: 1;
}
.flowers {
background: #f970bd;
}
.trees {
background: #049500;
}
<div class="container">
<div class="fruits">The fruits</div>
<div class="flowers">The flowers</div>
<div class="fruits">The fruits</div>
<div class="trees">The trees</div>
<div class="fruits">The fruits</div>
</div>
I am putting all .fruits div in the bottom using flex-direction: column;. There are two other divs .flowers and .trees which can be placed randomly anywhere inside .conatiner and I can't handle that. I want them to take half of its parent width so they take only one row.
What I want to achieve:
Giving 50% width will not work here. I know the rule says the direction is column-wise, however, I still hope if there is any available method/trick to do so! Any other workaround using different technique rather than using flex will also help.
You can do this with flex-direction: row you just need to set flex-wrap: wrap on parent and flex: 0 0 50% on elements you want to take half width.
You also need to use * {box-sizing: border-box} for paddings and calc() for margins.
* {
box-sizing: border-box;
}
.container {
display: flex;
flex-wrap: wrap;
}
.container > div {
padding: 20px;
color: #fff;
margin: 5px;
flex: 0 0 calc(100% - 10px);
text-align: center;
font-size: 30px;
}
.fruits {
order: 2;
background: #ff5423;
}
.container div:not(.fruits) {
order: 1;
flex: 0 0 calc(50% - 10px);
}
.flowers {
background: #f970bd;
}
.trees {
background: #049500;
}
<div class="container">
<div class="fruits">The fruits</div>
<div class="flowers">The flowers</div>
<div class="fruits">The fruits</div>
<div class="trees">The trees</div>
<div class="fruits">The fruits</div>
</div>

CSS Flexbox - Same height when a column contains multiple parts?

I have a simple question. I have a basic flex-box layout. One column takes up 2/3 of the layout, the other takes up a third. Both of them have a purple semi-transparent header (.85) with their contents are in an opaque black box.
http://codepen.io/StuffieStephie/pen/XdoBqL
body {
background: url('http://www.amazingwallpaperz.com/wp-content/uploads/Black-and-Purple-Abstract-Cool-Backgrounds-Wallpaper.jpg') center center;
background-size: cover;
font-family: 'Open Sans';
}
#featuredSlide, #featuredSlide img {
width: 100%;
max-width: 800px;
margin: 0 auto;
}
.container {
display: -webkit-flex;
display: flex;
justify-content: space-between;
color: #fff;
}
.sect {
box-sizing: border-box;
width: 32%;
-webkit-flex: 1;
flex: 1;
margin: 30px; text-align: center;
}
.sect + .sect {
margin-left: 10px;
}
.sect.feat {width: 65%;
-webkit-flex: 2;
flex: 2;
}
.sect .cont {
background:#414141;
padding-top: 40px;
padding-bottom: 30px;
border-radius: 0 0 5px 5px;
}
.sect h2 {
background:#414141;
background-color: rgba(52,41,109,.85);
margin-bottom: 0;
text-align: center;
text-transform: uppercase;
font-size: 2em;
font-weight: 300;
padding: 30px 10px;
border-radius: 5px 5px 0 0;
}
<head><link href='http://fonts.googleapis.com/css?family=Open+Sans:300,400,600' rel='stylesheet' type='text/css'>
</head>
<body>
<div class="container">
<div class="sect feat">
<h2> Featured Guests & Programming</h2>
<div class="cont">
<!-- SLIDE SHOW -->
<div id="featuredSlide" class="owl-carousel">
<img src="http://placehold.it/800x300/5d64a8">
</div> <!-- CLOSING SLIDE SHOW DIV TAG --></div>
</div>
<div class="sect">
<h2> News </h2>
<div class="cont">Some thrilling article</div>
</div>
</div>
<div class="clearfix"></div>
</body>
Both .sect elements are the same height. I want both .sect .cont elements to be the same height. I know I can make them look the same height by setting a background-color to .sect but that will ruin the transparency of my headers.
Any thoughts?
You can add flex-direction: column; to your .sect class, and give your .cont class a flex-grow: 1. This will make the .cont div's take up the remaining height of the .sect class.
.sect {
display: flex;
flex-direction: column;
}
.cont {
flex-grow: 1;
}
CodePen
You absolutely can do this with css only. Add the following to your .sect properties:
overflow: hidden;
position: relative;
border-radius:5px;
and add this to make the heights match:
.sect + .sect .cont::after {
background: #414141 none repeat scroll 0 0;
content: "";
height: 3000px;
left: 0;
position: absolute;
width: 100%;
}
You should also then be able to take out your border radii from the h2 and .cont as well.

Switching flex items from row to column alignment

I have a 'card' like html component, that it displays this way:
+------+-----------------+-------+
| 1 | 2 | 3 |
+------+-----------------+-------+
And when I go under the 720px I want that became like this:
+------+-------------------------+
| | 2 |
| 1 +-------------------------+
| | 3 |
+------+-------------------------+
I am having difficulties to figure out how can I achieve this with flexbox. I am wondering if it is the right solution for this kind of problem.
the initial state, is currently like this:
<div class="card">
<div class="status"></div>
<div class="title">Tryout.it</div>
<div class="details">156 emails</div>
<div class="action"><button>go</div>
</div>
and my CSS something like this:
.card {
margin: 10px;
min-width: 320px;
min-height: 42px;
background-color: white;
border: 1px solid #eee;
border-radius: 6px;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
padding: 9px 10px;
}
.card .status {
width: 30px;
height: 24px;
}
.card .title {
flex-grow: 1;
}
You cannot achieve this with flexbox with your current HTML structure.
(In the future you can use the grid layout for this, but at the moment it is not supported.)
However, if you place 2 and 3 in a container you can do this:
.card {
margin: 10px;
border: 1px solid #eee;
border-radius: 6px;
display: flex;
justify-content: space-between;
padding: 9px 10px;
}
.card .avatar {
width: 30px;
height: 24px;
}
.card .container {
flex-grow: 1;
display: flex;
flex-wrap: wrap;
}
.card .container .name {
width: 50%;
}
.card .container .presentation {
flex-grow: 1;
}
#media (max-width: 720px) {
.card .container .name {
width: 100%;
}
}
<div class="card">
<div class="avatar">
x
</div>
<div class="container">
<div class="name">Mr. Potato</div>
<div class="presentation">Hi!</div>
</div>
</div>
You can use CSS media query to apply a different style your div's at a certain screen size.
#media screen and (max-width: 720px) {
.css-class {
}
#css-id {
}
}
#ciaoben, Since you disappeared after asking you question, I'll provide an answer based upon the logic that the .title and .details blocks are meant to be blocks 2 and 3 from your diagram and that the .action is meant to be a fourth block on the opposite side.
Simply put, you need another layer for your HTML structure before you can apply the CSS to adjust it. You would wrap the blocks you want to have the appearance of altered in another DIV.
Once you have the HTML structure updated, it's a simple matter of applying a #media query to adjust the appearance at the desired screen size.
Please see my example below. Note: I updated your CSS to a more streamlined flexbox approach. Further, it applis display: flex to the .action block because, as I noted above, you don't identify it at all.
.card {
margin: 10px;
min-width: 320px;
min-height: 42px;
background-color: white;
border: 1px solid #eee;
border-radius: 6px;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
padding: 9px 10px;
}
.card .status {
width: 30px;
}
.card .stretchit, .card .action {
-webkit-flex: 1;
flex: 1;
}
#media screen and (min-width: 720px) {
.card .stretchit {
display: flex;
}
.card .title, .card .details {
-webkit-flex: 1;
flex: 1;
}
}
<div class="card">
<div class="status"></div>
<div class="stretchit">
<div class="title">Tryout.it</div>
<div class="details">156 emails</div>
</div>
<div class="action"><button>go</button></div>
</div>

Make flex child element occupy 100% height of parent flex [duplicate]

This question already has answers here:
HTML5 flexible box model height calculation
(2 answers)
Closed 4 years ago.
I have a container flex with content flexes. How do i make content flex occupy full width and height of container flex.
<div id="main">
<div id="main-nav">
</div>
<div class="container">
<div class="content"></div>
<div class="content"></div>
</div>
</div>
#main{
display: flex;
flex-direction: column;
height: 100vh;
width: 100vw;
}
#main-nav{
width: 100%
height: 50px;
}
.container{
display: flex;
flex-direction: row;
flex-wrap: wrap;
flex: 1;
}
.content{
display: flex;
width: 100%;
height: 100%;
}
The above code makes content to occupy 100% width of container but height is based on the text within the content. I tried the solutions mentioned from similar questions but had no luck and it was still the same.
Basically, I want each of the content to occupy the same height as occupied by the container in the viewport height. I also tried jQuery,
var rht = $("#container").height();
$(".content").height(rht);
It changes the height properly but adds a horizontal scroll bar with increase in width.
After several updates to the original question:
* {
box-sizing: borderbox;
margin: 0;
padding: 0;
}
#main {
display: flex;
flex-direction: column;
border: 1px solid red;
min-height: 100vh;
}
#main-nav {
flex: 0 0 50px;
}
.container {
display: flex;
flex-direction: column;
flex: 1;
border: 1px solid green;
}
.content {
flex: 1;
border: 1px solid orange;
}
<div id="main">
<div id="main-nav"></div>
<div class="container">
<div class="content"></div>
<div class="content"></div>
</div>
</div>
JSfiddle Demo
You cannot set width or height of flex's child is bigger (size of flex)/(number of flex's childs) but you can add position: absolute into .content and position: relative into .container then set width and height for .content. First .content is under second .content, you can use propety z-index or display: none to control.
* {
box-sizing: borderbox;
margin: 0;
padding: 0;
}
#main {
display: flex;
flex-direction: column;
background: red;
min-height: 100vh;
}
#main-nav {
flex: 0 0 50px;
}
.container {
position: relative;
display: flex;
flex: 1;
background: green;
}
.content {
position: absolute;
left: 0px;
top: 0px;
height: 100%;
width: 100%;
flex: 1;
background: orange;
}
<div id="main">
<div id="main-nav"></div>
<div class="container">
<div class="content">left</div>
<div class="content">right</div>
</div>
</div>

Resources