CSS Grid - auto column height - html

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;

Related

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

Making grid responsive

Any idea of how to make this grid responsive?
This is my CSS:
body {
margin: 40px;
}
.wrapper {
display: grid;
grid-gap: 10px;
grid-template-columns: 100px 100px 100px;
background-color: #fff;
color: #444;
}
.box {
background-color: #444;
color: #fff;
border-radius: 5px;
padding: 20px;
font-size: 150%;
}
.a {
grid-column: 1 / 3;
grid-row: 1;
}
.b {
grid-column: 3 ;
grid-row: 1 / 3;
}
.c {
grid-column: 1 ;
grid-row: 2 ;
}
.d {
grid-column: 2;
grid-row: 2;
}
HTML
<div class="wrapper">
<div class="box a">A</div>
<div class="box b">B</div>
<div class="box c">C</div>
<div class="box d">D</div>
</div>
I tried this code:
#media only screen and (max-width:500px) {
.box {
width: 100%;
margin-right: 0;
float: none;
margin-bottom: 20px !important;
}
What's the best way to accomplish this?
I agree with #Petra that you need to use fr, but use a media query if you want to display them stacked on a mobile device. You could also just change the display to block. Make sure you add these after the initial CSS so that it isn't overridden.
#media screen and (max-width: 512px) {
.wrapper {
grid-template-columns: 1fr;
}
}
.wrapper {
display: grid;
grid-gap: 10px;
grid-template-columns: 1fr 1fr 1fr;
background-color: #fff;
color: #444;
}
ith CSS Grid Layout, we get a new flexible unit: the Fr unit. Fr is a fractional unit and 1fr is for 1 part of the available space.

HTML grid layout disrupted by SVG child element

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>

Flexbox/Float anchor items to top [duplicate]

This question already has answers here:
Create a Masonry grid with flexbox (or other CSS)
(3 answers)
Closed 5 years ago.
Consider this example:
Notice that that 4th item is pushed to top instead of aligning with the 3rd item. I can't achieve this using flexbox's align-items: flex-end, neither with floats.
I am aware of achieving this by using masonry/isotope, but I would like to avoid using javascript just for this layout.
Is it possible to achieve using only CSS?
Yes, it's possible via CSS Grid Layout:
.grid {
display: grid;
grid-gap: 10px 30px;
grid-template-rows: auto 1fr auto;
}
/* styles just for demo */
.grid__item {
background-color: #e0e0e0;
font-size: 30px;
padding: 10px;
}
.b, .d {
align-self: flex-start;
}
.a {
grid-row: 1 / span 2;
/* setting height just for demo */
height: 200px;
}
.b {
grid-column: 2;
}
.c {
grid-row: 3;
}
.d {
grid-column: 2;
}
<div class="grid">
<div class="grid__item a">1</div>
<div class="grid__item b">2</div>
<div class="grid__item c">3</div>
<div class="grid__item d">4</div>
</div>
If you need IE\Edge support you should use old grid syntax. You can fake grid-gap using additional grid columns and rows. Demo:
.grid {
display: -ms-grid;
display: grid;
-ms-grid-columns: 1fr 30px 1fr;
grid-template-columns: 1fr 30px 1fr;
-ms-grid-rows: auto 10px 1fr 10px auto;
grid-template-rows: auto 10px 1fr 10px auto;
}
/* styles just for demo */
.grid__item {
background-color: #e0e0e0;
font-size: 30px;
padding: 10px;
}
.b, .d {
-ms-grid-row-align: start;
align-self: flex-start;
}
.a {
-ms-grid-row-span: 3;
grid-row: 1 / span 3;
/* setting height just for demo */
height: 200px;
}
.b {
-ms-grid-column: 3;
grid-column: 3;
}
.c {
-ms-grid-row: 5;
grid-row: 5;
}
.d {
-ms-grid-column: 3;
grid-column: 3;
-ms-grid-row: 3;
grid-row: 3;
}
<div class="grid">
<div class="grid__item a">1</div>
<div class="grid__item b">2</div>
<div class="grid__item c">3</div>
<div class="grid__item d">4</div>
</div>

rows overlapping in CSS Grid Layout

How can I prevent the footer row from overlapping the content row?
This is what I'm getting:
body {
display: grid;
grid-template-rows: 3.7rem auto auto;
grid-template-columns: 3rem 3fr 2fr;
}
*[role="banner"] {
grid-row: 1;
grid-column: 2/4;
background-color: green;
height: 3rem;
}
*[role="main"] {
grid-row: 2;
grid-column: 2;
background-color: yellow;
height: 100px;
}
*[role="contentinfo"] {
grid-row: 3;
grid-column: 2/3;
border-top: 1px solid black;
}
*[role="contentinfo"] img {
height: 100px;
}
<div role="banner"></div>
<article role="main"><p>Some Text.</p><p>Some more text</p><p>the last text</p></article>
<footer role="contentinfo"><img src="https://s14-eu5.ixquick.com/cgi-bin/serveimage?url=https%3A%2F%2Fdata.motor-talk.de%2Fdata%2Fgalleries%2F0%2F147%2F9424%2F43109894%2Fbild--7008737403287221413.jpg&sp=6a4eaf3bd8ff58ca9d9bba2e3519888e"></footer>
The footer (row 3) is overlapping the article (row 2) because you have a fixed height on the article:
[role="main"] { height: 100px; }
The overrides the auto height you have specified on the grid container with:
grid-template-rows: 3.7rem auto auto
Once you remove the height rule, the overlap is gone.
body {
display: grid;
grid-template-rows: 3.7rem auto auto;
grid-template-columns: 3rem 3fr 2fr;
}
*[role="banner"] {
grid-row: 1;
grid-column: 2/4;
background-color: green;
height: 3rem;
}
*[role="main"] {
grid-row: 2;
grid-column: 2;
background-color: yellow;
/* height: 100px; <-------- REMOVE */
}
*[role="contentinfo"] {
grid-row: 3;
grid-column: 2/3;
border-top: 1px solid black;
}
*[role="contentinfo"] img {
height: 100px;
}
<div role="banner"></div>
<article role="main"><p>Some Text.</p><p>Some more text</p><p>the last text</p></article>
<footer role="contentinfo"><img src="https://s14-eu5.ixquick.com/cgi-bin/serveimage?url=https%3A%2F%2Fdata.motor-talk.de%2Fdata%2Fgalleries%2F0%2F147%2F9424%2F43109894%2Fbild--7008737403287221413.jpg&sp=6a4eaf3bd8ff58ca9d9bba2e3519888e"></footer>