Is it possible to build this header layout using Flexbox CSS? - html

I've been trying to figure out how to make this layout possible in CSS Flexbox, so far cannot figure out a way to make it work that doesn't involve hiding a duplicate to show only on desktop. Is this possible to do using Flexbox?
Image example of what I'm trying to achieve:

A solution in grid would be a lot nicer and this is a working example the breakpoint for mobile version happens in 800px,
I suggest you read the Grid Area Template system it make these kind of layouts in very modern and nice way
.parent{
width: 100%;
height:100vh;
display: grid;
grid-template-columns: 200px 1fr;
grid-template-rows: 1fr 1fr 1fr;
grid-template-areas: "blue red""blue red""green green";
gap: 10px;
}
.blue{
grid-area: blue;
width: 200px;
background: blue;
}
.red{
grid-area: red;
width: 100%;
background: red;
}
.green{
grid-area: green;
width: 100%;
height: 100%;
background: green;
}
#media screen and (max-width: 800px){
.parent{
grid-template-areas: "blue red"
"blue green";
grid-template-rows: 1fr 1fr;
}
}
<div class="parent">
<div class="red"></div>
<div class="green"></div>
<div class="blue"></div>
</div>

Related

CSS Grid auto-height columns to content

I'm trying to create a layout like this:
I want the grid height to be according to the content. The pagination area height to be according to its box-sizing and the image area to take up the rest of the available space. I'm relatively new to grid. Help would be highly appreciated.
This is what I'm getting:
.grid {
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-template-rows: repeat(2, min-content);
}
The problem is pagination and image sections takes half of the grid area. I do not want any section to have a fixed height in pixels.
Based on the response to a previous awnser here i have tried to make the changes that are being looked for.
From what i can gather you are describing 3 total elements Image, Pagination, Content
of these 3 total elements you would like
Content to occupy 100% of the width of the right side
Pagination to live on the left side and occupy a small amount that is just enough to fit the pagination
Image to live on the left side an occupy the remaining space
To do this we can still use grid we just need to specify different values for our template which I have done below. The key here is min-content
html body{
margin: 0px;
padding: 0px;
}
.your_main_class {
width: 100vw;
height: 100vh;
display: grid;
grid-template-columns: 50vw 50vw;
grid-template-rows: 1fr min-content;
grid-template-areas: "image cont"
"pagination cont";
}
div{
height: 100%;
width: 100%;
}
.image{
grid-area: image;
background: red;
}
.pagination{
grid-area: pagination;
background: blue;
}
.content{
grid-area: cont;
background: black;
}
<div class="your_main_class">
<div class="image"> Image </div>
<div class="pagination"> Pagination </div>
<div class="content"> content </div>
</div>
You can do that by specifying the area of the divs. Check the snippet bellow.
.your_main_class {
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-template-rows: repeat(3, 1fr);
}
.image{
grid-area: 1 / 1 / 3 / 6;
background: red;
}
.pagination{
grid-area: 3 / 1 / 4 / 6;
background: blue;
}
.content{
grid-area: 1 / 6 / 4 / 13;
background: black;
}
<div class="your_main_class">
<div class="image"> </div>
<div class="pagination"> </div>
<div class="content"> </div>
</div>

Unequal rows in CSS grid

I am trying to create a CSS grid with unequal rows and I cannot make .feature-block-header take ONLY as much space as it actually needs. I don't want it to be equal height with .feature-block-text. Is there a way of having a flex-grow sort of way on .feature-block-text so that it takes whatever space header did not use?
I think I have tried almost every grid row property...
.feature-block {
display: grid;
grid-template-columns: 320px auto;
grid-column-gap: 10px;
grid-template-areas:
"feature-block-image feature-block-header"
"feature-block-image feature-block-text";
}
.feature-block-header {
grid-area: feature-block-header;
background: yellow;
margin-top: 0;
}
.feature-block-image {
grid-area: feature-block-image;
width: 320px;
height: 320px;
background: lightblue;
}
.feature-block-text {
grid-area: feature-block-text;
background: lightgreen;
}
<div class="feature-block">
<h2 class="feature-block-header">Header</h2>
<div class="feature-block-image"></div>
<div class="feature-block-text">
<p>Some text within text block</p>
</div>
</div>
By adjusting the grid-template-rowsproperty, you can adjust the row heights. I just added this property to your code to demonstrate the result.
EDIT: I changed 50px to auto to make it flexible to adjust row content height.
grid-template-rows: auto 1fr;
.feature-block {
display: grid;
grid-template-columns: 320px auto;
grid-column-gap: 10px;
grid-template-areas:
"feature-block-image feature-block-header"
"feature-block-image feature-block-text";
grid-template-rows: auto 1fr;
}
.feature-block-header {
grid-area: feature-block-header;
background: yellow;
margin-top: 0;
}
.feature-block-image {
grid-area: feature-block-image;
width: 320px;
height: 320px;
background: lightblue;
}
.feature-block-text {
grid-area: feature-block-text;
background: lightgreen;
}
<div class="feature-block">
<h2 class="feature-block-header">Header</h2>
<div class="feature-block-image"></div>
<div class="feature-block-text">
<p>Some text within text block</p>
</div>
</div>
You can set align-self: start; to .feature-block-header.
https://developer.mozilla.org/en-US/docs/Web/CSS/align-self

why is this CSS grid displaying in wrong dimensions in pixels?

I am just starting out with CSS Grid and it's displaying proper boxes in proper places, but in wrong pixel size???? The main container is displaying at about 1500px instead of 1200px and all the row dimensions are wrong too.
#container {
width: 1200px;
display: grid;
grid-gap: 10px;
grid-template-columns: 2fr 1fr 1fr;
grid-template-rows: 225px 175px 225px 160px;
}
.feature {
grid-row: 1 / 5;
}
.vertical {
grid-row-end: span 2;
}
.im_picture {
background-color: #336;
}
.im_picture img {}
.button {
background-color: #808000;
grid-column: 2 / 4;
}
<div id="container">
<div class="im_picture feature"></div>
<div class="im_picture vertical"></div>
<div class="im_picture"></div>
<div class="im_picture vertical"></div>
<div class="im_picture"></div>
<div class="button">book a session</div>
Nothing wrong with the code, it's an issue with a combination of Chrome and Windows settings
https://superuser.com/questions/1139259/how-to-adjust-ui-scaling-for-chrome

How to make CSS Grid items take up remaining space?

I have a card built with CSS Grid layout. There might be an image to the left, some text to the right top and maybe a button or a link at the right bottom.
In the code below, how can I make the green area take up as much space as possible and at the same time make the blue area take up as little space as possible?
The green should push the blue area down as far as possible.
https://jsfiddle.net/9nxpvs5m/
.grid {
display: grid;
grid-template-columns: 1fr 3fr;
grid-template-areas:
"one two"
"one three"
}
.one {
background: red;
grid-area: one;
padding: 50px 0;
}
.two {
background: green;
grid-area: two;
}
.three {
background: blue;
grid-area: three;
}
<div class="grid">
<div class="one">
One
</div>
<div class="two">
Two
</div>
<div class="three">
Three
</div>
</div>
Adding grid-template-rows: 1fr min-content; to your .grid will get you exactly what you're after :).
.grid {
display: grid;
grid-template-columns: 1fr 3fr;
grid-template-rows: 1fr min-content;
grid-template-areas:
"one two"
"one three"
}
.one {
background: red;
grid-area: one;
padding: 50px 0;
}
.two {
background: green;
grid-area: two;
}
.three {
background: blue;
grid-area: three;
}
<div class="grid">
<div class="one">
One
</div>
<div class="two">
Two
</div>
<div class="three">
Three
</div>
</div>
Jens edits: For better browser support this can be used instead: grid-template-rows: 1fr auto;, at least in this exact case.
A grid is a series of intersecting rows and columns.
You want the two items in the second column to automatically adjust their row height based on their content height.
That's not how a grid works. Such changes to the row height in the second column would also affect the first column.
If you must use CSS Grid, then what I would do is give the container, let's say, 12 rows, then have items span rows as necessary.
.grid {
display: grid;
grid-template-columns: 1fr 3fr;
grid-template-rows: repeat(12, 15px);
}
.one {
grid-row: 1 / -1;
background: red;
}
.two {
grid-row: span 10;
background: lightgreen;
}
.three {
grid-row: span 2;
background: aqua;
}
.grid > div {
display: flex;
align-items: center;
justify-content: center;
}
<div class="grid">
<div class="one">One</div>
<div class="two">Two</div>
<div class="three">Three</div>
</div>
Otherwise, you can try a flexbox solution.
.grid {
display: flex;
flex-flow: column wrap;
height: 200px;
}
.one {
flex: 0 0 100%;
width: 30%;
background: red;
}
.two {
flex: 1 0 1px;
width: 70%;
background: lightgreen;
}
.three {
background: aqua;
}
.grid>div {
display: flex;
align-items: center;
justify-content: center;
}
<div class="grid">
<div class="one">One</div>
<div class="two">Two</div>
<div class="three">Three</div>
</div>
When using grid, and you have grid template area used, and by chance you gave a particular area a width, you are left with a space grid does automatically.
In this situation, let grid-template-columns be either min-content or max-content, so that it adjusts its position automatically.
A possible approach might be grouping two and three together, and using flexbox:
.grid {
display: grid;
grid-template-columns: 1fr 3fr;
grid-template-areas: "one two"
}
.one {
background: red;
grid-area: one;
padding: 50px 0;
}
.wrap {
grid-area: two;
display: flex;
flex-direction: column;
}
.two {
background: green;
flex: 1;
}
.three {
background: blue;
}
<div class="grid">
<div class="one">
One
</div>
<div class="wrap">
<div class="two">
Two
</div>
<div class="three">
Three
</div>
</div>
</div>
Definitely not the most elegant solution and probably not best practice, but you could always add more lines of
"one two"
before the part where you have
"one three"
so it ends up looking like
.grid {
display: grid;
grid-template-columns: 1fr 3fr;
grid-template-areas:
"one two"
"one two"
"one two"
"one three"
}
Again, pretty sure this is just a work around and there's better solutions out there... But this does work, to be fair.
Just use width: 100% and height: 100% in the CSS class of the item you want to fill the grid. Join a max-width property and a max-height property if you don't want a grid item inside a grid container to grow more than some size.

Why does grid-gap not work on mobile?

I've been playing around with CSS Grid recently and have noticed something that I can't see to find the answer to. Let's say I split my page out to have 2 columns, and then a row below it, with another column (which spans both columns). On mobile, I'd like them to stack one on top of the other and then go back to layout described above after a certain breakpoint. Here is the markup:
HTML
<div class="grid">
<div class="upper">
<div class="a">A</div>
<div class="b">B</div>
</div>
<div class="lower">
<div class="c">C</div>
</div>
</div>
SCSS
.upper, .lower {
display: grid;
}
.upper {
grid-template-columns: 1fr 1fr;
grid-template-rows: auto auto;
background-color:grey;
grid-gap:10px;
#media only screen and (max-width:800px) {
grid-template-columns: 1fr;
grid-template-rows: auto;
}
}
.lower {
grid-template-columns: 1fr;
grid-template-rows:auto;
background-color: green;
grid-gap:10px;
}
I've noticed that on mobile, even though I've defined grid-gap for both of my grid sections, on mobile when the columns stack, the grid-gap is not maintained. So in the fiddle below, when you make the window smaller, you can see that when the columns, stack one on top of the other, the gap between B and C is non existent. Here is the fiddle:
Fiddle
Hope I'm making sense!
EDIT: Bear in mind I'm only testing this in Firefox and Chrome (which support grid).
The grid-gap rule doesn't work between B and C because it doesn't apply.
This rule creates gutters between rows and columns inside a grid container.
But you are declaring grid-gap on .upper and .lower, two siblings in a block container. Their parent (.grid) is not a grid container because it doesn't have display: grid or inline-grid.
Therefore, grid-gap: 10px on .upper is creating a 10px gutter between A and B...
and grid-gap: 10px on .lower is creating a 10px gutter between.... nothing (.lower has only one grid item. grid-gap creates gutters between multiple grid items).
fiddle demo 1
For grid-gap to work among the .upper and .lower siblings you need to apply it to their parent, which must be a grid container.
fiddle demo 2
.grid {
display: grid; /* NEW */
grid-gap: 25px; /* NEW */
}
.upper, .lower {
display: grid;
}
.upper {
grid-template-columns: 1fr 1fr;
grid-gap: 25px;
}
.lower {
grid-template-columns: 1fr;
grid-template-rows: auto;
grid-gap: 10px; /* does nothing unless there are multiple grid items */
}
#media ( max-width:800px ) {
.upper {
grid-template-columns: 1fr;
grid-template-rows: auto;
}
}
.upper > * { border: 1px dashed red; }
.lower > * { border: 1px dashed blue; }
<div class="grid">
<div class="upper">
<div class="a">A</div>
<div class="b">B</div>
</div>
<div class="lower">
<div class="c">C</div>
</div>
</div>