I'm in the midst of learning CSS Grid (long overdue, I know). I've challenged myself to convert a relatively standard float-based layout to a grid, but can't figure out this last part.
My goal is to have a layout where the content (logo + nav, and sidebar + content) is centered, with a max-width
. For example, the logo + nav should have a max-width
of 600px. I also have a requirement of having a solid fill background covering the full-width of the viewport (matching the height of the variable height logo/nav row).
The first column (logo and sidebar) should shrink to fit their content - so the first column is only as wide as the wider between logo/sidebar. The nav/content should then fill the remaining space allowed by the max-width
.
The following is my best attempt. The width of the main content does not fill a max-width
. Instead, the width of the main content is the width of the Logo + 250px (the width defined by the grid columns).
What I'm hoping to achieve is - define the max-width
of Logo + Nav to a specific width (say 600px), and have the Logo column shrink to fit its content.
body {
margin: 40px;
}
.fill {
grid-column-start: 1;
grid-column-end: 6;
grid-row-start: 1;
grid-row-end: 1;
background-color: gray;
}
.logo {
grid-area: logo;
font-size: calc(1rem + 4vw);
}
.sidebar {
grid-area: sidebar;
}
.content {
grid-area: content;
}
.nav {
grid-area: nav;
text-align: right;
}
.footer {
grid-area: footer;
}
.wrapper {
display: grid;
grid-gap: 10px;
grid-template-columns: auto min-content 120px 120px auto;
grid-template-areas: "... logo nav nav ..." "... sidebar content content ..." "... footer footer footer ...";
background-color: #fff;
color: #444;
}
.box {
background-color: #444;
color: #fff;
border-radius: 5px;
padding: 10px;
}
.header,
.footer {
background-color: #999;
}
<div class="wrapper">
<div class="fill"></div>
<div class="box logo">Logo</div>
<div class="box nav">Nav</div>
<div class="box sidebar">Sidebar</div>
<div class="box content">Content
<br /> More content than we had before so this column is now quite tall.</div>
<div class="box footer">Footer</div>
</div>
Is this possible with CSS Grid, and if so, how?
You can have a 2-column grid with grid-template-columns: auto 1fr
so that the first column takes the width of its content (as wide as the wider between logo/sidebar) and the second column takes up the remaining space (Note that I have set max-width: 600px
to the grid container).
I also have a requirement of having a solid fill background covering the full-width of the viewport (matching the height of the variable height logo/nav row)
For this you can do the following:
First fix logo
and nav
in the first row by setting the grid-row
and grid-column
properties
Now use a pseudo element for wrapper
overlapping the first row (but stacked below using z-index
property).
Set margin-left
property as calc(-50vw + 50%)
and width
as 100vw to stretch the solid fill background across the viewport.
See demo below:
body {
margin: 40px;
}
.wrapper {
display: grid;
grid-gap: 10px;
grid-template-columns: auto 1fr; /* 2-column grid */
/* background-color: #fff;*/
color: #444;
max-width: 600px; /* max-width of the layout */
margin: 0 auto; /* center in the viewport */
}
.logo {
font-size: calc(1rem + 4vw);
grid-row: 1; /* fix the logo in the first row */
grid-column: 1; /* fix the logo in the first column */
}
.nav {
text-align: right;
grid-row: 1; /* fix the nav in the first row */
grid-column: 2; /* fix the nav in the second column */
}
.footer {
grid-column: span 2; /* footer spans the two columns */
}
.box {
background-color: #444;
color: #fff;
border-radius: 5px;
padding: 10px;
}
.header,
.footer {
background-color: #999;
}
.wrapper:after { /* position this in the first row */
content: '';
display: block;
grid-row: 1;
grid-column: 1/ 3;
width: 100vw;
margin-left: calc(-50vw + 50%);
background: gray;
z-index: -1; /* push it behind the first row */
}
<div class="wrapper">
<div class="box logo">Logo</div>
<div class="box nav">Nav</div>
<div class="box sidebar">Sidebar</div>
<div class="box content">Content
<br /> More content than we had before so this column is now quite tall.</div>
<div class="box footer">Footer</div>
</div>