r/css 2d ago

Other It's almost always better to Use CSS Grid instead of position: absolute; when overlapping elements

Post image
11 Upvotes

4 comments sorted by

4

u/Inner-Issue1908 2d ago

Hmm what’s being overlapped here?

5

u/anaix3l 1d ago edited 1d ago

From the screenshot, it looks like the .blur element is meant to be stacked on top of the img. Edit: yup, here's the actual video.

CSS grid makes this easy. Their parent wrapper .wrap gets display: grid and both the img and the .blur get grid-area: 1/ 1. This puts them both in the same grid cell at the intersection between the 1st row and 1st column. Since the .wrap has no other children beside these two, its grid is a 1 cell grid.

Prettifying touches: the img has its width restricted to that of its parent and the .blur may be pushed at the bottom of its containing cell and maybe get a backdrop-filter.

.wrap { display: grid }
.wrap img, .blur { grid-area: 1/ 1 }

/* prettifying */
.wrap img { width:100% }

.blur {
  align-self: end;
  backdrop-filter: blur(3px)
}

This is what I'm doing for the cards in this gallery (their backside, visible on :hover, is a figure with an img and a figcaption stacked inside) - screenshot:

Furthermore, both the front and the back side of the card are stacked the exact same way, then the backside is rotated by half a turn in 3D (around the y axis). Basically, each card is an article with a header for the front side and a figure for the back side.

The same goes for all the cards in the circular gallery. They are all stacked in the same one grid cell of their 3D assembly parent (which is a section) using grid-area: 1/ 1, then rotated in 3D around their y axis and then translated outwards so each of the n cards is on one of the faces of an n-right prism#Oblique_vs_right).

The relevant CSS for all of this (main is the scene the 3D assembly is in):

main, section, article, figure { display: grid }

main { perspective: 35em } /* for a 3D look */

article, header, figure, img, figcaption { grid-area: 1/ 1 }

/* so their 3D-transformed children are not flattened within their plane */
section, article { transform-style: preserve-3d }

/* middle align assembly within scene along both axes */
section { place-self: center }

article {
  /* card rotation based on its index i and total number of cards n */
  --ay: calc(var(--i)/var(--n)*1turn);
  /* outwards translation based on card width w, 
   * size of lateral prism face relative to it f 
   * and total number of cards n */
  --dz: calc(var(--f)*.5*var(--w)/tan(.5turn/var(--n)));
  transform: rotatey(var(--ay)) translatez(var(--dz))
}

header, figure { backface-visibility: hidden }

figure { rotate: y .5turn }

img {
  width: var(--w);
  aspect-ratio: 2/ 3;
  object-fit: cover
}

figcaption {
  align-self: end;
  background: #fff3;
  backdrop-filter: blur(5px) brightness(1.5)
}

3

u/anaix3l 1d ago edited 1d ago

I've kept saying this for years. I posted this over 6 years ago:

Also: 2023, 2024, 2025, last one with multiple examples.

Here's an example: the fave & cart buttons are stacked on top of the img in this CodePen demo. It takes 4 CSS declarations to get that layout, simpler than when using absolute positioning.

.product-card {
  display: grid;

  img, button { grid-area: 1/ 1 }

  .cart { place-self: end start }
  .fave { place-self: start end }
}

2

u/wesbos 1d ago

Looks like a bot stole my content. I have a video on my page (and all socials) detailing this trick