I'm trying to model a CSS grid
I'd like it to be 2x2
xx yy
ww zz
While the screen is at least N width, I want each of the cells to take up 50% of the width, with a gap in between.
xxxx yyyy
wwww zzzz
When the screen hits a certain min width, I want the grid to stack
x
y
w
z
If I start with this grid
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(50%, 1fr));
grid-column-gap: 32px;
grid-row-gap: 32px;
}
.grid-item {
width: 100%;
height: 100%;
}
<div class="grid">
<div class="grid-item"/>
<div class="grid-item"/>
<div class="grid-item"/>
<div class="grid-item"/>
</div>
The grid is always vertically stacked, since there will never be enough room for 2 50% cells, with a static 32px column gap.
If I change it to
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(49%, 1fr));
grid-column-gap: 32px;
grid-row-gap: 32px;
}
Then the grid will be 2x2, up until some minimum screen width, where they'll stack vertically. This is the behavior I want, aside from the fact that the grid vertically stacking seems somewhat accidental, since it only happens due to the grid-column-gap. I'm not actually defining a minimum width for my grid cells, it's just whatever width results in my column-gap taking up more than 2% of the space.
What if I wanted to explicitly define the pixel limit for the grid collapsing? What if I wanted this behavior without having a column-gap?
Perhaps a nice approach to fix this problem could be using CSS' media queries and percentages. You can use a code like below:
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
<style>
.grid{
width:100%;
}
#media only screen and (min-width: 600px) {
.grid-item {
display:inline-block;
width:46%;
padding: 1%;
}
}
#media only screen and (max-width: 599px) {
.grid-item {
width:100%;
display:block;
padding: 32px;
}
}
</style>
</head>
<body>
<div class="grid">
<div class="grid-item">one</div>
<div class="grid-item">two</div>
<div class="grid-item">three</div>
<div class="grid-item">four</div>
</div>
</body>
Another approach which is easier could be using Bootstrap's grids but as your question didn't have the Bootstrap tag, I didn't mention it.
Related
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
I want to achieve 12 column grid behavior similar to what Bootstrap has,
but using CSS grids.
I need to have a fixed gapsĀ in pixels
And have a 12 column grid, so I can decide how to place the children.
I'm facing the issue, that combination of grid-template-columns and column-gap doesn't shrink the columns on a smaller screens, but cause horizontal overflow on a screen.
How can I achieve expected behavior with shrinking without reducing the number of columns and keeping the gap in pixels.
DEMO:
.parent {
max-width: 300px;
height: 500px;
overflow: auto;
border: 1px solid blue;
}
.box {
grid-column: span 6 / span 6;
background: red;
height: 40px;
}
.grid {
display: grid;
grid-template-columns: repeat(12, minmax(0, 1fr));
gap: 40px;
}
<div class="parent">
<div class="grid">
<div class="box"></div>
<div class="box"></div>
</div>
</div>
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
I am finishing my portfolio site, but I encountered a problem. I used auto-fit function, because I want it to be responsive, and I will keep adding new images there each month.
I found that I can't center it the way I want, because grid is filling empty space with additional columns which I don't need right now, so my grid is kissing left side of my website. Please help guys, you are the best! :)
<section class="projects">
<h2 class="h2">Projects</h2>
<div class="projects__part">
<h4 class="h4">Primary projects</h4>
<div class="projects__item">
<img src="https://hlfppt.org/wp-content/uploads/2017/04/placeholder.png" class="projects-item__img">
</div>
<div class="projects__item">
<img src="https://hlfppt.org/wp-content/uploads/2017/04/placeholder.png" class="projects-item__img">
</div>
<div class="projects__item">
<img src="https://hlfppt.org/wp-content/uploads/2017/04/placeholder.png" class="projects-item__img">
</div>
</div>
<div class="projects__part">
<h4 class="h4">Secondary projects</h4>
<div class="projects__item">
<img src="https://hlfppt.org/wp-content/uploads/2017/04/placeholder.png" class="projects-item__img">
</div>
<div class="projects__item">
<img src="https://hlfppt.org/wp-content/uploads/2017/04/placeholder.png" class="projects-item__img">
</div>
<div class="projects__item">
<img src="https://hlfppt.org/wp-content/uploads/2017/04/placeholder.png" class="projects-item__img">
</div>
</div>
</section>
.projects {
&__part {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
/*DESIRED RESPONSIVE EFFECT:
h4 {
margin-left: 22rem;
}
margin-left: 35rem;
*/
}
&-item {
&__img {
width: 14rem;
height: 14rem;
border-radius: 100%/100%;
}
}
h4 {
grid-column: 1 / -1;
}
}
Here's my code : https://codepen.io/maja5252/pen/XPPaBL?editors=1100#0
Again sorry if format of this post is not correct. Still don't know how to split my code to HTML and CSS part :)
A couple issues with your code:
-CSS grid likes to control the size of its columns, and you've got fixed height/width on your images. If you do a DevTools inspection of your code, you'll see your 3rd column is overflowing out of your grid because of this. I changed the height/width to 100%/100%. If you need square images, fix that issue in Photoshop not CSS.
-Centering the entire grid is pretty simple, all you need to do is add margin: 0 auto because it's a block-level element. But, a block level element takes up 100% width of the viewport, so centering a 100% width element won't produce any visible effect. I put the width at 80% to demonstrate how this might look centered, but you could use any non-100% value for this effect.
-I'm also not sure what you're doing with auto-fit in your grid. Just use 1fr and it works really well and the code is clean.
-I also made the whole grid responsive for you - not sure you want to do that, but might as well showcase it.
All the corrected CSS issues together:
.projects {
margin: 0 25px;
#media (min-width: 450px) {
width: 80%;
margin: 0 auto;
}
&__part {
display: grid;
grid-gap: 25px;
grid-template-columns: 1fr;
#media (min-width: 450px) and (max-width: 768px) {
grid-template-columns: 1fr 1fr;
}
#media (min-width: 768px) {
grid-template-columns: 1fr 1fr 1fr;
}
}
&-item {
&__img {
width: 100%;
height: 100%;
border-radius: 50%;
}
}
h4 {
grid-column: 1 / -1;
}
}
Demo:
https://codepen.io/staypuftman/pen/qMMPwp
I found out, that my H4 headings were disrupting an auto-fit effect, so it worked like auto-fill effect. Code is edited - I pulled headings out of the grid, and it got centered.
to #staypuftman - thanks for your advices - I'll keep them in mind in my future work. Now, when auto-fit works, you can see how responsive it is, without any media query. Again thanks for your effort to help me.
I've been playing around with CSS Grid recently and have noticed something that I can't see to find the answer to. Let's say I split my page out to have 2 columns, and then a row below it, with another column (which spans both columns). On mobile, I'd like them to stack one on top of the other and then go back to layout described above after a certain breakpoint. Here is the markup:
HTML
<div class="grid">
<div class="upper">
<div class="a">A</div>
<div class="b">B</div>
</div>
<div class="lower">
<div class="c">C</div>
</div>
</div>
SCSS
.upper, .lower {
display: grid;
}
.upper {
grid-template-columns: 1fr 1fr;
grid-template-rows: auto auto;
background-color:grey;
grid-gap:10px;
#media only screen and (max-width:800px) {
grid-template-columns: 1fr;
grid-template-rows: auto;
}
}
.lower {
grid-template-columns: 1fr;
grid-template-rows:auto;
background-color: green;
grid-gap:10px;
}
I've noticed that on mobile, even though I've defined grid-gap for both of my grid sections, on mobile when the columns stack, the grid-gap is not maintained. So in the fiddle below, when you make the window smaller, you can see that when the columns, stack one on top of the other, the gap between B and C is non existent. Here is the fiddle:
Fiddle
Hope I'm making sense!
EDIT: Bear in mind I'm only testing this in Firefox and Chrome (which support grid).
The grid-gap rule doesn't work between B and C because it doesn't apply.
This rule creates gutters between rows and columns inside a grid container.
But you are declaring grid-gap on .upper and .lower, two siblings in a block container. Their parent (.grid) is not a grid container because it doesn't have display: grid or inline-grid.
Therefore, grid-gap: 10px on .upper is creating a 10px gutter between A and B...
and grid-gap: 10px on .lower is creating a 10px gutter between.... nothing (.lower has only one grid item. grid-gap creates gutters between multiple grid items).
fiddle demo 1
For grid-gap to work among the .upper and .lower siblings you need to apply it to their parent, which must be a grid container.
fiddle demo 2
.grid {
display: grid; /* NEW */
grid-gap: 25px; /* NEW */
}
.upper, .lower {
display: grid;
}
.upper {
grid-template-columns: 1fr 1fr;
grid-gap: 25px;
}
.lower {
grid-template-columns: 1fr;
grid-template-rows: auto;
grid-gap: 10px; /* does nothing unless there are multiple grid items */
}
#media ( max-width:800px ) {
.upper {
grid-template-columns: 1fr;
grid-template-rows: auto;
}
}
.upper > * { border: 1px dashed red; }
.lower > * { border: 1px dashed blue; }
<div class="grid">
<div class="upper">
<div class="a">A</div>
<div class="b">B</div>
</div>
<div class="lower">
<div class="c">C</div>
</div>
</div>