I have started using Grid CSS and i am stuck in building a Layout using Grid system.
I am looking to build a layout where the column would overlap a row and take full height. I have attached a screenshot of the layout and what i have tried so far.
body {
margin: 40px;
}
.sidebar {
grid-area: sidebar;
}
.content {
grid-area: content;
}
.header {
grid-area: header;
}
.wrapper {
display: grid;
grid-gap: 10px;
grid-template-columns: 120px 120px 120px;
grid-template-areas:
"header header header"
"sidebar content content";
background-color: #fff;
color: #444;
}
.box {
background-color: #444;
color: #fff;
border-radius: 5px;
padding: 20px;
font-size: 150%;
}
.header {
background-color: #999;
}
.overlay {
background-color: red;
z-index: 10;
grid-column: content-start / content-end;
grid-row: header-start / content-end;
}
<div class="wrapper">
<div class="box header">Header</div>
<div class="box sidebar">Sidebar</div>
<div class="overlay">Content</div>
</div>
Depending on how you want to overlap the following code works, but need to be adapted:
There's a lot of other way to do this...
body {
margin: 40px;
}
.sidebar {
grid-area: sidebar;
}
.content {
grid-area: content;
}
.header {
grid-area: header;
}
.wrapper {
display: grid;
grid-gap: 10px;
grid-template-columns: 120px 120px 120px;
grid-template-rows: 30px 30px auto auto;
grid-template-areas:
"header header header"
"sidebar content content";
background-color: #fff;
color: #444;
}
.box {
background-color: #444;
color: #fff;
border-radius: 5px;
padding: 20px;
font-size: 150%;
}
.header {
background-color: #999;
grid-row: 1 / 3;
}
.sidebar {
background-color: red;
z-index: 10;
grid-row: 2 / 4;
height: 300px;
}
.overlay {
background-color: red;
z-index: 10;
grid-column: content-start / content-end;
grid-row: 3 / 4;
}
<div class="wrapper">
<div class="box header">Header</div>
<div class="box sidebar">Sidebar</div>
<div class="overlay">Content</div>
</div>
Related
I have a css grid:
|-------|-------------------|
|-------| |
| | overflow |
|-------|-------------------|
|-------|-------------------|
And I cannot stop the "overflow" from growing, basically it always expands, despite having set:
overflow: auto;
in the css. How can achieve this?
The snippet below.
html {
font-size: 22px;
}
body {
padding: 1rem;
/* grid-template-columns: 1fr 3fr; */
}
.wrapper {
max-height: 70vh;
padding: 1rem;
}
.header {
background-color: red;
color: white;
padding: 1rem;
height: 2rem;
resize: horizontal;
grid-area: 1 / 1 / 2 / 2;
}
.nav {
background-color: lightgrey;
color: baclk;
padding: 1rem;
height: 4rem;
overflow: auto;
min-width: 12rem;
resize: horizontal;
grid-area: 2 / 1 / 3 / 2;
}
.scroll {
background-color: dodgerblue;
color: white;
padding: 1rem;
overflow: auto;
grid-area: 1 / 2 / 3 / 3;
}
.prev {
background-color: black;
color: white;
padding: 1rem;
height: 4rem;
grid: 3 / 1 / 4 / 2;
}
.select {
background-color: lightgrey;
color: white;
padding: 1rem;
height: 4rem;
grid-area: 4 2 4 4;
}
.cards {
max-width: 1200px;
margin: 0 auto;
display: grid;
grid-gap: 0.5rem;
}
/* Screen larger than 600px? 2 column */
#media (min-width: 600px) {
.cards {
grid-template-columns: 1fr 3fr;
}
}
<div class="wrapper">
<div class="cards">
<div class="header">HEADER</div>
<div class="scroll">
<p>111</p>
<p>222</p>
<p>333</p>
<p>444</p>
<p>555</p>
<!-- <p>666</p>
<p>777</p>
<p>888</p>
<p>999</p> -->
</div>
<div class="nav">NAV</div>
<div class="prev">PREVIEW</div>
<div class="select">SELECT</div>
</div>
</div>
It turned out the solution is to add one line to the grid definition:
grid-template-rows: auto 1fr auto;
This produces a nice layout, when the "scroll" area overflows, while the grid scales as expected. Updated snippet below.
html {
font-size: 22px;
}
body {
padding: 1rem;
overflow: hidden;
/* grid-template-columns: 1fr 3fr; */
}
.header {
background-color: red;
color: white;
padding: 1rem;
height: 2rem;
grid-area: 1 / 1 / 2 / 2;
}
.nav {
background-color: lightgrey;
color: baclk;
padding: 1rem;
height: auto;
overflow: auto;
min-width: 12rem;
resize: horizontal;
grid-area: 2 / 1 / 3 / 2;
}
.scroll {
background-color: dodgerblue;
color: white;
padding: 1rem;
overflow: auto;
max-height: 70vh;
grid-area: 1 / 2 / 3 / 3;
}
.prev {
background-color: black;
color: white;
padding: 1rem;
max-height: 30vh;
grid: 3 / 1 / 4 / 2;
}
.select {
background-color: lightgrey;
color: white;
padding: 1rem;
height: 4rem;
grid-area: 4 2 4 4;
}
.cards {
max-width: 80vw;
height: 90vh;
margin: 0 auto;
display: grid;
grid-gap: 0.5rem;
}
/* Screen larger than 600px? 2 column */
#media (min-width: 600px) {
.cards {
grid-template-columns: 1fr 3fr;
grid-template-rows: auto 1fr auto;
}
}
<div class="wrapper">
<div class="cards">
<div class="header">HEADER</div>
<div class="scroll">
<p>111</p>
<p>222</p>
<p>333</p>
<p>444</p>
<p>555</p>
<p>666</p>
<p>777</p>
<!-- <p>888</p>
<p>999</p> -->
</div>
<div class="nav">NAV</div>
<div class="prev">PREVIEW</div>
<div class="select">SELECT</div>
</div>
</div>
I have the following layout with 2 headers and 3 footers:
.my-grid {
display: grid;
grid-template-areas:
"header1"
"header2"
"mainAreaExpandMePlease"
"footer1"
"footer2"
"footer3"
;
grid-template-rows: 27px 27px 1fr 28px 28px 28px;
height: 100%;
}
The main area will expand to fill the gap left after showing the headers and footers.
I want to be able to toggle footers on and off (show / hide them) such that they collapse. With the code above, a gap will be left in place of the footer when we hide it.
How should I go about:
Having a main area that always expands
Having optional headers and footers which collapse, when hidden
Examples:
If header1 collapses, then header2 should take its place and mainAreaExpandMePlease should expand to where header2 used to be
If header2 collapses, then mainAreaExpandMePlease should expand up by another 27px
If footer3 collapses, then footer2 takes place of footer3, footer1 takes the place of footer2 and mainAreaExpandMePlease will stretch down another 28px
Thank you!
Fiddle: https://jsfiddle.net/jg6ho4wu/1/
html, body {
height: 100%;
margin: 0;
padding: 0;
}
.my-grid {
display: grid;
grid-template-areas:
"header1"
"header2"
"mainAreaExpandMePlease"
"footer1"
"footer2"
"footer3";
grid-template-rows: 27px 27px 1fr 28px 28px 28px;
height: 100%;
}
.header1 {
grid-area: header1;
background-color: yellow;
}
.header2 {
grid-area: header2;
background-color: magenta;
}
.mainAreaExpandMePlease {
grid-area: mainAreaExpandMePlease;
background-color: cyan;
}
.footer1 {
grid-area: footer1;
background-color: green;
}
.footer2 {
grid-area: footer2;
background-color: red;
}
.footer3 {
grid-area: footer3;
background-color: blue;
}
<div class="my-grid">
<div class="header1"></div>
<div class="header2"></div>
<div class="mainAreaExpandMePlease"></div>
<div class="footer1"></div>
<div class="footer2" style="display:none"></div>
<div class="footer3"></div>
</div>
Don't set the height of the header and footer rows at the container level.
Set their heights on the items, and set their container heights to auto.
.my-grid {
display: grid;
height: 100vh;
grid-template-rows: auto auto 1fr auto auto auto;
grid-template-areas: "header1"
"header2"
"mainAreaExpandMePlease"
"footer1"
"footer2"
"footer3";
}
.header1 {
height: 27px;
grid-area: header1;
background-color: yellow;
}
.header2 {
height: 27px;
grid-area: header2;
background-color: magenta;
}
.mainAreaExpandMePlease {
grid-area: mainAreaExpandMePlease;
background-color: cyan;
}
.footer1 {
height: 28px;
grid-area: footer1;
background-color: green;
}
.footer2 {
height: 28px;
grid-area: footer2;
background-color: red;
}
.footer3 {
height: 28px;
grid-area: footer3;
background-color: blue;
}
body {
margin: 0;
padding: 0;
}
<div class="my-grid">
<div class="header1"></div>
<div class="header2"></div>
<div class="mainAreaExpandMePlease"></div>
<div class="footer1"></div>
<div class="footer2" style="display:none"></div>
<div class="footer3"></div>
</div>
I've got some problems when I'am trying to make my section with Grid layout. Where exactly I make mistake? Can someone explaine me, please?
HTML
<body>
<header>
<div class="grid-wrapper">
<div class="item1"><span>Item 1</span></div>
<div class="item2"><span>Item 2</span></div>
<div class="item3"><span>Item 3</span></div>
<div class="item4"><span>Item 4</span></div>
<div class="item5"><span>Item 5</span></div>
</div>
</header>
</body>
CSS
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-color: #969d9f;
}
header {
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
background-color: #969d9f;
}
.grid-wrapper {
border: 1px solid red;
width: 1200px;
display: grid;
grid-gap: 20px;
grid-template-columns: repeat(2, 1fr);
}
.item1, .item2, .item3, .item4, .item5 {
border: 1px solid grey;
background-color: #636564;
height: 360px;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 40px;
}
.item1 { width: 750px; }
.item2 { width: 360px; }
.item3 { width: 555px; }
.item4 { width: 555px; }
.item5 { width: 1200px; }
So the main question is how can I correctly display my blocks and where is my main mistake that I make?
Here is some pics:
Thank you for your attention!
its my opinion
HTML
<body>
<header>
<div class="grid-wrapper">
<div class="item1"><span>Item 1</span></div>
<div class="item2"><span>Item 2</span></div>
<div class="item3"><span>Item 3</span></div>
<div class="item4"><span>Item 4</span></div>
<div class="item5"><span>Item 5</span></div>
</div>
</header>
</body>
CSS
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-color: #969d9f;
}
header {
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
background-color: #969d9f;
}
.grid-wrapper {
border: 1px solid red;
width: 1200px;
display: grid;
grid-gap: 20px;
grid-template-areas: "item1 item1 item2" /* make grid area */
"item3 item4 item4"
"item5 item5 item5";
grid-template-columns:(1fr, 1fr, 1fr); /* set width of colums */
}
.item1, .item2, .item3, .item4, .item5 {
border: 1px solid grey;
background-color: #636564;
height: 360px;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 40px;
}
.item1 {grid-area: item1} /* connect items with grid area */
.item2 {grid-area: item2}
.item3 {grid-area: item3}
.item4 {grid-area: item4}
.item5 {grid-area: item5}
Your layout isn't a "normal" grid (your rows 1 & 2 have cells with different widths from each other), so to resolve it, a solution could be to create more columns (3/4/5 columns: it depends by cells width and if the biggests [1&4] are equals or not) and play, for example, with grid-template-areas to create items that can... "fill more than 1 cell": in background there is a grid, but with this "trick" you can transform it as your layout.
This is a useful guide for more informations about CSS grid: https://css-tricks.com/snippets/css/complete-guide-grid/
Another solution is to use flexbox also for those rows :-)
Try it:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-color: #969d9f;
}
header {
width: 100%;
/*height: 100vh;*/
display: flex;
justify-content: center;
background-color: #969d9f;
}
.grid-wrapper {
border: 1px solid red;
width: 100%;
max-width:1200px;
display: grid;
grid-gap: 20px;
grid-template-columns: repeat(4, 1fr);
grid-template-areas:
"item1 item1 item1 item2"
"item3 item4 item4 item4"
"item5 item5 item5 item5";
}
.item1, .item2, .item3, .item4, .item5 {
border: 1px solid grey;
background-color: #636564;
height: 360px;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 40px;
}
/*.item1 { width: 750px; }
.item2 { width: 360px; }
.item3 { width: 555px; }
.item4 { width: 555px; }
.item5 { width: 1200px; }*/
.item1 {
grid-area: item1;
}
.item2 {
grid-area: item2;
}
.item3 {
grid-area: item3;
}
.item4 {
grid-area: item4;
}
.item5 {
grid-area: item5;
}
<header>
<div class="grid-wrapper">
<div class="item1"><span>Item 1</span></div>
<div class="item2"><span>Item 2</span></div>
<div class="item3"><span>Item 3</span></div>
<div class="item4"><span>Item 4</span></div>
<div class="item5"><span>Item 5</span></div>
</div>
</header>
P.S. Maybe it is better don't use a fixed widths in a world of mobile device, so I changed your witdh:1200px with a max-width:1200px, but well you can change it
if you do not care about it ;-)
I would like to restructure a page on my angularJS website. Currently data is being displayed in a table view; I would like to create a left sidebar with a (tile) list of names. When a name is clicked on, the right sidebar should display additional details about the selected individual. Any guidance on how to efficiently accomplish this using HTML and CSS will be much appreciated.
Here is the simple code I have so far:
body {
margin: 40px;
}
.lft_sidebar {
grid-area: sidebar;
}
.content {
grid-area: content;
}
.header {
grid-area: header;
}
.wrapper {
display: grid;
grid-gap: 10px;
grid-template-columns: 120px 120px 120px;
grid-template-areas: "....... header header" "sidebar content content" "footer footer footer";
background-color: #fff;
color: #444;
}
.box {
background-color: #444;
color: #fff;
border-radius: 5px;
padding: 10px;
font-size: 150%;
}
.header,
.footer {
background-color: #999;
}
<div class="wrapper">
<div class="header">Header</div>
<div class="lft_sidebar">Neme 1</div>
<div class="lft_sidebar">Name 2</div>
<div class="lft_sidebar">Name 3</div>
<div class="lft_sidebar">Name 4</div>
<div class="rght_sidebar"> More details about Selected Name</div>
</div>
You can use the grid-column-start and grid-column-end CSS properties to specify where a grid cell should start / end.
body {
margin: 40px;
}
.lft_sidebar {
grid-area: sidebar;
}
.left {
grid-column-start: 1;
grid-column-end: 2;
}
.rght_sidebar {
grid-column-start: 2;
grid-column-end: 4;
}
.header {
grid-column-start: 1;
grid-column-end: 4;
}
.wrapper {
display: grid;
grid-gap: 10px;
grid-template-columns: repeat(3, 1fr);
background-color: #fff;
color: #444;
}
.box {
background-color: #444;
color: #fff;
border-radius: 5px;
padding: 10px;
font-size: 150%;
}
.header,
.footer {
background-color: #999;
}
<div class="wrapper">
<div class="header">Header</div>
<div class="left">
<div class="lft_sidebar">Neme 1</div>
<div class="lft_sidebar">Name 2</div>
<div class="lft_sidebar">Name 3</div>
<div class="lft_sidebar">Name 4</div>
</div>
<div class="rght_sidebar"> More details about Selected Name</div>
</div>
Essentially what I need to happen is to set up a grid, but if one of the elements is missing, another element stretches to fill the space.
This is an example Pen of where I'm currently at:
https://codepen.io/Rockster160/pen/JMLaXY
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
div {
box-sizing: border-box;
}
.grid {
height: 100%;
width: 100%;
background: white;
border: 2px solid red;
display: grid;
grid-template-columns: 250px auto;
grid-template-rows: 100px auto 50px;
grid-template-areas: "sidebar header"
"sidebar content"
"sidebar footer";
}
.sidebar {
grid-area: sidebar;
background: green;
}
.header {
grid-area: header;
background: lightblue;
}
.content {
grid-area: content;
background: blue;
border: 5px solid black;
}
.footer {
grid-area: footer;
background: orange;
}
<div class="grid">
<div class="sidebar"></div>
<div class="header"></div>
<div class="content"></div>
<!-- <div class="footer"></div> -->
</div>
footer is an optional element, so when it doesn't exist (commented out as in the code) then content should stretch and line up with the bottom of sidebar.
I've tried a variety of different combinations using min/max content and different auto placements, but no luck. I thought if I had multiple elements named content it might work as well, but no luck there either.
Any help is greatly appreciated!
You are forcing the 3rd row to be 50px in the grid style.
Change it to be adapted to the content, and set the 50px as height in the footer itself:
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
div {
box-sizing: border-box;
}
.grid {
height: 100%;
width: 100%;
background: white;
border: 2px solid red;
display: grid;
grid-template-columns: 250px auto;
grid-template-rows: 100px auto max-content; /* changed last 50px to max-content*/
grid-template-areas: "sidebar header"
"sidebar content"
"sidebar footer";
}
.sidebar {
grid-area: sidebar;
background: green;
}
.header {
grid-area: header;
background: lightblue;
}
.content {
grid-area: content;
background: blue;
border: 5px solid black;
}
.footer {
grid-area: footer;
background: orange;
height: 50px; /* added */
}
<div class="grid">
<div class="sidebar"></div>
<div class="header"></div>
<div class="content"></div>
<!-- <div class="footer"></div> -->
</div>
And another posibility, thanks to Michael_B. The sintax of grid-template-rows is clearer:
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
div {
box-sizing: border-box;
}
.grid {
height: 100%;
width: 100%;
background: white;
border: 2px solid red;
display: grid;
grid-template-columns: 250px auto;
grid-template-rows: 100px 1fr auto;
grid-template-areas: "sidebar header"
"sidebar content"
"sidebar footer";
}
.sidebar {
grid-area: sidebar;
background: green;
}
.header {
grid-area: header;
background: lightblue;
}
.content {
grid-area: content;
background: blue;
border: 5px solid black;
}
.footer {
grid-area: footer;
background: orange;
height: 50px; /* added */
}
<div class="grid">
<div class="sidebar"></div>
<div class="header"></div>
<div class="content"></div>
<div class="footer"></div>
</div>
The easiest way to do this is to use the :last-child selector:
.content:last-child {
grid-row: content / footer;
}
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
div {
box-sizing: border-box;
}
.grid {
height: 100%;
width: 100%;
background: white;
border: 2px solid red;
display: grid;
grid-template-columns: 250px auto;
grid-template-rows: 100px auto 50px;
grid-template-areas: "sidebar header" "sidebar content" "sidebar footer";
margin-bottom: 2rem;
}
.sidebar {
grid-area: sidebar;
background: green;
}
.header {
grid-area: header;
background: lightblue;
}
.content {
grid-area: content;
background: blue;
border: 5px solid black;
}
.content:last-child {
grid-row: content / footer;
}
.footer {
grid-area: footer;
background: orange;
}
<div class="grid">
<div class="sidebar"></div>
<div class="header"></div>
<div class="content"></div>
<!-- <div class="footer"></div> -->
</div>
<div class="grid">
<div class="sidebar"></div>
<div class="header"></div>
<div class="content"></div>
<div class="footer"></div>
</div>
Or, alternatively, we could reverse the order of the .content and .footer elements in the HTML (as below) and use the CSS negation operator (:not()) to determine that the .content element should take up extra space if it is not preceded by a .footer element:
:not(.footer) + .content {
grid-row: content/footer;
}
which styles a .content element that is not immediately preceded by a .footer sibling in such a way that it starts in the grid-row identified by content and ends in the grid-row identified by footer:
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
div {
box-sizing: border-box;
}
.grid {
height: 100%;
width: 100%;
background: white;
border: 2px solid red;
display: grid;
grid-template-columns: 250px auto;
grid-template-rows: 100px auto 50px;
grid-template-areas: "sidebar header" "sidebar content" "sidebar footer";
}
.sidebar {
grid-area: sidebar;
background: green;
}
.header {
grid-area: header;
background: lightblue;
}
.content {
grid-area: content;
background: blue;
border: 5px solid black;
}
:not(.footer)+.content {
grid-row: content/footer;
}
.footer {
grid-area: footer;
background: orange;
}
<div class="grid">
<div class="sidebar"></div>
<div class="header"></div>
<div class="content"></div>
<!-- <div class="footer"></div> -->
</div>
<div class="grid">
<div class="sidebar"></div>
<div class="header"></div>
<div class="content"></div>
<div class="footer"></div>
</div>
References:
grid-row.
:last-child.
Negation pseudo-class:not().
Sometimes things are simpler with flexbox.
Since your container has a defined height (the viewport), you can use flex-flow: column wrap to create both columns.
Then use flex: 1 on the content item, which tells it to consume free space.
When the footer is present, the content makes space for it. When the footer is not present, the content consumes all space.
.grid {
display: flex;
flex-flow: column wrap;
height: 100vh;
background: white;
border: 2px solid red;
}
.sidebar {
flex: 0 0 100%;
width: 250px;
background: green;
}
.header {
flex: 0 0 100px;
width: calc(100% - 250px);
background: lightblue;
}
.content {
flex: 1;
width: calc(100% - 250px);
border: 5px solid black;
background: blue;
}
.footer {
flex: 0 0 50px;
width: calc(100% - 250px);
background: orange;
}
body { margin: 0; }
div { box-sizing: border-box; }
<!-- WITH FOOTER -->
<div class="grid">
<div class="sidebar"></div>
<div class="header"></div>
<div class="content"></div>
<div class="footer"></div>
</div>
<hr>
<!-- WITHOUT FOOTER -->
<div class="grid">
<div class="sidebar"></div>
<div class="header"></div>
<div class="content"></div>
</div>
Change your .grid class to
.grid {
display: grid;
grid-template-columns: 250px auto;
grid-template-rows: 100px auto 50px;
grid-template-areas:
"sidebar header"
"sidebar content"
"sidebar content";
}
when you comment your footer tag as in your pen, grid is still waiting to have a footer element there, so it's kinda "saving space" for this element there