Responsive web design scenario - css

I am designing a 3 column web page layout like below.
To make it responsive I specified widths in %, min width in pixels and float:left. Now If I resize the page, all 3 DIVs (1,2, and 3) get resized first then 3rd DIV moves below of 1st DIV. If I resize more then 2nd DIV moves to below of 1st and 3rd moves below to 2nd.
This is because of float property. But I want to modify it in such a way that 3rd DIV should be moved first (as it is already being) then 1st DIV should be moved instead of 2nd DIV. 2nd DIV must be on the top.
How can I do this?

Reordering can be done with Flexbox. You will, however need 1 media query.
http://codepen.io/cimmanon/pen/fwqed
body {
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row wrap;
-ms-flex-flow: row wrap;
flex-flow: row wrap;
}
div {
-webkit-flex: 1 1 20em;
-ms-flex: 1 1 20em;
flex: 1 1 20em;
}
#media (max-width: 40em) {
.a, .c {
-ms-flex-order: 1;
-webkit-order: 1;
order: 1;
}
}
.a {
background: orange;
}
.b {
background: yellow;
}
.c {
background: grey;
}
Reordering can also be done with relative positioning (see: https://stackoverflow.com/questions/16307621/reordering-elements-at-specific-browser-widths).

Sorry I had some missed some details on how it should look earlier, here is another solution with some simple jQuery/javascript:
http://jsfiddle.net/jzxww/4/
This solution has Column 1 move to the bottom instead of to the middle.
Here is the code broken down
function resizeHandlr(){
trigger = $("#superwrap").width(); // get width of wrapper
$("#supersize").html("superwrap size: " + trigger + "px");
if (trigger > 600){
// if greater than 600px, make all widths 33.33% so they are responsive;
} else if ( (trigger < 600) && (trigger > 400)){
// if between 600 and 400px, make top columns 50% and bottom one 100%
// move column1 back to top of wrapper (if coming from < 400px)
} else if (trigger < 400) {
// if wrapper is less than 400px, make all widths 100%
// also MOVE column 1 to the bottom of wrapper
}
}

try this
//css
.left-col{float:left;width:33%}
.right-col{float:right;width:33%}
.main-col{margin: 0 33%}
//html
<div class="left-col"> some text </div>
<div class="right-col"> some text </div>
<div class="main-col"> some text </div>

I got pretty close to a 2,3,1. Check it out: http://jsfiddle.net/3QFaa/
New HTML Markup
<div id="superwrap">
<div id="muahaha">
<div id="col2">2</div>
<div id="col3">3</div>
</div>
<div id="col1">1</div>
CSS
#superwrap { position: relative; width: 100%; background-color: orange; min-width: 200px;}
#muahaha {top: 0px; width:66.66%; float: right; min-width: 200px; }
#muahaha:after {
content: "";
display: table;
clear: both;}
#col2, #col3 { float: left;}
#col1 { background-color: cyan; width: 33.33%; min-width: 200px;}
#col2 {background-color: yellow; width: 50%; min-width: 200px;}
#col3 { background-color: green; width: 50%; min-width: 200px;}
Thanks #sebastianG for the fiddle.
Only problem with this is, as you notice, col1 does not drop until it hits the very far right edge of #superwrap
Another nearly-perfect version:
If col1 does not have to be centered immediately:
http://jsfiddle.net/XDTEW/
Added float: left to col1
I also think you will be better using #media queries for different screen size scenarios.

Related

Flexbox - move middle element to the next line (without media query)

What I want to achieve (but without the media query):
JsFiddle
#media all and (max-width: 600px) {
#wrapper {
flex-wrap:wrap;
height: 100px;
}
.center {
width: 100%;
order: 3;
}
.left{
width: 50%;
}
.right {
width:50%;
order:2;
}
}
I have 3 elements inside a wrapper, all shrinked. At desktop size, there is some space left over, however when I resize my window to a smaller dimension, at some point, elements run out of space. When that happens, I want to put the middle element to the next line. I have a solution, where the third element goes to the next line, and JSFiddle solution, where the second element goes to the next line, but always at the same static width.
So is it possible to put the middle element to the next line, when all three shrinked elements run out of space?
You can definitely wrap the line without media queries by using flex-wrap, flex-grow, flex-shrink and flex-basis to specify a minimum width that any given item should have:
#wrapper{
display: flex;
width: 100%;
height: 50px;
align-items: center;
text-align: center;
flex-wrap: wrap;
}
.right{
width: 20%;
background-color: blue;
order: 3;
flex-grow: 1;
flex-shrink: 0;
flex-basis: 200px;
}
But it's not possible to change the flex-order based solely on whether the elements "fit". For that you definitely need a media query.

full height columns and header with flexbox

I'm newish to flexbox. My current layout isn't working as well as I'd hoped - my columns are only as tall as the content within them.
+----------------+
| header |
+-+--------------+
|n|content |
|v+--------------+
+-+
empty
----------------------
I'm hoping flexbox will solve that. I'll have to retrofit my existing markup.
Page is full screen width, with a full-width header, then the rest of the page is fluid width content with a fixed width sidebar. (Some pages have a sidebar on the left, others have one on the right.)
Ideally, the two content areas will both extend to the bottom of the page (with their coloured backgrounds) but only go over the fold and scroll if the content is longer than a page.
+----------------+
| header |
+-+--------------+
|n| content |
|a| |
|v| |
--+-+--------------+--
Do I treat the entire page as the "container", in which I create two rows, one of which is split? Or do I just start the flexbox stuff with the second row that has the sidebar?
It seems to me, it has to be the former, if flexbox is to know how high my header is. Otherwise, when I set their heights to 100%, they'll go over the fold by an amount equal to my header.
I didn't see a header-and-split-columns as a simple example in the flexbox docs, but I'll continue to read and experiment.
(Naturally, it will also have to be responsive, so that, at smaller screen sizes, the elements wrap under each other to fit on a narrow screen.)
OK, gathering all the feedback I've gotten above, and borrowing heavily from here, this is what I came up with.
<div class="page-body no-nav no-aside">
<main>
<p>content</p>
</main>
<nav>nav</nav>
<aside>details</aside>
</div>
.
.wrapper {
display: flex;
min-height: 100vh;
flex-direction: column;
background-color: blue;
header {
height: 155px;
}
.page-body {
display: flex;
flex: 1;
background-color: lavender;
flex-direction: column;
min-height: calc(100vh - 155px);
min-height: -webkit-calc(100vh - 155px);
nav {
order: -1;
background-color: red;
}
aside {
background-color: orange;
}
&.no-nav nav,
&.no-aside aside {
display: none;
}
}
}
#media (min-width: 768px) {
.wrapper {
.page-body {
flex-direction: row;
flex: 1;
main {
flex: 1;
}
nav {
flex: 0 0 385px;
}
aside {
flex: 0 0 320px;
}
}
}
}
Header is fixed height
Page-body fills the rest of the page
pretty straightforward to add a footer if needed (see Holy-Grail article above)
all columns are full height, no scrolling unless content flows
sidebars are fixed width, content body is fluid
structure is responsive
added some functionality to hide/show the sidebars as-needed per page
Oddly, this defaults to small-screen as has a media query that overrides for larger screens. (Usually the other way around where I come from.)
You can use calc for the min-height (assuming header height as 50px):
.content {
min-height: calc(100% - 50px);
min-height: -webkit-calc(100% - 50px);
}
As for the fixed width sidebar, prevent it from growing or shrinking:
.sidebar {
flex-shrink: 0;
flex-grow: 0;
}
I would only put the sidebar and the content in the flex box. Put both the sidebar and the content inside a container div and assign display:flex to the container:
.container {
display: flex;
flex-direction: row;
}
You will likely need your sidebar to collapse or become fluid with media queries when the window width decreases to a certain point. Also, I find this tool helpful when working with flex, as it does get complex.
You can create two flexboxes - one to divide header and "rest", and the other inside "rest" to divide it into nav and content.
Also you can just set min-height of header, as can be seen here
I hope I've understood your question.. This approach might help get you started. Let me know if you have any specific questions...
body {
margin: 0;
height: 100vh;
font-family: sans-serif;
color: white;
}
.container {
height: 100%;
background: grey;
display: flex;
flex-direction: column;
}
header {
height: 150px;
background: blue;
}
.content {
height: 100%;
display: flex;
background: green;
}
.sidebar {
background: #76c5ff;
width: 200px;
}
.main {
background: #ef3a59;
flex: 1;
}
#media (max-width: 600px) {
body {
height: initial;
}
.content {
height: initial;
}
.content {
flex-direction: column;
}
.sidebar {
width: 100%;
order: 2; /* remove this to keep sidebar above main content */
}
}
<div class="container">
<header>header
</header>
<div class="content">
<div class="sidebar">sidebar</div>
<div class="main">main content</div>
</div>
</div>

CSS Flexbox height

I'm trying to make a chat layout. So i have 3 divs, activeUSer - top, messages middle (has to fill the space between 1 and 3), actions - bottom
Now, I've put flex-direction row. and it works fine. I needed the bottom div to grow if the input grows (if you have 2 or more lines of writing)
It worked ok untill I added display:flex to the Actions div (bottom). I needed another flex layout for input and buttons. Now it does not care for the padding i've set on the last div
Here is my codepen https://codepen.io/capraruioan/pen/XKWxrV
#content {
height: 300px;
display: flex;
flex-direction: column;
}
.activeUser {
height: 66px;
background-color: yellow;
}
.Messages {
flex: 1 1 100%;
}
.Actions {
flex-grow: 1;
display: flex;
padding-top: 2px;
padding-bottom: 20px;
}
.aa { //the inputbox
border: 1px solid black;
min-height: 10px
}
fixed it by letting display default on the 3rd div and placing a div with display flex inside

Why does "flex-wrap: wrap" break "align-items"?

(I'm using Chrome v.39+)
I'm trying to use the flex-wrap property to stack child divs both horizontally and vertically, but I'm seeing some very strange behaviors. For example, if there's 3 child divs and the last is given a width of 100% (causing it to wrap) there will be unwanted gaps introduced.
Sometimes I can force the first 2 divs to honor align-items: stretch by giving them height: 100% or height: calc(100% - 1px), other times they won't stretch passed the mysterious gap, and sometimes they'll even disappear all together if I try to force them to stretch.
Here's a simplified example of the problem. They grey shouldn't be visible.
Why are these gaps appearing in flex-wrapped divs and how can I prevent them?
The gray area is still visible at the bottom because you set a height on the parent container.
If you don't want to see that gray area, remove the height from the container and add a fixed height that you require on one of the elements in the first row
DEMO
.a {
width: 300px;
display: flex;
flex-wrap: wrap;
position: relative;
top: 100px;
left: 200px;
background-color: #999;
}
.b {
height: 150px;
background-color: #00ff00;
}
.c {
background-color: #0000ff;
}
.d {
background-color: #ff0000;
}
.b {
flex-grow: 1;
flex-shrink: 0;
}
.c {
width: 5px;
flex-shrink: 0;
}
.d {
width: 100%;
height: 10px;
flex-shrink: 0;
}
<div class='a'>
<div class='b'></div>
<div class='c'></div>
<div class='d'></div>
</div>
Note: If you want to avoid fixed dimensions - just remove the height:10px from the red div.
This will ensure that there are no gaps and that each row has equal height
DEMO

flexbox one element fixed height, other filling

I want to make some kind of image viewer with some descriptive text below. Problem is, that the lower box with the description has a fixed height and the image should fill the remaining height of whatever container it is in.
I wanted to use flexbox for that, as I think it seems to be the most elegant and simple solution (without using JS).
This this code and codepen for my current work, which seems to work mostly:
html, body, #container {
height: 100%
}
#container {
display: flex;
flex-direction: column;
}
#container > #image {
/* flex-grow: 1; */ /* not needed here? */
max-width: 75%;
background-color: #fcc;
margin: 0 auto;
}
img {
max-height: 100%;
/* HERE IS WHERE MY PROBLEM STARTS!; */
max-width: 100%;
}
#container > #text {
flex-grow: 0;
flex-shrink: 0;
background-color: rgba(128, 128, 128, 0.7);
padding: 5px;
max-width: 75%;
margin: 15px auto 0;
/* TOP MARGIN DOESN'T WORK */
}
http://codepen.io/Kageetai/pen/AaCJy
I got most of it to work but the image is not resizing itself correclty. As you can see through the transparent background of the text box, it stretches itself over the border of the containing div and even behind the text box.
So how can I retain the image with the correct aspect ratio inside its container?
And furthermore the centering with margin: 0 auto; seems to make problems when resizing the window. The image is not centered anymore and the page needs a refresh to make it work again.
So does anyone know how to make the image behave correctly? :)
For image , you can set an height, margin and display.
For image container, give a 2 or 3 value to flex and none to other, so it fills as much space as avalaible.
DEMO
CSS used :
html,
body,
#container {
height: 100%
}
#container {
display: flex;
flex-direction: column;
}
#container > #text {
background-color: #ccf;
padding: 5px;
}
#container>#image {
flex:3;
display:flex;
}
img {
width:auto;
display:block;
margin:auto;
height:100%;
}
Here's a more basic demo of how to achieve this.
<html style="height: 100%">
<body style="height: 100%; margin: 0; display: flex; flex-direction: column">
<p>Toolbar</p>
<div style="background: #bbb; flex: 1">Image</div>
</body>
</html>
A demo can be seen over at Codepen.

Resources