Flex Layout mixing rows and column - css

I can make this layout using float easily. but having hard time to do with flex box.
css :
.a {
background: red;
float: left;
width: 30%;
height: 100px;
}
.b,
.c {
background: green;
overflow: hidden;
height: 45px;
}
.b {
margin-bottom: 10px;
}
.c {
background: lightblue
}
html:
<div class="a">column</div>
<div class="b">row1</div>
<div class="c">row2</div>
many thanks in advance.

Flexbox codepen demo
How does it work?
Wrap your columns in a common parent (e.g. a main element) with an height set. Then place your elements with flex-direction: column and create a space between b and c with justify-content: space-between.
The height of the column a is 100% of the container so b and c can shift into a new column thanks to flex-wrap: wrap.
CSS
main {
display: flex;
flex-direction: column;
flex-wrap: wrap;
justify-content: space-between;
height: 100px;
}
.a {
background: red;
height: 100%;
width: 30%;
}
.b, .c {
background: green;
height: 45px;
width: 70%;
}
.c {
background: lightblue
}
Grid Layout demo
How does it work?
With Grid Layout you could achieve the same thing by creating a layout with 10 columns and 2 rows and a gap between b and c with row-gap: 10px. Then adjust all the various (column|row)-(start|end)
CSS
main {
display: grid;
grid-template-columns: repeat(10, 1fr);
row-gap: 10px;
width: 100%;
}
.a {
background: red;
grid-area: 1 / 1 / 3 / 3;
}
.b,
.c {
grid-column: 3 / 11;
background: green;
overflow: hidden;
height: 45px;
}
.b {
grid-row-start: 1;
}
.c {
grid-row-start: 2;
background: lightblue;
}

You can achieve this by using grid by wrapping a,b,c in a grid-container
.grid-container {
display: grid;
grid-template-columns: 1fr 1fr;
}
.a {
background: red;
/* width: 30%; */
height: 100px;
grid-row-start: 1;
grid-row-end: 3;
}
.b,
.c {
background: green;
overflow: hidden;
height: 45px;
}
.b {
margin-bottom: 10px;
}
.c {
background: lightblue;
}
<div class="grid-container">
<div class="a">column</div>
<div class="b">row1</div>
<div class="c">row2</div>
</div>

Related

Overlapping two boxes

I have been trying to have two boxes in CSS, one in the upper right hand corner of the other. I have been trying to nest divs and use relative positioning but I cannot figure out how to do it. Can someone help me? (Not using z index)
If I understand correctly that you want one box to be inside the other, you can achieve this using position: relative and moving the inner box using top, right, left and bottom.
I recommend diving in to the MDN page for CSS position for more information.
.box1, .box2 {
display: inline-block;
}
.box1 {
width: 200px;
height: 200px;
background: green;
}
.box2 {
position: relative;
width: 100px;
height: 100px;
top: -100px;
left: -100px;
background: orange;
}
<div class='box1'></div>
<div class='box2'></div>
You can use something like this. Using flexBox to align them and giving a negative margin to second box.
*,
*::before,
*::after {
box-sizing: border-box;
}
body {
min-height: 100vh;
margin: 0;
background-color: bisque;
display: grid;
place-content: center;
}
.container{
display: flex;
flex-direction: row;
}
.first{
height: 5rem;
width: 5rem;
background-color: tomato;
}
.second{
margin-top:-50%;
height: 5rem;
width: 5rem;
background-color: tomato;
}
<div class="container">
<div class="first"></div>
<div class="second"></div>
</div>
Based on Marcos answer i think i understand you wrong.
Here is a simple way get the result that you want. You can use position:relative to parent and position: absolute to child item. Then you can move child element inside. top:0; will take you to top corner and right:0; will take you to right corner.
*,
*::before,
*::after {
box-sizing: border-box;
}
body {
min-height: 100vh;
margin: 0;
background-color: bisque;
display: grid;
place-content: center;
}
.parent{
width: 10rem;
height: 10rem;
background-color: tomato;
position: relative;
}
.child {
width: 5rem;
height: 5rem;
background-color: aqua;
position: absolute;
top:0;
right: 0;
}
<div class="parent">
<div class="child"></div>
</div>
Spontaneously, I can think of two possibilities. 1) Work with 'position' or 2) work with 'margin'.
here an example with margin in combination flexbox;
.w {
background-color: lightgray;
display: flex;
justify-content: center;
padding: 20px;
}
.a, .b {
width: 150px;
height: 150px;
}
.a {
background-color: lightblue;
}
.b {
background-color: lightgreen;
margin-top: 20px;
margin-left: -20px;
}
<div class="w">
<div class="a">A</div>
<div class="b">B</div>
</div>

Grid Layout - Square Photo Wall

I tried to rebuild this Square Grid: how-to-create-a-flexible-square-grid-with-css-grid-layout
It works until I put images into the grid elements: Photo wall
.square-container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
grid-auto-rows: 1fr;
grid-auto-flow: dense;
}
.square-container::before {
content: '';
width: 100%;
height: 0;
padding-bottom: 100%;
grid-row: 1 / 2;
grid-column: 1 / 1;
}
.square-container > *:first-child {
grid-row: 1 / 1;
grid-column: 1 / 1;
}
/* Just to make the grid visible */
.square-container > * {
background: rgba(0,0,0,0.1);
border: 1px solid grey;
opacity: 0.75;
}
.square-container > *:focus,
.square-container > *:hover {
border: 1px solid blue;
opacity: 1;
}
.square-container img
{ object-fit: contain; width:100%; height:auto; padding:0; margin:0; }
How can I fit the img-elements into the whole size of the grid-element?
.square-container img {
object-fit: cover;
width:100%;
height:100%;
}
creates a rectangle. A fixed grid-auto-rows: 15rem creates a near-square but then I can abstain from the pseudo element.

flexbox align items shifted from center without fillers

Centering a flex item is easy. However I like to shift it upwards a bit so that the the relation between the upper and lower space is e. g. 1/2. Easy too when using fillers. But is there a way to do this whithout fillers?
HTML:
<div id="filler-top"></div>
<div id="the-item">
</div>
<div id="filler-bottom"></div>
CSS:
#the-item {
width: 80vw;
height: 30vh;
border: 2px solid lightblue;
}
body {
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
}
#filler-top {
width: 100%;
flex: 1;
}
#filler-bottom {
width: 100%;
flex: 2;
}
https://jsfiddle.net/Sempervivum/b2wotc8e/3/
Applying margin-top and margin-bottom doesn't work as a percentage is relative to the width.
instead of adding 2 elements to the markup, you can use :before and :after pseudo-elements:
#the-item {
width: 80vw;
height: 30vh;
border: 2px solid lightblue;
}
body {
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
}
body:before {
content: "";
width: 100%;
flex: 1;
}
body:after {
content: "";
width: 100%;
flex: 2;
}
<div id="the-item"></div>
Another option is to simply use a mixture of position:relative, top and transform:
#the-item {
width: 80vw;
height: 30vh;
border: 2px solid lightblue;
position: relative;
top: 33.333%;
transform: translateY(-33.333%);
}
body {
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
}
<div id="the-item"></div>

Setting layout with flexbox

I have a wireframe below and want to see what's the best way to code this with flexbox.
I have coded a simple flexbox grid system but my wireframe requires more customization than what I have on my grid system.
I have parent div has display: flex and have 2 child divs have flex:1 and flex: 0 0 40%.
What is the best way to add content div(gray boxes inside on blue and red) that will stay with rest of main wrapper(entire gray box sets to max-width: 1400px)?
Thank you.
Here's the general idea.
Positioned pseudo-elements, one for each section of the row. With a suitable width (note that the body should have overflow-x:hidden) and appropriate positioning values.
* {
box-sizing: border-box;
}
body {
overflow-x: hidden;
}
.wrapper {
min-height: 100vh; /* for demo purposes */
width: 60%;
margin: auto;
background: grey;
display: flex;
flex-direction: column;
}
header {
height: 20vh;
background: green;
}
.inner {
height: 30vh;
display: flex;
}
main {
background: blue;
flex: 1;
border: 2px solid black;
}
aside {
background: red;
flex: 0 0 40%;
border: 2px solid black;
}
.other {
background: pink;
flex: 1;
}
/* magic section */
.extend {
position: relative;
}
.extend::after {
content: '';
position: absolute;
width: 100vw;
top: 0;
height: 100%;
background: inherit;
z-index: -1;
}
.left::after {
right: 0;
}
.right::after {
left: 0;
}
<div class="wrapper">
<header></header>
<div class="inner">
<main class="extend left"></main>
<aside class="extend right"></aside>
</div>
<div class="other"></div>
</div>

Align elements in div

I have 3 divs in a container.
I want the left one (green) to be anchored (with some offset) to the left-bottom corner, the middle element (red) docked to the left element and centered vertically, and the right one (blue) to be docked to the right but centered vertically.
Here's a fiddle I'm working on.
I tried using right and margin-right etc. but it didn't work, here are some of my attempts.
This is the initial setup:
<div class="container">
<div class="left">
</div>
<div class="middle">
</div>
<div class="right">
</div>
</div>
.container {
background: gray;
height: 300px;
width: 100%;
}
.container > div {
height: 100px;
width: 100px;
}
div.left {
background: green;
height: 250px;
}
div.middle {
background: red;
}
div.right {
background: blue;
}
Result:
I've changed the fiddle based on your comments. Is this what you desire? Fiddle
*I've updated the fiddle
.container {
position: relative;
background: gray;
height: 300px;
width: 100%;
}
.container > div {
height: 100px;
width: 100px;
}
.left {
position: absolute;
left: 0;
bottom: 0;
height: 250px !important;
background: green;
}
.middle {
position: absolute;
left: 100px;
bottom: calc(50% - 50px);
background: red;
}
.right {
position: absolute;
right: 0;
bottom: calc(50% - 50px);
background: blue;
}
Fiddle
If you still want to retain the float layout (i.e. left and middle will not overlap each other), the solution is to wrap the inner content of each div with another <div> element, and position them absolutely with respect to their floated parents: http://jsfiddle.net/teddyrised/drrz6/2/
<div class="container">
<div class="left"><div></div>
</div>
<div class="middle"><div></div>
</div>
<div class="right"><div></div>
</div>
</div>
For your CSS:
.container {
background: gray;
height: 300px;
width: 100%;
}
.container > div {
height: 300px;
width: 100px;
position: relative;
}
.container > div > div {
width: 100px;
height: 100px;
position: absolute;
}
.left {
float: left;
}
.left > div {
background: green;
bottom: 0;
}
.middle {
float: left;
}
.middle > div {
background: red;
top: 50%;
margin-top: -50px; /* Half of height */
}
.right {
float: right;
}
.right > div {
background: blue;
bottom: 0;
}
Simply use flex boxes:
Demo http://jsfiddle.net/fr9U5/
HTML:
<div class="box">
<div class="left">left</div>
<div class="middle">middle</div>
<div class="right">right</div>
</div>
CSS:
.box {
width: 270px;
height:210px;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-box-direction: reverse;
-moz-box-direction: reverse;
-webkit-box-orient: vertical;
-moz-box-orient: vertical;
-webkit-flex-direction: column-reverse;
-ms-flex-direction: column-reverse;
flex-direction: column-reverse;
-webkit-flex-wrap: nowrap;
-ms-flex-wrap: nowrap;
flex-wrap: nowrap;
-webkit-box-pack: justify;
-moz-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between;
-webkit-align-content: flex-start;
-ms-flex-line-pack: start;
align-content: flex-start;
-webkit-box-align: center;
-moz-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
background-color: gray;
}
.left {
-webkit-box-ordinal-group: 1;
-moz-box-ordinal-group: 1;
-webkit-order: 0;
-ms-flex-order: 0;
order: 0;
-webkit-box-flex: 0;
-moz-box-flex: 0;
-webkit-flex: 0 1 auto;
-ms-flex: 0 1 auto;
flex: 0 1 auto;
-webkit-align-self: flex-start;
-ms-flex-item-align: start;
align-self: flex-start;
background-color: green;
}
.middle {
-webkit-box-ordinal-group: 1;
-moz-box-ordinal-group: 1;
-webkit-order: 0;
-ms-flex-order: 0;
order: 0;
-webkit-box-flex: 0;
-moz-box-flex: 0;
-webkit-flex: 0 1 auto;
-ms-flex: 0 1 auto;
flex: 0 1 auto;
-webkit-align-self: center;
-ms-flex-item-align: center;
align-self: center;
background-color: red;
}
.right {
-webkit-box-ordinal-group: 1;
-moz-box-ordinal-group: 1;
-webkit-order: 0;
-ms-flex-order: 0;
order: 0;
-webkit-box-flex: 0;
-moz-box-flex: 0;
-webkit-flex: 0 1 auto;
-ms-flex: 0 1 auto;
flex: 0 1 auto;
-webkit-align-self: flex-end;
-ms-flex-item-align: end;
align-self: flex-end;
background-color: blue;
}
/*
Legacy Firefox implementation treats all flex containers
as inline-block elements.
*/
#-moz-document url-prefix() {
.flex-container {
width: 100%;
-moz-box-sizing: border-box;
}
}
.box > div {
border:1px solid #000;
width: 33%;
height:33%;
}
OK. I guess the position:absolute is what works best for me, although I'd prefer the middle (red) element to depend on the left (green) one.
Here is the solution, and thanks Terry for the tip on deducting half-size of self to center vertically.
.container {
background: gray;
height: 300px;
width: 100%;
position: relative;
}
.container > div {
height: 100px;
width: 100px;
position: absolute;
}
div.left {
background: green;
left: 0;
bottom: 0;
height: 250px;
}
div.middle {
background: red;
left: 100px;
bottom: 0;
top: 50%;
margin-top: -50px; //deduct lalfsize of self
}
div.right {
background: blue;
right: 0;
top: 50%;
margin-top: -50px; //deduct lalfsize of self
}

Resources