HTML grid layout disrupted by SVG child element - html

I'm trying to make a page with a simple 3x3 grid layout: header top, footer bottom, two sidebars, and the main display. Everything works fine until I add the SVG element that should fill the main-display div:
<div class="main">
<svg viewBox="0 0 500 500"></svg>
</div>
The whole grid layout gets confused at this point, with the browser eliminating the header, extending the page below the height: 100% that I have declared, etc.
I can easily "fix" this by setting my SVG max-height and max-width arbitrarily small (below ~60% in Firefox 62.0.3; in Safari 12.0, <90%). But that isn't really a fix since it leaves a conspicuous gap (a huge one in Firefox). I much prefer to size my SVG 100% to fill its space in the grid. I must be missing something. What am I doing wrong?
Edit: Adding a screenshot of what I want and (one version of) what I have.
Here is what I have. Here is what I want.
The stylesheet for what you see is below. The only difference between the two images is the change in max-width and max-height from 10% to 100%.
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
display: grid;
border-style: solid; // to show that body renders improperly
border-color: red;
grid-template-columns: 3fr 9fr 2fr;
grid-template-rows: 1fr 10fr 1fr;
width: 100vw;
height: 100vh;
}
div {
border: solid black 1px; // to show div positions
}
.header {
grid-column: 1 / 4;
grid-row: 1;
}
.main {
grid-column: 2;
grid-row: 2;
}
.side1 {
grid-column: 1;
grid-row: 2;
}
.side2 {
grid-column: 3;
grid-row: 2;
}
.footer {
grid-column: 1 / 4;
grid-row: 3;
}
svg {
max-height: 100%;
max-width: 100%;
}
<body>
<div class="header">Header</div>
<div class="side1">Site 1</div>
<div class="main">
<svg viewBox="0 0 500 500"></svg>
</div>
<div class="side2">Site 2</div>
<div class="footer">Footer</div>
</body>

It turns out that the problem is not with the svg element at all, but with its containing div (.main in the question's code snippet). Like flex items, grid items have a default min-width: auto and min-height: auto. By setting them to 0, the svg is able to size automatically, as it should.
I still don't quite understand why the svg disrupted the layout, especially when it was set to 80% in Firefox, leaving conspicuous space around it, but the problem with the grid layout itself is clear enough.
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
display: grid;
grid-template-columns: 3fr 9fr 2fr;
grid-template-rows: 1fr 10fr 1fr;
width: 100vw;
height: 100vh;
}
div {
border: solid black 1px; // to show div positions
}
.header {
grid-column: 1 / 4;
grid-row: 1;
}
.main {
grid-column: 2;
grid-row: 2;
min-width: 0;
min-height: 0;
}
.side1 {
grid-column: 1;
grid-row: 2;
}
.side2 {
grid-column: 3;
grid-row: 2;
}
.footer {
grid-column: 1 / 4;
grid-row: 3;
}
svg {
max-height: 100%;
max-width: 100%;
}
<body>
<div class="header">Header</div>
<div class="side1">Site 1</div>
<div class="main">
<svg viewBox="0 0 500 500"></svg>
</div>
<div class="side2">Site 2</div>
<div class="footer">Footer</div>
</body>

Please see below. No issues encountered.
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.wrapper {
display: grid;
grid-template-columns: 3fr 9fr 2fr;
grid-template-areas: "header header header" "side1 main side2" "footer footer footer";
}
.wrapper>div {
border: thin solid black;
/* For visibility only */
}
.header {
grid-area: header;
}
.side1 {
grid-area: side1;
}
.main {
grid-area: main;
}
.side2 {
grid-area: side2;
}
.footer {
grid-area: footer;
}
<div class="wrapper">
<div class="header">Header</div>
<div class="side1">Site 1</div>
<div class="main"><svg viewBox="0 0 500 500"></svg></div>
<div class="side2">Site 2</div>
<div class="footer">Footer</div>
</div>

Related

How can I prevent overflow of nested grid's content of div?

MCVE
I would like to nest a grid within another grid, and have a tall content box within the nested grid's content div. However no matter I set the overflow property of this content div to scroll, the content box grows causing the outer grid to exceed the viewport. So the viewport gets a scrollbar. The scrollbar of the content div is present but disabled.
// html
<div class="outergrid">
<div class="row1">
Outer Grid Header
</div>
<div class="row2">
<div class="header">
Inner Grid Header
</div>
<div class="box">
Tall Box
</div>
</div>
</div>
// style scss
*{
padding: 0px;
margin: 0px;
}
.outergrid {
display: grid;
grid-template-rows: 50px 100%;
grid-gap: 10px;
background-color: #0ff;
div {
background-color: #afa;
}
}
.row1{
grid-row: 1;
}
.row2{
grid-row: 2;
display: grid;
grid-template-rows: 50px 100%;
grid-gap: 5px;
.header {
grid-row: 1;
background-color: #ffa;
}
.contentbox {
grid-row: 2;
overflow: scroll;
.tallcontent {
background-color: #89f;
height: 1000px;
}
}
}
screenshot highlighting the problem
If I understood you correctly, then perhaps this solution (pure CSS, without SCSS) below can help you. The solution is to enforce a constraint on the height of the parent elements.
* {
padding: 0px;
margin: 0px;
}
.outergrid {
--grid-gap: 10px;
display: grid;
grid-template-rows: 50px calc(100% - 50px - var(--grid-gap));
grid-gap: var(--grid-gap);
background-color: #0ff;
max-height: 100vh;
}
.outergrid div {
background-color: #afa;
}
.row1 {
grid-row: 1;
}
.row2 {
--grid-gap: 5px;
grid-row: 2;
display: grid;
max-height: 100%;
grid-template-rows: 50px calc(100% - 50px - var(--grid-gap));
grid-gap: var(--grid-gap);
}
.row2 .header {
grid-row: 1;
background-color: #ffa;
}
.row2 .contentbox {
grid-row: 2;
overflow: scroll;
}
.row2 .contentbox .tallcontent {
background-color: #89f;
height: 1000px;
}
<div class="outergrid">
<div class="row1">
Outer Grid Header
</div>
<div class="row2">
<div class="header">
Inner Grid Header
</div>
<div class="contentbox">
<div class="tallcontent">
Tall Content
</div>
</div>
</div>
</div>

Why isn't using the highest z-index allowing my icon to cover a div that should go beneath it but it will not? [duplicate]

This question already has answers here:
Why can't an element with a z-index value cover its child?
(5 answers)
Closed 2 years ago.
I've searched around for other answers but can't seem to fin one specifically... I'm using z-index correctly so I don't get why this is happening. That line you see in the example is supposed to go under the icon and over the sidebar but it is not.
I've tried so far
Fiddling with the z-indexes
Giving the icon in question position absolute
placing the !important keyword on the z-index property
.
.container {
background-color: #d9d8d7;
width: 600px;
height: 500px;
display: grid;
grid-template-rows: repeat(6, 1fr);
grid-template-columns: repeat(6, 1fr);
grid-gap: 5px;
}
.text-container {
background: pink;
grid-column: 3 / -1;
grid-row: 1 / 3;
display: grid;
grid-template-rows: repeat(5, 1fr);
grid-template-columns: repeat(5, 1fr);
grid-gap: 5px;
}
.top-left-container {
grid-column: 1 / 4;
grid-row: 1 / 4;
position: relative;
background-color: orange;
/* position:relative; */
}
.horizontal-line {
position: absolute;
bottom: 75%;
left:-150%;
height: 2px;
width: 300%;
z-index: ;
background-color: black;
/* z-index level 2 "middle" */
z-index: 10;
}
.heading {
/* background-color:yellow; */
grid-column: 1 /-1;
grid-row: 1 / 2;
}
.sidebar {
background-color: lightblue;
grid-row: 1 / -1;
grid-column: 1 / 2;
display: flex;
flex-direction: column;
justify-content: start;
align-items: center;
/* z-index level 1 */
z-index: 5;
}
.sidebar__wrapper {
display: flex;
flex-direction: column;
/* background-color: red; */
}
.sidebar__icon {
margin: 10px;
height: 50px;
width: 50px;
z-index: 50;
/* z-index level 3 Why wont'this cover the div
that has a higher z-index than it */
z-index: 15;
}
<div class="container">
<div class="sidebar">
<div class="sidebar__wrapper">
<img src="https://cdn0.iconfinder.com/data/icons/images-icons-rounded/110/Image-Focus-512.png" alt="" class="sidebar__icon">
<img src="https://cdn0.iconfinder.com/data/icons/images-icons-rounded/110/Image-Focus-512.png" alt="" class="sidebar__icon">
<img src="https://cdn0.iconfinder.com/data/icons/images-icons-rounded/110/Image-Focus-512.png" alt="" class="sidebar__icon">
</div>
</div>
<div class="text-container">
<div class="top-left-container">
<div class="heading">Header Here</div>
<div class="horizontal-line"></div>
</div>
</div>
</div>
So there are four things about z-index:
the lower in the code the higher the placement
adding a transform or opacity will give new z-index context (meaning higher yet again)
positioning an element will do the same as number 2
And lastly, as is in your case, a child element will inherit and be limited by its parent element if its parent element has a z-index set
The solutions:
Either take the child div out, and make it a sibling to the competing z-index div on the page (in your case that line) *recommended
Remove z-index context on parent element, so child again can be free
Give the element you want to stand out one more z-index
I added z-index .sidebar__wrapper class more then .horizontal-line class
.container {
background-color: #d9d8d7;
width: 600px;
height: 500px;
display: grid;
grid-template-rows: repeat(6, 1fr);
grid-template-columns: repeat(6, 1fr);
grid-gap: 5px;
}
.text-container {
background: pink;
grid-column: 3 / -1;
grid-row: 1 / 3;
display: grid;
grid-template-rows: repeat(5, 1fr);
grid-template-columns: repeat(5, 1fr);
grid-gap: 5px;
}
.top-left-container {
grid-column: 1 / 4;
grid-row: 1 / 4;
position: relative;
background-color: orange;
/* position:relative; */
}
.horizontal-line {
position: absolute;
bottom: 75%;
left:-150%;
height: 2px;
width: 300%;
background-color: black;
/* z-index level 2 "middle" */
z-index:10;
}
.heading {
/* background-color:yellow; */
grid-column: 1 /-1;
grid-row: 1 / 2;
}
.sidebar {
background-color: lightblue;
grid-row: 1 / -1;
grid-column: 1 / 2;
display: flex;
flex-direction: column;
justify-content: start;
align-items: center;
/* z-index level 1 */
}
.sidebar__wrapper {
display: flex;
flex-direction: column;
z-index: 11;
/* background-color: red; */
}
.sidebar__icon {
margin: 10px;
height: 50px;
width: 50px;
z-index: 50;
/* z-index level 3 Why wont'this cover the div
that has a higher z-index than it */
z-index: 15;
}
<div class="container">
<div class="sidebar">
<div class="sidebar__wrapper">
<img src="https://cdn0.iconfinder.com/data/icons/images-icons-rounded/110/Image-Focus-512.png" alt="" class="sidebar__icon">
<img src="https://cdn0.iconfinder.com/data/icons/images-icons-rounded/110/Image-Focus-512.png" alt="" class="sidebar__icon">
<img src="https://cdn0.iconfinder.com/data/icons/images-icons-rounded/110/Image-Focus-512.png" alt="" class="sidebar__icon">
</div>
</div>
<div class="text-container">
<div class="top-left-container">
<div class="heading">Header Here</div>
<div class="horizontal-line"></div>
</div>
</div>
</div>

Filling large gaps between rows

In the code box-2 and box-3 row height auto stretches to box-1 height which is tallest item in the row. There is a extra gap in box-2 and box-3 columns. I want that gap to be filled up by the box-5 which is in the second row. Fiddle
.container {
display: grid;
grid-template-columns: 20% 40% 40%;
grid-gap: 20px;
}
.container > div {
border: 1px solid red;
}
.box-1 {
background-color: lightgreen;
height: 300px;
}
.box-2 {
background-color: lightsalmon;
height: 150px;
}
.box-3 {
background-color: lightsalmon;
height: 150px;
}
.box-4 {
background-color: lightskyblue;
height: 500px;
}
.box-5 {
background-color: lightseagreen;
grid-column: 2/-1;
}
<div class="container">
<div class="box-1"></div>
<div class="box-2"></div>
<div class="box-3"></div>
<div class="box-4"></div>
<div class="box-5"></div>
</div>
This is the output I am looking for
You're setting the height of the grid items directly, and not defining any rows on the grid container. Therefore, the grid algorithm has to create rows to accommodate the grid areas. It only needs to create two rows to complete the layout. That's why there's a large gap beneath boxes 2 and 3. Box 1, being the tallest, sets the height of top row.
The layout you want requires at least three rows.
Try this approach: Set the rows (and heights) at the container level, then set the grid areas.
.container {
display: grid;
grid-template-columns: 1fr 2fr 2fr;
grid-template-rows: repeat(3, 150px);
grid-gap: 10px;
}
.box-1 {
grid-column: 1;
grid-row: 1 / span 2;
background-color: lightgreen;
}
.box-2 {
grid-column: 2;
grid-row: 1;
background-color: lightsalmon;
}
.box-3 {
grid-column: 3;
grid-row: 1;
background-color: lightsalmon;
}
.box-4 {
grid-column: 2 / -1;
grid-row: 2 / 4;
background-color: lightskyblue;
}
.box-5 {
grid-column: 1;
grid-row: 3;
background-color: lightseagreen;
}
<div class="container">
<div class="box-1">1</div>
<div class="box-2">2</div>
<div class="box-3">3</div>
<div class="box-4">4</div>
<div class="box-5">5</div>
</div>
If you want more options for sizing grid areas, then increase the number of rows / columns.
For example, instead of this:
grid-template-rows: repeat(3, 150px)
...you can do this:
grid-template-rows: repeat(9, 50px)
... then span grid areas across rows as needed.
Keep box 1 and box 3 in one div align it vertically and keep all other 3 boxes in one container in 1 container then u can do this easily

Grid layout stretching height to fit content, but remaining other grid-cells height

I'm trying to make grid layout. This is code:
<div class="wrapper">
<div class="header">HEADER</div>
<div class="nav">NAV
</div>
<div class="aside-left">LEFT</div>
<div class="main">MAIN
<img src="a1.jpeg">
<img src="a1.jpeg">
<img src="a1.jpeg">
</div>
<div class="aside-right">RIGHT</div>
<div class="footer">FOOTER</div>
</div>
</body>
.wrapper{
height: 100%;
width: 100%;
background-color: ghostwhite;
display: grid;
grid-template-columns: repeat(12,1fr);
grid-template-rows: minmax(100px,auto);
grid-gap:5px;
}
.header{
grid-column: 1/13;
grid-row: 1/2;
}
.nav{
grid-column: 1/13;
grid-row: 2/3;
}
.aside-left{
grid-column: 1/3;
grid-row: 3/10;
}
.main{
grid-column: 3/11;
grid-row: 3/10;
}
.aside-right{
grid-column: 11/13;
grid-row: 3/10;
}
.footer{
grid-column: 1/13;
grid-row:10/12;
}
I want class main to stretch to fit it's content and it is working, but .nav and .footer doesn't take up their min height 100px, but they seem to take up auto height too, however header class works correctly, so any ideas? I want other elements to have at least 100px height
I figured out answer:
body, html{
background-color: ghostwhite;
height: auto;
}
.wrapper{
max-height: auto;
width: 100%;
background-color: ghostwhite;
display: grid;
grid-template-columns: repeat(4,1fr);
grid-auto-rows: minmax(100px,auto);
grid-gap:5px;
}
it seems 100% height was factoring out other elements' height, while increasing others'

CSS Grid - auto column height

The cart form is stretching vertically and the thumbs are positioning in the bottom left corner, when I'd like them to sit directly under the cart form like so:
.product-page--main-content {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: auto 1fr auto;
}
.product-page--main-content>* {
padding: 50px 100px;
border: 1px solid #ccc;
}
.product-page--cart-form-block {
grid-row: 2;
}
.product-page--thumbs {
grid-row: 3;
}
.product-page--images {
grid-column: span 2;
grid-row: span 3;
height: 400px;
}
.product-page--description {
grid-row: span 3;
}
<div class="product-page--main-content">
<div class="product-page--title-n-vendor">Title</div>
<div class="product-page--cart-form-block">Cart form</div>
<div class="product-page--thumbs">Thumbs</div>
<div class="product-page--images">Images</div>
<div class="product-page--description">Description</div>
</div>
Codepen: https://codepen.io/paulmason/pen/rYXyYW
The code you have is working perfectly, as written.
Your image grid item is set to height: 400px.
.product-page--images {
grid-column: span 2;
grid-row: span 3;
height: 400px;
}
Then you have 50px in top and bottom padding.
.product-page--main-content > * {
padding: 50px 100px;
border: 1px solid #ccc;
}
So the image grid item is 500px tall, in a row set to 1fr, in a grid with three rows. It all works perfectly, as specified.
Maybe what you want is four rows:
.product-page--main-content {
display: grid;
grid-template-columns: repeat(4, 1fr);
/* grid-template-rows: auto 1fr auto; */ /* now defaults to grid-auto-rows: auto */
}
.product-page--main-content > * {
padding: 50px 100px;
border: 1px solid #ccc;
}
.product-page--cart-form-block {
grid-row: 2;
}
.product-page--thumbs {
grid-row: 3;
}
.product-page--images {
grid-column: span 2;
grid-row: span 4; /* changed from 3 */
height: 400px;
}
.product-page--description {
grid-row: span 4; /* changed from 3 */
}
<div class="product-page--main-content">
<div class="product-page--title-n-vendor">Title</div>
<div class="product-page--cart-form-block">Cart form</div>
<div class="product-page--thumbs">Thumbs</div>
<div class="product-page--images">Images</div>
<div class="product-page--description">Description</div>
</div>
I'm not sure this is what you're asking but this seems to fit: change
grid-template-rows: auto 1fr auto;
to
grid-template-rows: 3;