New to Flexbox - what do I need to do? - css

The code has three divs that are ordered in the dom by div-00#
What I'd like to create using flexbox (for width >= 460px) is the following layout (please see images)
Added: 18-12-16 -
is anyone able to suggest how to do this using flexbox?
There is a second issue with the tab order but would appreciate sorting the layout first.
ON MOBILE (say < 460px) - within the .div-main:
All the divs are 100% of the parent div, ordered .div-001 -div-002 .div-003.
ON DESKTOP (say >= 460px) - within the .div-main:
Because of varying heights I'm not using floats, as this happens on desktop
.
.div-001 -- Position: Top Right. Height: Varying. Width: 20%. Ideally the tab index should be 2 (therefore I've used flex to order this '2') but know that the order is read out by the order of the DOM.
.div-002 -- Position: Top Left. Height: Varying. Width: 80%. Ideally the tab index should be 1 (therefore I've used flex to order this '1')
.div-003 -- Position: Right (Directly below .div-003). Height: Varying. Width: 20%. Ideally the tab index should be 3 (therefore I've used flex to order this '3')
The order (just in case you were wondering) is important.
* {
margin: 0;
padding: 0;
border: 0;
}
a:focus,
a:hover {
color: red;
}
.header,
.footer {
width: 100%;
max-width: 1220px;
margin: 0 auto;
background: #000;
}
.header {
height: 50px;
}
.footer {
height: 20px;
}
.div-main {
width: 90%;
max-width: 1200px;
margin: 0 auto;
padding: 10px 0;
}
.div-main > div {
min-height: 50px;
box-sizing: border-box;
border: 1px solid #f00;
padding: 10px;
}
#media all and (min-width: 460px) {
.div-main {
display: flex;
flex-direction: column;
}
.div-desktop-left {
width: 80%;
margin-right: auto;
}
.div-desktop-right {
width: 20%;
margin-left: auto;
}
.div-001 {
/* example */
height: 70px;
order: 2;
}
.div-002 {
/* example (varying height) */
align-self: flex-start;
/* smaller than .div-001 */
height: 50px;
/* bigger than .div-001 */
/* height: 360px; */
order: 1;
}
.div-003 {
/* example */
height: 20px;
order: 3;
}
}
<header class="header"></header>
<div class="div-main">
<div class="div-001 div-mobile-001 div-desktop-002 div-desktop-right div-desktop-right-001">Desktop link 002</div>
<div class="div-002 div-mobile-002 div-desktop-001 div-desktop-left div-desktop-left-001">Desktop link 001</div>
<div class="div-003 div-mobile-003 div-desktop-003 div-desktop-right div-desktop-right-002">Desktop link 003</div>
</div>
<footer class="footer"></footer>

Couldn't figure it out with flexbox,
Heres a solution using CSS Grid if you're not technology restricted:
HTML
body {
margin: 0;
padding: 0;
}
main {
display: grid;
grid-template-columns: 3fr 1fr;
height: 300px;
}
.box {
border: 5px solid red;
padding: 50px;
}
.box.three {
grid-column: 2;
}
#media (max-width: 460px) {
main {
display: flex;
flex-flow: column;
}
.box {
border-color: black;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Flexer</title>
</head>
<body>
<main>
<div class="box one">one</div>
<div class="box two">two</div>
<div class="box three">three</div>
</main>
</body>
</html>

The problem is with giving .div-main a flex-direction: column by doing that .div-desktop-left and .div-desktop-right will not align next to each other what you need change is to give .div-main flex-direction: row and flex-wrap: wrap and that will solve the problem
* {
margin: 0;
padding: 0;
border: 0;
}
a:focus,
a:hover {
color: red;
}
.header,
.footer {
width: 100%;
max-width: 1220px;
margin: 0 auto;
background: #000;
}
.header {
height: 50px;
}
.footer {
height: 20px;
}
.div-main {
width: 90%;
max-width: 1200px;
margin: 0 auto;
padding: 10px 0;
}
.div-main > div {
min-height: 50px;
box-sizing: border-box;
border: 1px solid #f00;
padding: 10px;
}
#media all and (min-width: 460px) {
.div-main {
display: flex;
flex-direction: row;
flex-wrap:wrap;
}
.div-desktop-left {
width: 80%;
margin-right: auto;
}
.div-desktop-right {
width: 20%;
margin-left: auto;
}
.div-001 {
/* example */
height: 70px;
order: 2;
}
.div-002 {
/* example */
align-self: flex-start;
height: 50px;
order: 1;
}
.div-003 {
/* example */
height: 20px;
order: 3;
}
}
<header class="header"></header>
<div class="div-main">
<div class="div-001 div-mobile-001 div-desktop-002 div-desktop-right div-desktop-right-001">Desktop link 002</div>
<div class="div-002 div-mobile-002 div-desktop-001 div-desktop-left div-desktop-left-001">Desktop link 001</div>
<div class="div-003 div-mobile-003 div-desktop-003 div-desktop-right div-desktop-right-002">Desktop link 003</div>
</div>
<footer class="footer"></footer>

Related

How can I fix column spanning issue in css flex box

check image for better understanding
I want box three(blue) to come right below box one(red) currently white space inbetween them.
Here, the content height of the box two(gree) is greater than box one hence stretching that extra space. I need to cover up that empty white space .
I can not use GRID here, as I already used react-bootstrap Row/Col on my entier react site.
https://codesandbox.io/s/suspicious-david-i2vnht?file=/src/index.js:23-322
I used flexbox and tried using
aligh-items:flex-start/flex-end
does not work.
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: sans-serif;
}
#app {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
}
.one,
.two,
.three,
.four {
flex-grow: 1;
}
/* .one,.two,.three,.four, .five,.six{
flex-grow:1;
width:33%;
} */
.one {
background: red;
padding: 50px;
order: 0;
width: 67%;
}
.two {
background: green;
order: 1;
padding: 1rem;
width: 33%;
height: 30vh;
}
.three {
background: blue;
order: 2;
width: 67%;
height: 50vh;
}
.four {
background: tomato;
order: 3;
width: 33%;
}
.five {
background: goldenrod;
order: 1;
}
.six {
background: orange;
order: 0;
}
<div id="app">
<div class="one">ONE</div>
<div class="three">THREE</div>
<div class="two">Two</div>
<div class="four">FOUR</div>
<!-- <div class="five">Five</div> -->
<!-- <div class="six">Six</div> -->
</div>

CSS: Is it possible to achieve the following layout?

Is it possible to achieve the following responsive design layout shown in the image below using CSS3 Flexbox? I am able to achieve the desktop layout using the code below. However, I can't think of a way to make div #div3 and #div4 fill below #div1 and #div2
EDIT: I'm sorry that I forgot to mention that it is not restricted to CSS Flexbox only, and it seems like the grid solution would be more flexible so I will just mark it as the accepted answer. Thanks for the help guys!
My code
#div1 {
background-color: red;
width: 100px;
height: 100px;
}
#div2 {
background-color: green;
width: 100px;
height: 100px;
}
#div3 {
background-color: orange;
width: 100px;
height: 100px;
}
#div4 {
background-color: blue;
width: 100px;
height: 100px;
}
.container,
#flex-container {
display: flex;
}
#flex-container {
flex-direction: column;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="test.css">
</head>
<body>
<div class="container">
<div id='div1'></div>
<div id="flex-container">
<div id='div2'></div>
<div id='div3'></div>
<div id='div4'></div>
</div>
</div>
</body>
</html>
Using grid in this case would make it much easier.
Every div here has a grid-area set to some value that is used to indicate how it should behave in the grid according to layout rules defined in .container grid-template-areas every string there defines one row in the grid. The grid-template-rows and grid-template-columns are used to define number of rows and columns
* {
box-sizing: border-box;
}
body {
height: 100vh;
margin: 0;
}
#div1 {
background-color: red;
width: 100%;
height: 100%;
grid-area: div1;
}
#div2 {
background-color: green;
width: 100%;
height: 100%;
grid-area: div2;
}
#div3 {
background-color: orange;
width: 100%;
height: 100%;
grid-area: div3;
}
#div4 {
background-color: blue;
width: 100%;
height: 100%;
grid-area: div4;
}
.container {
display: grid;
height: 100%;
grid-gap: 10px;
padding: 10px;
grid-template-rows: repeat(3, 1fr);
grid-template-columns: repeat(2, 1fr);
grid-template-areas: "div1 div2" "div3 div3" "div4 div4";
}
#media (max-width: 768px) {
.container {
grid-template-areas: "div1 div2" "div1 div3" "div1 div4";
}
}
<div class="container">
<div id='div1'></div>
<div id='div2'></div>
<div id='div3'></div>
<div id='div4'></div>
</div>
Yes. First, you could put all the divs inside the same container:
<div id="flex-container">
<div id='div1'></div>
<div id='div2'></div>
<div id='div3'></div>
<div id='div4'></div>
</div>
Then, in container you set flex-direction: column and flex-wrap: wrap. You put width 50% if you want half screen and 100% full screen. The flex-wrap setup will organize items as it should be.
In mobile #media, you change flex-direction to row and width of each div to match the layout you want.
It would be like this:
#div1 {
background-color: red;
height: 100%;
width: 50%;
}
#div2 {
background-color: green;
height: 100px; // or 33.333%
width: 50%;
}
#div3 {
background-color: orange;
width: 50%;
height: 100px; // or 33.333%
}
#div4 {
background-color: blue;
width: 50%;
height: 100px; // or 33.333%
}
#flex-container {
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 300px;
}
#media (max-width: 480px) { // screen width you prefer
#flex-container {
display: flex;
flex-direction: row;
}
#div1 {
width: 50%;
height: 100px;
}
#div2 {
width: 50%;
}
#div3 {
width: 100%;
}
#div4 {
width: 100%;
}
}
Hope it helps.
You could even simplify CSS using classes for repeated properties.

Responsive design - mantain the aligment of a div to the left when the width becomes smaller

I have the following layout:
a wrapper that get all the width of the browser
a wrapper-right(menu) that is always close to the browser right
header that has a max width and is centered
content align with header
When the resolution is below a specific step(32rem) and wrapper_right get close to the header I want the header to get a smaller width, so the wrapper_right doesn't go over it.
The problem is that the header doesn't remain align to the left to the content, being set to left,right auto.
I try to use margin-left:80px, but doesn't work properlly.
If the resolution goes below 27rem I want the wrapper_right to be hidden, and header back to normal.
OBS. 27rem, 32rem are just for example, to be visible in the code box. I can modify the html code if is necessary.
.wrapper {
height: 6rem;
position: relative;
width: 100%;
background-color: red;
display: inline-block;
}
.header {
margin: 1.5rem auto 0;
max-width: 30rem;
background-color: blue;
}
#media (max-width: 32em) {
.header {
max-width: calc(30rem - 80px);
}
}
.wrapper-right {
background: green;
height: 100%;
position: absolute;
right: 0;
top: 0;
width: 80px;
}
.content {
max-width: 30rem;
margin: 0 auto;
background-color: orange;
}
<div class="wrapper">
<div class="header">
<div> lorem ipsum></div>
<div> lorem ipsum></div>
<div> lorem ipsum></div>
</div>
<div class="wrapper-right">menu</div>
</div>
<div class="content">content</div>
Is this what you're after?
https://codepen.io/panchroma/pen/PxKBBV
The important bits in the CSS are:
lines 36-40 where we're scaling the width of .header at viewports below 40rem
lines 42 - 50 where we're hiding .wrapper-right, and restoring .header to full-width
As an FYI, your CSS has a class titled .l-header but I couldn't see where you were going with this.
Hope this helps!
HTML
As originally posted
CSS
.wrapper {
height: 6rem;
position: relative;
width: 100%;
background-color: red;
display: inline-block;
}
.header {
margin: 1.5rem auto 0;
max-width: 30rem;
background-color: blue;
}
#media (max-width: 32em) {
.l-header {
max-width: calc(30rem - 80px);
}
}
.wrapper-right {
background: green;
height: 100%;
position: absolute;
right: 0;
top: 0;
width: 80px;
}
.content {
max-width: 30rem;
margin: 0 auto;
background-color: orange;
}
#media (max-width: 40rem) {
.header{
width:calc(75vw - 80px);
}
}
#media (max-width: 27rem) {
.wrapper-right{
display:none;
}
.header{
width:100%;
}
}
Version 2
Based on your comments, here's version 2
https://codepen.io/panchroma/pen/VVMJxM
The important bits are that I added the .header-wrapper. Then we're changing the left and right padding on .header-wrapper at various viewports to keep the header and content divs aligned.
Good luck!
HTML
<div class="wrapper">
<div class="header-wrapper">
<div class="header">
<div> lorem ipsum></div>
<div> lorem ipsum></div>
<div> lorem ipsum></div>
</div>
</div>
<div class="wrapper-right">menu</div>
</div>
<div class="content">content</div>
CSS
/* note that I'm using normalize.css in the CSS setings */
/* https://necolas.github.io/normalize.css/ */
.wrapper {
height: 6rem;
position: relative;
width: 100%;
background-color: red;
display: inline-block;
margin-right:80px;
}
.header {
margin: 1.5rem auto 0;
max-width: 30rem;
background-color: blue;
position:relative;
z-index:5;
}
.wrapper-right {
background: green;
height: 100%;
position: absolute;
right: 0;
top: 0;
width: 80px;
}
.content {
max-width: 30rem;
margin: 0 auto;
background-color: orange;
}
#media (max-width: 40rem) {
.header-wrapper {
/* add padding-right to make room for .wrapper-right */
/* have used 81px instead of 80px so we can be certain */
/* that the div isn't extending under .wrapper-right */
padding-right:81px;
/* add padding-left to keep .header and .content aligned */
/* logic is that the space to the left of .content */
/* is the half of the window width - width of .content */
padding-left:calc(50vw - 15rem);
}
}
/* at viewports below 27rem, hide .wrapper-right and return .header to full width */
#media (max-width: 27rem) {
.wrapper-right{
display:none;
}
.header-wrapper{
padding:0;
}
}

css grid with background - scroll when grid is bigger than the background

I have a table that can grow, once it grows it can push the grid height to be larger than the background.
I want that the grid itself will have a scroll on top of the background.
I tried to use overflow but did not succeed.
you can see the problem here
here is the relevant code:
.wrapper {
background-repeat: no-repeat;
background-position: top center;
height: 1024px;
min-width: 1055px;
display: grid;
grid-template-columns: 0.1fr 2.8fr 0.1fr;
grid-gap: 10px;
grid-template-rows: 100px auto auto 100px;
font-family: 'roboto',sans-serif;
overflow:visible;
/*grid-auto-rows: minmax(100px, auto);*/
/*border: 1px solid;*/
}
.wrapper > div {
display: flex;
justify-content: center;
/* align-items: center; */
font-size: 16px;
font-weight: 400;
/* border: solid 1px; */
color: #39393ac7 /*#39393A*/;
}
.header {
grid-column: 2 ;
}
.herbTable {
grid-column: 2 ;
}
.chart {
grid-column: 2 ;
}
.footer {
grid-column: 1 / -1 ;
grid-row: 4;
}
#media screen and (max-width : 1439px) /*and (max-width : 1439px) */
{
.wrapper {
background-image: url("~/static/bg1440px.jpg");
background-size: cover;
/* background-size: 1024px; */
/* width: 1024px; */
}
}
#media screen and (min-width : 1440px)
{
.wrapper {
background-image: url("~/static/bg1440px.jpg");
background-size: 1440px auto;
/* height: 1024px; */
width: 1440px;
}
}
<template>
<div class="wrapper">
<appHeader class="header"></appHeader>
<loading :active.sync="isLoading" :can-cancel="false"></loading>
<appHerbsTable v-if="!isLoading" class="herbTable"></appHerbsTable>
<appChart v-if="!isLoading" class="chart">chart</appChart>
<div class="footer"></div>
</div>
</template>
.wrapper {
/* overflow: visible; */
overflow: auto; /* NEW */
}
As you have fixed column widths this should be pretty easy changing your css to:
.herbTable thead {
display: block; /*inline-block should also be ok*/
}
.herbTable tbody {
display: block;
max-height: 300px;
overflow-y: scroll;
}
.. you will have to modify your td widths to make this look nice again
EDIT: (I hope I finally understand what you mean by grid)
html {
height: 100%;
}
body {
height: 100%;
box-sizing: border-box;
padding: 8px;
margin: 0;
}
.wrapper {
height: 100%;
overflow-y: auto;
}
.. hope this helps ..

Flex css layout with fixed and variable elements

I am hoping to create the following layout in pure CSS. I know that I can achieve this with a JavaScript solution, but a CSS solution would be much cleaner, if it is possible.
I have created a jsFiddle which I know is incorrect, to provide a starting point. The HTML and CSS I use in the jsFiddle are shown below.
Notes:
I would like this to fill the full height of the window, so that there is no scroll bar for the page (but see my last point)
There are two sections that can contain a variable number of elements.
The red elements are images which the user can add on the fly, and which will be given a frame with a fixed aspect ratio (shown here as a square)
The green section will contain a list which will have at least one item, so it will have a fixed minimum height. It may have up to four items, so its height may change. I would prefer not to have this section scroll. If the user makes the window too short for both the green and the blue elements to show full height, then the page as a whole will have to scroll.
My question is: can this be done in pure CSS? If you know that there is a solution, and if you can provide some pointers as to how I can achieve it, then I can continue to work towards that solution. If you know that there is no solution, then I will simply adopt a JavaScript approach.
If there is a solution, and you would be happy to share it, then I will be delighted that you have saved me a lot of time.
<!DOCTYPE html>
<html>
<head>
<title>Flex</title>
<style>
body, html {
height: 100%;
margin: 0;
background: #000;
}
main {
width: 30em;
height: 100%;
margin: 0 auto;
background: #333;
display: flex;
-webkit-flex-direction: column;
flex-direction: column;
}
.head{
width:100%;
-webkit-flex: 3em;
flex: 3em;
background: #fcc;
}
.expand{
width:100%;
overflow:auto;
}
.filler {
width:100%;
height:20em;
background: #003;
border-bottom: 1px solid #fff;
}
.space {
width:100%;
height:10em;
border-bottom: 1px solid #fff;
}
.foot{
width:100%;
-webkit-flex: 0 0 2em;
flex: 0 0 2em;
background: #cfc;
}
</style>
</head>
<body>
<main>
<div class="head">HEAD</div>
<div class="expand">
<div class="space"></div>
<div class="filler"></div>
<div class="space"></div>
</div>
<div class="foot">FOOT</div>
</main>
</body>
</html>
If I understand it well,
main {
height: auto;
min-height: 100%;
}
.head {
min-height: 3em;
}
.foot {
min-height: 2em;
}
.expand {
flex-basis: 0; /* Initial height */
flex-grow: 1; /* Grow as much as possible */
overflow: auto;
}
body,
html {
height: 100%;
margin: 0;
background: #000;
}
main {
width: 20em;
min-height: 100%;
margin: 0 auto;
background: #333;
display: flex;
-webkit-flex-direction: column;
flex-direction: column;
}
.head {
width: 100%;
min-height: 3em;
background: #fcc;
}
.expand {
width: 100%;
flex-basis: 0;
flex-grow: 1;
overflow: auto;
}
.filler {
width: 100%;
height: 20em;
background: #003;
border-bottom: 1px solid #fff;
}
.space {
width: 100%;
height: 2em;
border-bottom: 1px solid #fff;
}
.foot {
width: 100%;
min-height: 2em;
background: #cfc;
}
<main>
<div class="head">HEAD</div>
<div class="expand">
<div class="space"></div>
<div class="filler"></div>
<div class="space"></div>
</div>
<div class="foot">FOOT</div>
</main>

Resources