CSS Grid Margin Top for entire columns - css

Is it possible to shift all 2nd/even grid colums as a whole like in the image using CSS grid?
My current css code situation is very simple, it looks like this:
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 24px;
I am trying to achive something that looks like the following image:

You can use the :nth-child() pseudo class to achieve this. This is how I approached it:
<div class="container">
<div class="cards">
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
</div>
</div>
.container{
max-width: 900px;
margin: 0 auto;
height: auto;
}
.cards{
display: grid;
place-items: center;
grid-template-columns: repeat(4,1fr);
gap: 5px;
}
.card{
width: 200px;
height: 250px;
border: 3px solid black;
}
.card:nth-child(2n-2){
position: relative;
top: 100px;
}
/* or use margin */
/*
.card:nth-child(2n-2){
margin-top: 100px;
}
*/
Here is the codepen link: https://codepen.io/glenhug/pen/QWrWXJY
Also this is post had a nice explanation: How to target a specific column or row in CSS Grid Layout?

This might do the trick.
.grid-container {
width: min-content;
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-gap: 10px;
}
.grid-container > div {
width: 50px;
height: 50px;
border: 1px solid black;
}
.grid-container div:nth-child(2n) {
position: relative;
top: 15px;
}
<div class='grid-container'>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>

Not with CSS grid but combining inline-block, float and shape-outside you can do it and it will be responsive and works with any element.
Find all the details in my article: https://css-tricks.com/hexagons-and-beyond-flexible-responsive-grid-patterns-sans-media-queries/
Here is a demo:
.main {
display:flex;
--s: 100px; /* size */
--r: 1; /* ratio */
--mv: 4px; /* margin */
--vc: calc(var(--s) * var(--r) * .5);
--mh: calc(var(--mv) + var(--s)/2);
--f: calc(2*var(--s)*var(--r) + 4*var(--mv) - 2*var(--vc) - 2px);
}
.container {
font-size: 0; /*disable white space between inline block element */
}
.container div {
width: var(--s);
margin: var(--mv) var(--mh);
height: calc(var(--s)*var(--r));
display: inline-block;
font-size: initial;
background: red;
margin-bottom: calc(var(--mv) - var(--vc));
}
.container div:nth-child(odd) {
background: green;
}
.container::before {
content: "";
width: calc(var(--s)/2 + var(--mh));
float: left;
height: 135%;
shape-outside: repeating-linear-gradient(
#0000 0 calc(var(--f) - 2px),
#000 0 var(--f));
}
<div class="main">
<div class="container">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>

Related

Responsive checkerboard grid in CSS?

This snippet contains a responsive grid. As you change the screen width the number of columns varies automatically. Sometimes there is an even number of columns, sometimes there is an odd number. When there is an odd number of columns, the cells alternate colours like a checkerboard, but when there is an even number of columns, they do not. Is there any way to achieve the checkerboard effect for even numbers of columns as well as odd numbers? Does it require Javascript, or can it be done using CSS alone?
body {
margin: 0;
}
.checkers {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(8em, 1fr));
padding: 1em;
gap: 1em;
}
.checkers>div {
background-color: red;
aspect-ratio: 1/1;
}
.checkers>div:nth-child(even) {
background-color: blue;
}
<div class="checkers">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
If you can omit the use of 1fr and consider fixed width elements, you can do this using some background trick:
.checkers {
display: grid;
grid-template-columns: repeat(auto-fit, 8em);
padding: 1em;
gap: 1em;
position: relative; /* Relative on the main container */
z-index:0;
}
.checkers > div {
aspect-ratio: 1;
clip-path: inset(0); /* clip the pseudo element to element*/
}
.checkers > div:before {
content:"";
position: absolute;
z-index:-1;
inset: 1em; /* same as padding */
/* create a checkboard pattern using gradient
18em = (8em + 1em[gap])*2
*/
background: repeating-conic-gradient(red 0 25%,blue 0 50%) 0 0/18em 18em;
}
body {
margin: 0;
background: pink;
counter-reset: num;
}
.checkers div:after {
content: counter(num);
counter-increment: num;
color:#fff;
font-weight:900;
font-size: 25px;
}
<div class="checkers">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
As far as I can tell, this cannot be done for an even number of columns. What you can do is ensure there is always an odd number of columns. You will need to explicitly set an odd number of columns for grid-template-columns, which can be adjusted with media queries.
In this snippet I have borrowed the breakpoints from Bootstrap as a starting point. I have initially set the grid to have 3 columns minimum (grid-template-columns: repeat(3, 1fr);), then increment by 2 (next odd number) at each breakpoint up to 13 columns:
body {
margin: 0;
}
.checkers {
display: grid;
grid-template-columns: repeat(3, 1fr);
padding: 1em;
gap: 1em;
overflow: hidden;
}
.checkers>div {
background-color: red;
aspect-ratio: 1/1;
}
.checkers>div:nth-child(even) {
background-color: blue;
}
#media (min-width: 576px) {
.checkers {
grid-template-columns: repeat(5, 1fr);
}
}
#media (min-width: 768px) {
.checkers {
grid-template-columns: repeat(7, 1fr);
}
}
#media (min-width: 992px) {
.checkers {
grid-template-columns: repeat(9, 1fr);
}
}
#media (min-width: 1200px) {
.checkers {
grid-template-columns: repeat(11, 1fr);
}
}
#media (min-width: 1400px) {
.checkers {
grid-template-columns: repeat(13, 1fr);
}
}
<div class="checkers">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
You can adjust the breakpoint sizes to be multiples of your grid square sizes to get it dialed in to your liking.

Elements with rounded corners - how to detect specific elements to give them a special style?

I have kind of a strange layout - the boxes should have rounded corners as if they were one big element (see image with 4 examples). Problem is the boxes are made dynamically so the rows and columns can vary. And so the fun starts. I started with giving the first and the last box a rounded corner, after this counting (nth) - but I can't wrap my head around how to do this with different rows. Tried everything like "tnh-last-child(3)" (does not work if last "row" has only 2 boxes) or "nth-child(3n+1)" but then there is a problem when i have more than 2 "rows" (I mean there are no "rows" [would be great] - only columns). Any idea?
// First and last
&:first-of-type {
border-top-left-radius: 30px;
}
&:last-of-type {
border-bottom-right-radius: 30px;
}
&:nth-of-type(3) {
border-top-right-radius: 30px;
}
Here is a fiddle: https://codepen.io/herrfischer/pen/eYEyRQp
section {
display: flex;
flex-wrap: wrap;
justify-content: left;
width: 400px;
}
section div {
width: 30%;
margin: 5px;
height: 100px;
background-color: grey;
}
section div:first-of-type {
border-top-left-radius: 30px;
}
section div:last-of-type {
border-bottom-right-radius: 30px;
}
section div:nth-of-type(3) {
border-top-right-radius: 30px;
}
.red {
background-color: red;
}
<h1>Red box should always have a rounded corner in the bottom left.</h1>
<h2>Example A</h2>
<section class="a">
<div></div>
<div></div>
<div></div>
<div class="red"></div>
<div></div>
<div></div>
</section>
<h2>Example B</h2>
<section class="b">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div class="red"></div>
<div></div>
</section>
<h2>Example C</h2>
<section class="b">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div class="red"></div>
</section>
<h2>Example D</h2>
<section class="b">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div class="red"></div>
<div></div>
<div></div>
</section>
You can combine nth-child selectors. This will match with only one item.
&:nth-child(3n + 1):nth-last-child(3),
&:nth-child(3n + 1):nth-last-child(2),
&:nth-child(3n + 1):last-child {
border-bottom-left-radius: 30px;
}
section {
display: flex;
flex-wrap: wrap;
justify-content: left;
width: 400px;
}
section div {
width: 30%;
margin: 5px;
height: 100px;
background-color: grey;
}
section div:first-child {
border-top-left-radius: 30px;
}
section div:last-child {
border-bottom-right-radius: 30px;
}
section div:nth-child(3) {
border-top-right-radius: 30px;
}
section div:nth-child(3n+1):nth-last-child(3),
section div:nth-child(3n+1):nth-last-child(2),
section div:nth-child(3n+1):last-child {
border-bottom-left-radius: 30px;
}
.red {
background-color: red;
}
<h1>Red box should always have a rounded corner in the bottom left.</h1>
<h2>Example A</h2>
<section class="a">
<div></div>
<div></div>
<div></div>
<div class="red"></div>
<div></div>
<div></div>
</section>
<h2>Example B</h2>
<section class="b">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div class="red"></div>
<div></div>
</section>
<h2>Example C</h2>
<section class="b">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div class="red"></div>
</section>
<h2>Example D</h2>
<section class="b">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div class="red"></div>
<div></div>
<div></div>
</section>

Add an overlay div inside nested flex containers (3x3 grid) in a specific cell

I have a 3x3 grid with flex-box concept, inside of each cell it has another 3x3 grid.
I was trying to put an Overlay over the Inner grid in one cell, but I didn't find how to do it.
I found some examples like this one
Overlay / hover a div in flexbox container div
but it don't work in nested flex-box, or I don't know how to set them up.
here is the html, the grid has just two cell to take up less space, it actually is done with JQuery but for the example lets use only 2.
.Region{
position: absolute;
top: 10px;
left: 10px;
width: 500px;
height: 500px;
border: 5px double black;
display: flex;
}
.FlexContainer{
display: flex;
flex-direction: column;
flex-grow: 1;
}
.FlexContainer > div{
flex-grow: 1;
flex-basis: 0;
border: 3px solid blue;
display: flex;
flex-direction: row;
margin: 5px;
}
.FlexContainer > div > div{
flex-grow: 1;
flex-basis: 0;
border: 1px solid red;
margin: 3px;
display:flex;
flex-direction: row;
}
.Overlay{
position: absolute;
width: 100%;
height: 100%;
background-color: rgba(013, 130, 230, 0.5);
cursor: not-allowed;
}
<div class="Region">
<div class="FlexContainer">
<div>
<div>
<div class="FlexContainer">
<div>
<div></div>
<div></div>
<div></div>
</div>
<div>
<div></div>
<div></div>
<div></div>
</div>
<div>
<div></div>
<div></div>
<div></div>
</div>
</div>
</div>
<div></div>
<div></div>
</div>
<div>
<div></div>
<div></div>
<div></div>
</div>
<div>
<div>
<div class="FlexContainer">
<div class="Overlay"></div>
<div>
<div>
</div>
<div></div>
<div></div>
</div>
<div>
<div></div>
<div></div>
<div></div>
</div>
<div>
<div></div>
<div></div>
<div></div>
</div>
</div>
</div>
<div></div>
<div></div>
</div>
</div>
</div>
I have tried with the Overlay inside and outside the Inner FlexContainer, but didn't work.
Finally got it to work, indeed the parent container must have relative position for it to work, so there is two change, one in the FlexContainer and other in the Overlay
.FlexContainer{
position:relative; <-- ADD THIS
display: flex;
flex-direction: column;
flex-grow: 1;
}
.FlexContainer .Overlay {
position: absolute;
top: 0px;
left: 0px;
margin: 0px;
border: 0px;
width: 100%;
height: 100%;
background-color: rgba(013, 130, 230, 0.5);
cursor: not-allowed;
}
Code Pen solution https://codepen.io/anon/pen/dKaXqg
Credits to user Pogany from the css-tricks web site
CSS-TRICKS thread: https://css-tricks.com/forums/topic/add-and-overlay-div-in-nested-flex-box-container/#post-273437

how to lineup css boxes?

I have been busting my butt, just to lineup my pics in css boxes
here is the code(and the screen shop of result) its in the blade(laravel5) :
Here is my code:
#foreach($users as $user)
<div style="width: 200px;height: 200px;background-color: gray;text-align: center; float: right; margin-bottom: 22px;
margin-right: 17px;
">
<img src="{{$user->getavatar()}}" alt="{!!$user->username!!}" >
<strong>{!!$user->username!!}</strong>
</div>
<br>
#endforeach
Let's try another method using display instead of using float, and remove the <br>. How does this look?
<div style="width: 200px; height: 200px; text-align: center; display: inline-block; vertical-align: top; margin: 0 10px 22px;">
<img src="{{$user->getavatar()}}" alt="{!!$user->username!!}" >
<strong>{!!$user->username!!}</strong>
</div>
Remove the <br> tag at the end of the foreach loop.
You can put all your foreach loop divs inside a div container and use display:flex. It is better not to use css inline with yout html code(It looks heavy), also <br> is not needed there.
Please review this one:
#container {
display: flex;
flex-wrap: wrap;
padding: 50px;
}
#container div {
height: 200px;
width: 200px; /*or using calc(100% / 6);*/
background-color: gray;
text-align: center;
flex-grow: 0;
margin-bottom: 22px;
margin-right: 17px;
}
<div id="container">
<!--sample result of your foreach loop-->
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<!--end foreach-->
</div>

CSS fixed size margin only between elements

This keeps coming up on certain projects and I wanted to see if anyone may have a better solution.
Essentially, I'm trying to have a group of div elements of which all have an equal amount of spacing between them but not around. The snippet below is an example of what I'm looking for, my hope is someone may have a cleaner solution.
My question here is if anyone has a better solution that may use less css or less HTML elements. The important things to maintain:
Localization compliant - Since we aren't using margin left or right there aren't any weird localization issues in rtl
Alignment - It shouldn't size to the whole window if it doesn't need to but it should wrap if needed. (see example)
Spacing - Should be a fixed amount of space between the elements
If you have any ideas I'd love to hear them!
body {
background-color: black;
padding: 30px;
}
.inner {
overflow: hidden;
margin: 20px 0px;
}
.innerMargin {
background-color: white;
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin: -10px;
}
.innerMargin > div {
flex: 0 0 20px;
background-color: red;
margin: 10px;
height: 20px;
width: 20px;
}
.fixedWidth {
width: 180px;
}
<div class="inner">
<div class="innerMargin">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
<div class="inner fixedWidth">
<div class="innerMargin">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
I think it should be noted this is trivial with CSS Grid.
body {
background-color: #000;
}
.container {
display: grid;
grid-template: 20px/repeat(auto-fit, 20px);
grid-gap: 20px;
background-color: #FFF;
margin: 20px;
}
.container div {
background-color: red;
}
.fixed-width {
width: 180px;
}
.container > div {
background-color: red;
}
<div class="container">
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
</div>
<div class="container fixed-width">
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
</div>
CodePen here
Necromancing, but I'd like to add that a pretty quick way to accomplish this if you're just dealing with a row/column is to use a last-child pseudoselector to override margin to 0. Like so:
.column-item {
width: 5px;
height: 5px;
background-color: red;
margin-bottom: 20px;
}
.column-item:last-child {
margin: 0;
}
beginning
<div id="column">
<div class="column-item"></div>
<div class="column-item"></div>
<div class="column-item"></div>
<div class="column-item"></div>
<div class="column-item"></div>
<div class="column-item"></div>
<div class="column-item"></div>
</div>
end
If you know you will always have 5 boxes in the fixedwidth box, you could do something like:
HTML (Slim)
.container
- 5.times do
.box
.container.container--thinner
- 15.times do
.box
CSS (SCSS)
$width : 36;
body {background-color: #000;}
.container {
display:flex;
flex-wrap: wrap;
background-color: white;
margin-bottom: 2em;
width: $width + em;
.box {
width: 2em;
height: 2em;
margin-right: 2em;
background-color: red;
}
&--thinner {
justify-content: space-between;
width: $width/2 + em;
.box {
margin-bottom: 2em;
&:nth-of-type(5n) {
margin-right: 0;
}
}
}
}
Here's a Codepen

Resources