I'm playing around with flexbox to get the hang of it but I am running into some issues. My goal is to have the window separated by four background colors where the first is just a header row and then the rest of the page is filled by 3 columns each a different background color. But for some reason if I write display: flex it doesn't show anything. Can someone explain to me how to get this desired effect?
.container {
width: 100%;
height: 100%;
}
.header {
height: 150px;
background-color: red;
}
.col-container {
widows: auto;
height: auto;
display: flex;
flex-direction: row;
}
.col {
flex: 1;
}
.col-container:nth-child(1) {
background: green;
}
.col-container:nth-child(2) {
background: blue;
}
.col-container:nth-child(3) {
background: yellow;
}
<body>
<div class="container">
<div class="header"></div>
<div class="col-container">
<div class="col"></div>
<div class="col"></div>
<div class="col"></div>
</div>
</div>
</body>
Here is a working example:
.container {
width: 100%;
height: 100%;
}
.header {
height: 150px;
background-color: red;
}
.col-container {
widows: auto;
height: auto;
display: flex;
flex-direction: row;
}
.col-1 {
flex: 1 1 33.333%;
background-color: green;
}
.col-2 {
flex: 1 1 33.333%;
background-color: blue;
}
.col-3 {
flex: 1 1 33.333%;
background-color: yellow;
}
<body>
<div class="container">
<div class="header"></div>
<div class="col-container">
<div class="col-1">ts</div>
<div class="col-2">dtd</div>
<div class="col-3">dt</div>
</div>
</div>
</body>
Here's what you needed to fix:
Set flex-direction to row. You most likely want the columns next to each other.
Add the classes to your HTML for the col-1, col-2 and col-3.
You need content in those col classes, or you won't see anything anyway.
I set a flex-basis (the third parameter in the flex shorthand) to 33.333%. You don't necessarily need this, but it's nice to see how much space a particular element will fill or change it.
EDIT For the comments:
body {
margin: 0;
padding: 0;
}
.container {
width: 100%;
height: 100%;
}
.header {
height: 150px;
background-color: red;
}
.col-container {
widows: auto;
height: auto;
display: flex;
flex-direction: row;
height: calc(100vh - 150px);
}
.col-1 {
flex: 1 1 33.333%;
background-color: green;
}
.col-2 {
flex: 1 1 33.3333%;
background-color: blue;
}
.col-3 {
flex: 1 1 33.3333%;
background-color: yellow;
}
<body>
<div class="container">
<div class="header"></div>
<div class="col-container">
<div class="col-1"></div>
<div class="col-2"></div>
<div class="col-3"></div>
</div>
</div>
</body>
Basically, you need to give the col-container a height. To achieve this, I used vh units in the calc statement. It subtracts your header height from the viewport height and gives the remainder. This also removes the necessity for filler content.
Related
Consider the following:
* {padding: 0; margin: 0; }
body {
height: 100vh;
width: 100vw;
display: flex;
flex-direction: column;
}
header {
flex: 0 0 50px;
background-color: lightgray;
}
div#wrapper {
flex: 1 0 0px;
display: flex;
flex-direction: row;
}
aside {
background-color: darkgray;
flex: 0 0 50px;
}
main {
display: block;
flex: 1 1 0px;
background-color: aliceblue;
}
div#content {
width: 60px;
height: 2000px;
margin: 10px;
background-color: red;
}
div#content-wrap {
width: 100%;
height: 100%;
}
div#content-container {
height: 100%;
overflow-y: scroll;
}
<html>
<head></head>
<body>
<header></header>
<div id="wrapper">
<aside></aside>
<main>
<div id="content-wrap">
<div id="content-container">
<div id="content"></div>
</div>
</div>
</main>
</div>
</body>
</html>
In the snippet above, the <body> fills all the available space, it's consisted of a <header> which takes an arbitrary height and a <div id="wrapper"> that takes the rest of available height. The aforementioned "#wrapper" has a "sidebar" that has an arbitrary width and a "<main>" section to take the rest of the width. I want only the "main" section to be scrollable, but applying a long enough "#content" causes the "body" to get the scrollbar, instead! (while I've enforced the heights to be 100%) So, how to fix this?
here only remove same height according to <header></header> from <div id="wrapper"> bcz of normaly it will take 100% height #wrapper so only add height: calc(100% - 50px);
div#wrapper {
flex: 1 0 0px;
display: flex;
flex-direction: row;
height: calc(100% - 50px);
}
and it will be working like below ss
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>
I'm using Bootstrap v4 alpha4
Currently I have:
.row
.col-xs-12.col-md-8
div A
.col-xs-12.col-md-4
div B
div C
For the xs layout, I'd like the div order to be:
Div B
Div A
Div C
I have no idea how to do this or how to even ask about it. I'm not a front-end dev so I don't know what things are called.
We can change the HTML to whatever we want. It does not have to stay like it is now.
Bootstrap does have column ordering classes, but in this case you can simply use the responsive float classes..
<div class="row">
<div class="col-md-4 pull-md-right">
b
</div>
<div class="col-md-8">
a
</div>
<div class="col-md-4">
c
</div>
</div>
http://www.codeply.com/go/XL5zJELyLD
So using the classes from bootstrap and some general style you can achieve that like I did in this pen.
http://codepen.io/TunderScripts/pen/PGadpr
The Html:
<div class="row">
<div class="col-xs-12 col-md-4 pull-right col1"></div>
<div class="col-xs-12 col-md-8 pull-left col2"></div>
<div class="col-xs-12 col-md-4 pull-right col3"></div>
</div>
the css:
.col1{
background: red;
height: 200px;
}
.col2{
background: blue;
height: 600px;
}
.col3{
background: green;
height: 200px;
}
You can change the default behavior by using their classes for floats(pull-left, pull-right).
Instead of flexbox, I used combination of float and position css properties to get the expected result. Assuming large width as 150px and small width as 100px.
Working Fiddle
.container {
width: 250px;
position: relative;
}
.blue {
width: 150px;
height: 300px;
background: blue;
position: absolute;
}
.pink {
width: 100px;
height: 100px;
background: pink;
float: right;
}
.green {
width: 100px;
height: 100px;
background: green;
clear: right;
float: right;
}
#media (max-width: 450px) {
.blue {
position: relative;
}
.green,
.pink {
float: none;
width: 150px;
}
}
<div class="container">
<div class="pink"></div>
<div class="blue"></div>
<div class="green"></div>
</div>
As promised, a simple draft
HTML
<div class="row">
<div class="col1">DIV A</div>
<div class="col2">DIV B</div>
<div class="col3">DIV C</div>
</div>
CSS
.row {
display: flex;
flex-wrap: wrap;
flex-direction: row;
justify-content: space-between;
width: 400px;
margin: 0 auto;
}
.col1 {
width: 200px;
height: 400px;
background-color: #86a0ff;
}
.col2 {
width: 150px;
height: 150px;
background-color: #ff6cde;
}
.col3 {
margin-top: -200px;
margin-left: auto;
width: 150px;
height: 150px;
background-color: #35af6d;
}
#media (max-width: 768px) {
.row {
justify-content: center;
flex-direction: column;
}
.col1 {
order: 2;
width: 200px;
margin-top: 50px;
}
.col2 {
order: 1;
width: 200px;
}
.col3 {
order: 3;
width: 200px;
margin-top: 50px;
margin-left: 0;
}
}
As for explanation, here is a great guide to flexbox. The main idea in my example is that by using order property you can manipulate the order in which blocks are displaying. The main plus of using flexbox is that you won't need to load any library(such as Bootstrap) to achieve the desired result, such as responsiveness. And it also has a good browser support, unless you need to support older versions of browsers. I hope my answer will be helpful for you!
I'm trying to make a child div of a flexbox layout fill its parent. In any other context setting the width/height to 100% causes a div to fill its parent... I only wish to use flexbox for my top level layout.
Problems
#map-container div will not fill #col1 even though it has height 100% set.
#controls div appears outside #col1 completely. I've previously used absolute layout to align boxes to corners without problems. Being inside a flexbox grand-parent seems to cause issues.
What I'm expecting is #map-container and #map to fill #col1 and #controls to align to bottom right-hand corner of #map.
.wrapper, html, body {
height:100%;
margin:0;
}
#col1 {
display: flex;
}
#map-container {
background-color: yellow;
width: 100%;
height: 100%;
}
#map {
background-color: purple;
width: 100%;
height: 100%;
}
#controls {
background-color: orange;
position: absolute;
right: 3px;
bottom: 3px;
width: 100px;
height: 20px;
}
.wrapper {
display: flex;
flex-direction: column;
}
#row1 {
background-color: red;
}
#row2 {
flex:2;
display: flex;
}
#col1 {
background-color: green;
flex: 1 1;
}
#col2 {
background-color: blue;
flex :0 0 240px;
}
<div class="wrapper">
<div id="row1">Header</div>
<div id="row2">
<div id="col1">
<div id="map-container">
<div id="map">
Map
</div>
<div id="controls">Controls</div>
</div>
</div>
<div id="col2">Sidebar</div>
</div>
</div>
#map-container div will not fill #col1 even though it has height 100% set.
It won't work that way, because for a percentage unit to work, it needs to have height set on its parent all the way up. This fights against the flex model, where the flex-items are distributed and arranged by the flex-box layout and have no dimensions set. Why use a flex layout when all your elements are 100%? Either do a 100% on all your element all the way up, or do a flex on all containers.
If you stick to flex layout, then you will have to get into nested flex. Otherwise, you will get #map-container to fill-up, but not the #map.
This fiddle http://jsfiddle.net/abhitalks/sztcb0me illustrates that problem.
#controls div appears outside #col1 completely. I've previously used absolute layout to align boxes to corners without problems. Being
inside a flex-box grand-parent seems to cause issues.
The only issue is that you are positioning it absolutely, but in relation to what? You need to position your #map-container relatively for that to work.
Here is how:
Fiddle: http://jsfiddle.net/abhitalks/sztcb0me/1/
Snippet:
* { box-sizing: border-box; padding: 0; margin: 0; }
html, body, .wrapper { height:100%; width: 100%; }
.wrapper { display: flex; flex-direction: column; }
#row1 { flex: 0 1 auto; background-color: red; }
#row2 { flex: 2 0 auto; display: flex; }
#col1 { flex: 1 0 auto; display: flex; background-color: green; }
#col2 { flex: 0 0 240px; background-color: blue; }
#map-container {
flex: 1 0 auto; display: flex;
position: relative; background-color: yellow;
}
#map { flex: 1 0 auto; background-color: purple; }
#controls {
background-color: orange;
position: absolute;
right: 3px; bottom: 3px;
width: 100px; height: 20px;
}
<div class="wrapper">
<div id="row1">Header</div>
<div id="row2">
<div id="col1">
<div id="map-container">
<div id="map">
Map
</div>
<div id="controls">Controls</div>
</div>
</div>
<div id="col2">Sidebar</div>
</div>
</div>
the problem is that it's wrapped in #map-container
.wrapper, html, body {
height:100%;
margin:0;
}
#col1 {
display: flex;
}
#map-container {
background-color: yellow;
width: 100%;
height: 100%;
}
#map {
background-color: purple;
width: 100%;
/* height: 100%; */
display: flex;
flex-wrap: wrap-reverse;
justify-content: space-between;
}
#controls {
background-color: orange;
position: relative;
/*right: 3px;
bottom: 3px;*/
width: 100px;
height: 20px;
}
.wrapper {
display: flex;
flex-direction: column;
}
#row1 {
background-color: red;
}
#row2 {
flex:2;
display: flex;
}
#col1 {
background-color: green;
flex: 1 1;
}
#col2 {
background-color: blue;
flex :0 0 240px;
}
<div class="wrapper">
<div id="row1">Header</div>
<div id="row2">
<div id="col1">
<!-- <div id="map-container"> -->
<div id="map">
Map
<div id="controls">Controls</div> <!-- add it here -->
</div>
<!-- <div id="controls">Controls</div> -->
<!--</div> -->
</div>
<div id="col2">Sidebar</div>
</div>
</div>
adding an absolute position controls in that way is not optimal (in the snippet I commented it out) ; you can place the controlsnested in #map (and use flex properties for correcting placement)
I've just started to learn html and css. I'm trying to create a 3x3 grid with inline-block "method". This is the code so far:
HTML:
<!doctype html>
<html>
<head>
<link href="ex.css" rel="stylesheet" type="text/css">
<title>ex</title>
</head>
<body>
<div id="r1"></div>
<div id="r2"></div>
<div id="r3"></div>
<div id="r4"></div>
<div id="r5"></div>
</body>
</html>
CSS:
#r1 {
background-color: blue;
height: 300px;
width: 300px;
display: inline-block;
}
#r2 {
background-color: red;
height: 300px;
width: 300px;
display: inline-block;
}
#r3 {
background-color: blue;
height: 300px;
width: 300px;
display: inline-block;
}
#r4 {
background-color: green;
height: 300px;
width: 300px;
}
#r5 {
background-color: yellow;
height: 300px;
width: 300px;
}
Can someone help me to position #r5 (yellow box) near #r4 (green box) horizontally?
You need to wrap every row with another div like that:
HTML:
<body>
<div class="row">
<div id="r1"></div>
<div id="r2"></div>
<div id="r3"></div>
</div>
<div class="row">
<div id="r4"></div>
<div id="r5"></div>
</div>
</body>
CSS:
#r1 {
background-color: blue;
}
#r2 {
background-color: red;
}
#r3 {
background-color: blue;
}
#r4 {
background-color: green;
}
#r5 {
background-color: yellow;
}
.row > div{
display: inline-block;
height: 300px;
width: 300px;
}
Flex is here to save the day! This is exactly the type of thing flex was made for, but beware - support for it on old browsers isn't very good. If you don't care too much about old browsers then I suggest using flex, as formatting how the page looks via HTML is frowned upon.
See this JSFiddle.
HTML:
<div id="container">
<div class="box" id="r1"></div>
<div class="box" id="r2"></div>
<div class="box" id="r3"></div>
<div class="box" id="r4"></div>
<div class="box" id="r5"></div>
</div>
CSS:
#r1 {
background-color: blue;
}
#r2 {
background-color: red;
}
#r3 {
background-color: blue;
}
#r4 {
background-color: green;
}
#r5 {
background-color: yellow;
}
.box
{
height: 100px;
width: 100px;
-webkit-flex: 0 0 100px;
flex: 0 0 100px;
}
#container
{
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row wrap;
flex-flow: row wrap;
width: 300px;
}
This might not be sexy, but for basic purposes you could just add a line break every three divs:
<div id="r3"></div>
<br>
<div id="r4"></div>
Another alternative (perhaps more appropriate) is to set a fixed width for the container too, in your example:
body { width: 1000px; }
will actually take care of breaking the boxes apart, so every one of them could be inline-block.
And by the way, you don't need to keep duplicating all rules, try this:
div { display: inline-block; height: 300px; width: 300px; }