Grid item collapsing on smaller screen size - html

I have a set of children inside a display: grid container - each child is numbered. At the 600px breakpoint, child 4 completely loses composure and deflates to its inner content size. Why doesn't 4 hop on down below 3?
.box {
background: yellow;
display: flex;
justify-content: center;
align-items: center;
font-size: 48px;
font-weight: bold;
}
.box.md {
grid-column: span 2;
}
.box.lg {
grid-column: span 2;
grid-row: span 2;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
grid-auto-rows: 240px;
grid-auto-flow: dense;
grid-gap: 8px;
}
#media (max-width: 920px) {
max-width: 800px;
}
#media (max-width: 600px) {
grid-auto-rows: 120px;
}
<div class="container">
<div class="box lg">1</div>
<div class="box md">2</div>
<div class="box sm">3</div>
<div class="box sm">4</div>
</div>
https://jsfiddle.net/amw273vq/

Why doesn't 4 hop on down below 3?
Because items 1 & 2 both have grid-column: span 2 applied. Meaning there are two columns already available, and item 4 has no reason to move to the next row.
Make all columns take a full row.
Add this to your code:
#media (max-width: 600px) {
.container > div {
grid-column: span 1 !important; (you need to override the span 2 rules higher up)
}
}
revised demo
And the reason for the collapse of item 4 has nothing to do with your media query.
If you look closely, you'll find the item 4 collapses when the screen width is 640px. This is before the 600px media query is reached.
Here's the issue:
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr))
At 640px screen width, item 3 reaches 280px, the minimum width it can be.
As a result, item 4 is pushed to the second column, which was created by grid-column: span 2 on its siblings.
However, at this screen size, there is only space for one explicit (i.e., defined) column. The second column must be generated in the implicit (i.e., undefined) grid.
And, because the default value of grid-auto-columns – the property that sizes implicit columns – is auto, the second column takes the width of the widest cell.

Related

How to make columns into rows in css grid [duplicate]

This question already has answers here:
How to create a CSS Grid Layout box that spans 2 columns and 2 rows?
(3 answers)
Make grid container fill columns not rows
(6 answers)
Closed 2 months ago.
I have a css-grid layout set up as 3 columns. When a certain media-query matches, i want it to instead flow as rows where the first column becomes the first row, covering the full with. Column two and three should become one row and share the space equally. How can i achieve that? (i know how to write a media query, code is for demonstrating only)
.thegrid {
display: grid;
grid-template-columns: 1fr auto auto;
gap: 40px;
}
<div class="thegrid">
<div>
content 1
</div>
<div>
content 2
</div>
<div>
content 3
</div>
</div>
If you keep the columns, and add grid-column: 1/-1 to the first div (this makes sure the div covers the complete grid area). Does that give the desired look?
You must display grid then when your #media screen hits its threshold it will begin to flex. You have to tell which rows you want to combine within your flexed column and how far to extend them. Hopefully this helps and makes sense. good luck!
.thegrid {
display: grid;
grid-template-columns: auto auto auto;
grid-template-rows: 80px 200px;
gap: 10px;
background-color: #2196F3;
padding: 10px;
}
#media only screen and (max-width: 600px) {
.thegrid {
display: grid;
grid-template-columns: auto auto auto;
grid-template-rows: 80px 200px;
gap: 10px;
background-color: #2196F3;
padding: 10px;
}
.row-1 {
grid-column: 1/ span 2;
grid-row: 1;
}
.row-2 {
grid-row: 2;
}
}
<div class="thegrid">
<div class="row-1">
content 1
</div>
<div class="row-2">
content 2
</div>
<div class="row-2">
content 3
</div>
</div>

Div not getting displayed into 4 column and shrinking into 2 when adjusting window size

I have got a div which has 4 items and want to display them in a single row for large devices. It does display as I want, but there is a scroll bar on the page which makes this annoying. I need to scroll from left to right to see all the items if that makes sense.
Here's the code:
.container {
display: flex;
width: 100%;
height: 534px;
}
#media only screen and (max-device-width: 1080px) {
.container {
flex-direction: row;
flex-wrap: wrap;
width: 100%;
}
}
.item{
width: 250px;
position: relative;
margin: 50px auto;
}
<div class="container">
<div class="item">1</div>
<div class="item">1</div>
<div class="item">1</div>
<div class="item">1</div>
</div>
You have several options depending on exactly what outcome you want.
The simplest is to just allow the items (which have a fixed width) to wrap to the next line when the window is too small to accommodate them all. This means you may sometimes get 3 on the first line and 1 on the second.
With more control you can switch to making sure there are either 4 or 2 (or, on really narrow windows, 1) item in a row.
This snippet uses a grid to do this with breakpoints set using max-width (see note below).
.container {
display: grid;
grid-template-columns: repeat(4, 1fr);
width: 100%;
height: 534px;
}
#media only screen and (max-width: 1080px) {
.container {
grid-template-columns: repeat(2, 1fr);
}
}
#media only screen and (max-width: 270px) {
.container {
grid-template-columns: repeat(1, 1fr);
}
}
.item {
width: 250px;
position: relative;
margin: 50px auto;
}
<div class="container">
<div class="item">1</div>
<div class="item">1</div>
<div class="item">1</div>
<div class="item">1</div>
</div>
Note: device-width is deprecated (see for example [https://developer.mozilla.org/en-US/docs/Web/CSS/#media/device-width][1]
And the width of a device is not really relevant - what we need to adjust for is the width of the window. This is done in a media query with max-width.
Note also that both your original code and this snippet lessen the height of each item for narrower viewports as you have set a fixed height for the container. If you want the items to maintain full height then set height on the item (or adjust the height of container accordingly).
[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/#media/device-width

How to display two divs next to each other on a smartphone?

I have 4 divs and on a normal computer screen, they come next to each other with the following code.
.parent {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: 1fr;
grid-column-gap: 0px;
grid-row-gap: 0px;
}
.div1 {
grid-area: 1 / 1 / 2 / 2;
}
.div2 {
grid-area: 1 / 2 / 2 / 3;
}
.div3 {
grid-area: 1 / 3 / 2 / 4;
}
.div4 {
grid-area: 1 / 4 / 2 / 5;
}
<div class="parent">
<div class="div1">1</div>
<div class="div2">2</div>
<div class="div3">3</div>
<div class="div4">4</div>
</div>
When I view this on my smartphone, all 4 divs will display in 1 row.
How can I display 2 divs in 1 row? So the final result will be 2 rows with 2 divs each on a smartphone.
change this line: grid-template-columns: repeat(4, 1fr); to: grid-template-columns: repeat(2, 1fr); then you only have 2 columns per row.
then change this line: grid-template-rows: 1fr; to: grid-auto-rows: auto; to automatically insert as many rows as needed at size them to the highest content.
last but not least: delete css for all div-boxes as they are useless in this case anyway. Also its not the way it is or should be used.
use media queries to adjust design for different screen sizes as used in the sample below:
#media start the media query. with only screen you define that only the screen size should be used as rule. and (max-width: 480px) defines the rule to be applied for mobile screens (largest is 480px width for portrait mode).
.parent {
display: grid;
grid-auto-rows: auto;
grid-gap: 0px;
}
#media only screen
and (max-width: 480px) {
.parent {
grid-template-columns: repeat(2, 1fr);
}
}
#media only screen
and (min-width: 481px) {
.parent {
grid-template-columns: repeat(4, 1fr);
}
}
<div class="parent">
<div class="div1">1</div>
<div class="div2">2</div>
<div class="div3">3</div>
<div class="div4">4</div>
</div>
You can use #media screen to make custom Css for different screen sizes.
#media screen is used to specify different layout for various screen sizes.
You can find the guide here:
https://www.w3schools.com/cssref/css3_pr_mediaquery.asp
This guide also includes examples where you would get an idea how to unitize #media screen thing.

Expanding to fill remaining space in a CSS Grid layout

I want to use CSS grid and the following is a mock-up of the aim:
I'm building an interface that should expand rightward to fill the browser screen; my current code causes column 2 of the outer grid to be as wide as the browser in addition to column 1; or maybe one of it's children is causing this and it's just expanding to accommodate. Either way, it's spilling off the page horizontally
So the code:
#main {
width: 100%;
display: grid;
grid-template-columns: 250px 100%;
grid-template-rows: 100px 100%;
}
#col-2-outer {
display: grid;
grid-template-columns: 250px auto;
grid-template-rows: 100%;
}
#row-1-inner {
grid-column: span 2;
}
#col-2-inner table {
width: 100%;
}
<div id="main">
<div id="col-1-outer"></div>
<div id="col-2-outer">
<div id="row-1-inner"></div>
<div id="row-2-inner">
<div id="col-1-inner"></div>
<div id="col-2-inner">
<table></table>
</div>
</div>
</div>
</div>
FYI, for the time being I've forgone template areas until I get a handle on the basics (unless this somehow solves my problem but I gather this is strictly a code organization feature?).
I'd suggest to change your markup with a 3x2 grid like below:
Remove the hierarchical structure like you have in your code and add one element for each section in the grid.
Note that in the rule grid-template-columns: 250px 150px auto, 250px is the width of your col-1-outer and 150px is the width of the col-1-inner.
Span the first column over the two rows by using grid-row: span 2
Span the first row in the second column by using grid-column: span 2.
Extend the table over the last grid item by using 100% width and height.
See demo below:
* {
border: 1px solid; /* For illustration */
}
#main {
width: 100%;
display: grid;
grid-template-columns: 250px 150px auto;
grid-template-rows: 100px auto;
}
#col-1-outer {
grid-row: span 2;
}
#row-1-inner {
grid-column: span 2;
}
#col-2-inner table {
width: 100%;
height: 100%;
}
<div id="main">
<div id="col-1-outer">col-1-outer</div>
<div id="row-1-inner">col2-row-1-inner</div>
<div id="col-1-inner">col2-row2-inner</div>
<div id="col-2-inner">
<table><tr><td>table</td></tr></table>
</div>
</div>
The 100% for the 2nd column in your grid-template-columns is based on the width of the container - rather than occupying the space outstanding within the container, it will push out to the right because the 2nd column is trying to match the width of the container.
Try changing this to auto and this should rectify the issue, as it will only take up the space up to the end of the container and no further.
Source: https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns

Flex - changing order of nested elements?

On small screens i'm trying to get my .image div to slot in between .title and .text divs, something like:
title
image
text
.title and .text are wrapped in a container, this is so on a different screen size (medium up) I can do:
title | image
text | continuation of image element
I've thought about using a flex column layout for small screens, and changing the order of elements, but order doesn't seem to have an effect on a nested child element.
Here's the code for small:
HTML:
<div class="container">
<div class="content">
<div class="title"></div>
<div class="text"></div>
</div>
<div class="image"></div>
</div>
CSS:
.container {
display: flex;
flex-direction: column;
}
.image {
order: 2;
}
.title {
order: 1;
}
.text {
order: 3;
}
For reference my code for medium is (cascading upwards from small):
.container {
flex-direction: row;
}
.content {
flex-basis: 50%;
}
.image {
flex-basis: 50%;
}
You can ordering only sibling elements. Title and text aren't sibling with image. You need wrap title, text and image in general parent block
I have similar case, but for solution CSS grid is used, however there is also another support is recommended: CSS subgrid
For a simple design like even columns or rows it is not that hard to replicate, but if parent container contain more complex grid sizes, then CSS subgrid will be requirement for an only CSS solution.
Here is full demo: https://codepen.io/XCanG/pen/vYaNZPo?editors=1100
HTML I have in the demo have very similar structure with having parent, some container for 2 nested elements and 3rd element.
This is quote from my demo, except I rename class names according to your example:
.container {
display: grid;
grid-template-rows: repeat(3, 1fr);
}
.container .content {
display: grid;
grid-column: 1;
grid-row: 1 / span 3;
grid-template-rows: repeat(3, 1fr); /* Fallback */
grid-template-rows: subgrid; /* Limited support: https://caniuse.com/css-subgrid */
grid-template-columns: subgrid;
}
.container .title {
grid-colimn: 1;
grid-row: 1;
}
.container .text {
grid-column: 1;
grid-row: 3;
}
.container .image {
grid-column: 1;
grid-row: 2;
}
CSS make that nested element follow grid columns and rows, with subgrid support you will have exactly defined part of the grid (otherwise you will need to define fallback). And with grid-column and grid-row it is possible to sort elements.
Grid-template-areas will come in pretty handy in this type of layout as they are not siblings. And grid-template-areas have full browser support.
.container {
display: grid;
grid-template-areas: "title img"
"txt img";
}
.title{grid-area: title;}
.text{grid-area: txt;}
.image{grid-area: img;}
#media(max-width: 800px){
.container{
grid-template-areas: 'title'
'img'
'txt';
}
}
<div class="container">
<div class="content">
<div class="title">title</div>
<div class="text">text</div>
</div>
<div class="image">img</div>
</div>