I'm trying to create a layout with CSS grid that looks like this (ie: a section on the left that has a fixed width and height, a section at the top which takes up the minimum height possible, and a section underneath that which takes up all the remaining space):
However, what I'm getting is this (where the space at the bottom of the orange section is equal to the grid-row-gap):
I'm wondering why the fr is being calculated like this instead of compensating for the grid gap?
(In my project I can fix this issue by adding a margin to the bottom right element instead of using grid-row-gap, but I'd like to know if there's something I'm misunderstanding about CSS grid)
span {
display: inline-block;
}
.grid {
border: 1px solid black;
display: inline-grid;
grid-template-columns: repeat(2, auto);
grid-template-rows: auto 1fr;
grid-row-gap: 1rem;
}
.left {
background: orange;
height: 120px;
width: 120px;
grid-row: 1/span 2;
}
.right-top {
background: yellow;
height: 20px;
width: 300px;
}
.right-bottom {
background: blue;
}
<div class="grid">
<span class="left"></span>
<span class="right-top"></span>
<span class="right-bottom"></span>
</div>
Related
Going to do my best to explain the constraints.
There's 3 containers .content .left and .bottom and a resize handler to control available space.
I need .container to 'grow' as the space grows to take up the available space.
.left should stay at it's min-content width and 100% height and is already (great).
.bottom should stay at it's min-content height and 100% width and isn't currently (not great).
Cannot change the structure of the HTML because it's outside my control in real world.
Messed around for awhile with different combinations of align-items: stretch and grow but can't seem to do it when the direction is a row, but can't change it to a column without changing structure of HTML.
.container {
display: flex;
flex-wrap: wrap;
height: 20rem;
width: 20rem;
overflow: hidden;
resize: both;
border: 1px solid blue;
}
.left {
border: 1px solid red;
}
.content {
border: 1px solid pink;
flex: 1;
}
.bottom {
border: 1px solid grey;
flex-basis: 100%;
}
<div class="container">
<div class="left">left min content</div>
<div class="content">should resize vertically and horizontally</div>
<div class="bottom"/>bottom should be min content</div>
</div>
in this scenario we can utilize display: grid; properties and achieve the required behavior without changing the HTML structure, by doing something like this.
.container {
display: grid;
grid-template-columns: max-content auto;
grid-template-rows: auto max-content;
height: 40rem;
width: 20rem;
overflow: hidden;
resize: both;
border: 1px solid blue;
}
.left {
border: 1px solid red;
}
.content {
border: 1px solid pink;
}
.bottom {
border: 1px solid grey;
grid-column: span 2;
}
<div class="container">
<div class="left">left min content</div>
<div class="content">should resize vertically and horizontally</div>
<div class="bottom">bottom should be min content</div>
</div>
I have simply defined 2 rows and columns, grid-template-columns: max-content auto; and grid-template-rows: auto max-content;.
then letting the 1st column take all the available height using max-content, and the 2nd column, which is the bottom one, stays auto and takes up the remaining space.
then using grid-column: span 2; on the bottom div. which expands it to the size of 2 rows which in our case is 100% of the width (as we only have 2 rows).
I hope this will resolve your issue.
I'm building a grid layout using CSS Grid and I want all my columns to have the same size (fixed sized) and that size being the one of the largest column.
I know that I can do it using JS or even display: table but I would like to do it using CSS Grid (if it's possible).
Here's what I have:
* {
box-sizing: border-box;
}
div {
display: grid;
grid-template-columns: repeat(auto-fit, 120px);
gap: 5px;
}
span {
padding: 10px;
border: 1px solid black;
}
<div>
<span>Orange</span>
<span>Purple</span>
<span>Aquamarine</span>
<span>Black</span>
<span>Brown</span>
<span>Red</span>
</div>
I fixed the width at 120px but I want that width to be the one of Aquamarine which is the largest one.
If you have a fixed number of columns, you can do it by placing your grid element inside a wrapper element styled with display: inline-block; and then setting grid-template-columns: repeat(6, 1fr);. See this answer.
However, I don't know how to do this in a grid where you have a variable number of columns by using auto-fit or auto-fill.
* {
box-sizing: border-box;
}
.wrapper {
display: inline-block;
}
.grid {
display: grid;
grid-template-columns: repeat(6, 1fr);
gap: 5px;
}
span {
padding: 10px;
border: 1px solid black;
}
<div class="wrapper">
<div class="grid">
<span>Orange</span>
<span>Purple</span>
<span>Aquamarine</span>
<span>Black</span>
<span>Brown</span>
<span>Red</span>
</div>
</div>
I am using CSS grid for a website, and in the information section I have 2 columns:
on the left a paragraph with information, on the right the image.
However, when I want to add an h1 to the paragraph it creates an extra column, resulting in:
On the left the header, on the right the image and underneath the header is now the paragraph.
I've now avoided the problem by using and making a class for the first sentence of the paragraph (making that sentence look like a h1) but it feels like a makeshift solution. Is there a better way to solve this problem?
I've tried 2fr 2fr, still the same problem
I've added a screenshot of what it looks like
(I'm still very new to CSS grid)
.block1{
display:grid;
grid-template-columns: 1fr 2fr;
column-gap: 250px;
background-color: #EFEDE3;
padding: 150px;
}
.block1 img{
justify-self: end;
border-radius: 5px;
width: 75%;
}
.block1 span {
font-weight: bolder;
font-size: 32px;
}
You can try this one.
HTML:
<div class="grid">
<div class="paragraph">
<h1>Paragraph</h1>
</div>
<div class="imageBox">
</div>
</div>
and CSS:
.grid {
display: grid;
grid-template-columns: 1fr 2fr;
column-gap: 250px;
}
.paragraph {
border: 1px solid green;
height: 40vh;
}
.imageBox {
border: 1px solid red;
height: 40vh;
}
I'm trying to achieve this layout (https://codepen.io/totkeks/pen/PowodPq) with a top section, main section and side section.
<div class="grid">
<div class="top">Top</div>
<div class="main">Main</div>
<div class="side">Side</div>
</div>
body {
padding: 0;
margin: 0;
}
.grid {
display: grid;
grid-gap: 3rem;
grid-template-columns: 22rem minmax(48rem, auto);
grid-auto-rows: auto;
padding: 3rem;
min-height: 100vh;
box-sizing: border-box;
border: 2px dotted black;
}
.top, .main, .side {
background-color: papayawhip;
}
.main {
grid-row: span 2;
}
#media screen and (max-width: 1200px) {
.grid {
grid-template-columns: 1fr;
}
}
When the page is smaller (< 1280px currently in CSS query) the three sections are stacked on top of each other, first top, then main, then side, all covering the full width.
When the page is wider, the top and side sections are fixed size on the left side and the main section is on the right side, growing as space becomes available.
Just a moment ago I found this Q&A Responsive layout without media query and while it goes in the right direction, it is not entirely what I'm trying to achieve.
I already spent two evenings with this idea and would like to find a solution or get a definitive "No, that's not possible with current CSS".
You could give a try with auto-fit, grid-colum, grid-row and use width + calc() to trick the wrapping . But you could find funny behaviors from a browser to anoter . (auto-flow is required ) However, mediaquerie is made for this, much cleaner and reliable.
body {
padding: 0;
margin: 0;
}
.grid {
display: grid;
grid-gap: 3rem;
margin: 1em;
border: solid;
grid-template-columns: repeat(auto-fit, minmax(22rem,auto));
grid-auto-rows: auto;
padding: 3rem;
min-height: calc(100vh - 2em);
box-sizing: border-box;
}
.top,
.main,
.side {
background-color: orange;
border:solid;
}
.top,
.side {
grid-column: 1;
width: 22rem;
min-width:100%;
}
.main {
grid-column: auto;
min-width: calc(100vw - 33rem);
grid-row: span 2;
}
<div class="grid">
<div class="top">Top</div>
<div class="main">Main</div>
<div class="side">Side</div>
</div>
My answer maybe yes for the fun only.
I'm experimenting with CSS Grids, and this is the layout I'm building:
.grid {
display: grid;
align-items: center;
grid-template-columns: 1fr 4rem 1fr;
grid-template-rows: 1rem 1fr 1rem;
max-width: 900px;
margin: 0 auto;
}
.text {
/*
// Ideally, this should be
grid-area: text
*/
grid-column: 1 / 3;
grid-row: 2 / 3;
/* Fix z-index */
position: relative;
padding: 4rem;
background-color: #fff;
}
.image {
/*
// Ideally, this should be
grid-area: image;
*/
grid-column: 2 / 4;
grid-row: 1 / -1;
background-color: lightgray;
padding: 1rem;
/* Center das image */
display: flex;
justify-content: center;
}
/* Basic body */
body {
background-color: #fafafa;
font-family: sans-serif;
padding: 2rem;
}
img {
max-width: 100%;
height: auto;
}
<div class="grid">
<div class="text">One morning, when bobby woke from troubled dreams, he found himself transformed in his bed into a horrible vermin. He lay on his leg like back, and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into
stiff sections.
</div>
<div class="image">
<img src="http://unsplash.it/400/400" />
</div>
</div>
(best to preview in full page...)
What I'd like to avoid:
.text and .image both currently are using grid-column: * / *; syntax, instead I'd like to use grid-area: text and grid-area: image;.
Is it possible to define grid-template-{columns|rows} as overlapping areas? I tried using second way of defining grid areas
, but that didn't seem to work.
Looks like you can't do [a-start] [b-start] [a-end] [b-end] in that syntax, or at least I didn't manage to.
So - Is there any way to create an overlapping grid using named areas?
I'm trying to use the named areas for convenience purely - so that it's easier to reason about the responsive layout code, instead of repeating myself multiple times in media queries.
Edit
Found the answer because of #vals answer below.
This seemed to work just fine, I probably made a syntax error in my previous attempt somewhere:
grid-template-columns: [text-start] 1fr [image-start] 4rem [text-end] 1fr [image-end];
grid-template-rows: [image-start] 1rem [text-start] 1fr [text-end] 1rem [image-end];
At least in a more basic layout, it seems to work for me:
.container {
border: solid 1px green;
height: 180px;
width: 300px;
display: grid;
grid-template-columns: [left-start] 100px [right-start] 100px [left-end] 100px [right-end];
grid-template-rows: [left-start] 60px [right-start] 60px [left-end] 60px [right-end];
}
.left {
grid-area: left;
background-color: red;
}
.right {
grid-area: right;
background-color: lightgray;
opacity: 0.5;
}
<div class="container">
<div class="left">
</div>
<div class="right">
</div>
</div>