[SOLVED] Can't figure out how to do this layout with css grids and `aspect-square`...

Im trying to make a card with the following layout. the main requirement is that the red box should be a square, with an icon/logo inside. this will be a 2x2 grid. the red square should have the same height/width as the blue cell's height, so if the blue cell gets bigger, the red square will size accordingly the pink cell is essentially blank, but will have the same height as the yellow. the yellow cell height will change dynamically based on the content. sorry if this is confusing, maybe this will clarify:
-RED width should match RED height (square)
-RED height should match BLUE height
-BLUE height should match child content height (auto)
-BLUE width should be full width (auto) aka remainder of the space
-PINK height should match YELLOW height (auto)
-PINK width should match BLUE width
-YELLOW height should match child content height (auto)
-YELLOW width should match BLUE width
-RED width should match RED height (square)
-RED height should match BLUE height
-BLUE height should match child content height (auto)
-BLUE width should be full width (auto) aka remainder of the space
-PINK height should match YELLOW height (auto)
-PINK width should match BLUE width
-YELLOW height should match child content height (auto)
-YELLOW width should match BLUE width
so far, im somewhat able to get it working, but am facing clipping/overlapping issues on smaller devices. AI told me it has something to do with aspect-square or something, but visually in my head, it should be fine. or should I just switch to using flexbox? here is some code: https://pastebin.com/Ba8yc8Ma
Pastebin
```js <div className={cn( "grid grid-rows-2 border", "...
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
No description
No description
115 Replies
ἔρως
ἔρως3mo ago
what's the size of the square, in pixels?
Bingo Bandit
Bingo BanditOP3mo ago
it should be based on the height of the blue cell, which will have a line of text (title), so essentially it will be the font-size that is set in the blue cell
ἔρως
ἔρως3mo ago
then you want the columns to be 1fr auto and the rows 1fr auto and set the aspect ratio to 1:1 if you always want a square
Bingo Bandit
Bingo BanditOP3mo ago
i tried that but still get the clipping issue :/ thanks for the help though, your solution is very similar to the one in my pastbin link, and i had tried that first before posting
Chris Bolson
Chris Bolson3mo ago
surely the columns should be the other way round, auto 1fr so that the logo column is only wide as needed whilst maintaing the square aspect ratio 🤔
Bingo Bandit
Bingo BanditOP3mo ago
i feel like i tried all those combinations and couldn't achieve my desired result... ive spent hours and hours trying to figure this out but it seems like an issue with aspect-square conflicting with css grid my google fu shows only results where the entire grid and its cells are square, or ratios like 2:1 or 3:1 etc
Chris Bolson
Chris Bolson3mo ago
I pasted your code into tailwind play, adjusted the grid-col definition to grid-col-[auto_1fr] and it worked as I believe your are descrobing. The red box maintains it's aspect ratio of 1/1 as the height increases according to the h3 font size increased https://play.tailwindcss.com/S6w1OC6wJo
ἔρως
ἔρως3mo ago
i always mess up the order :/
Bingo Bandit
Bingo BanditOP3mo ago
hmm ok i changed font to 7xl, and the red square does not scale to match
No description
Bingo Bandit
Bingo BanditOP3mo ago
here is the closest i've gotten
<div className="grid grid-cols-[min-content_1fr] grid-rows-[min-content_1fr] bg-[var(--base-2)] border border-[var(--base-4)] transition-all duration-500 hover:border-[var(--base-6)] group">
<div
id="logo"
className="aspect-square flex items-center justify-center bg-[var(--base-3)]"
>
{currentLogo && (
<div
className="h-4/5 w-4/5 bg-[var(--base-12)] cheese:bg-[var(--accent-9)]"
style={{
maskImage: `url(${currentLogo})`,
WebkitMaskImage: `url(${currentLogo})`,
maskSize: "contain",
maskRepeat: "no-repeat",
maskPosition: "center",
}}
/>
)}
</div>
<div
id="title"
className="flex items-center px-8 py-6 bg-[var(--base-1)] border-l border-[var(--base-4)]"
>
<H3 className="text-[var(--base-12)] font-normal tracking-tight leading-tight">
{title}
</H3>
</div>
<div
id="blank"
className="bg-[var(--base-3)] border-t border-[var(--base-4)]"
/>
<div
id="description"
className="px-8 py-6 flex items-start bg-[var(--base-1)] border-l border-t border-[var(--base-4)]"
>
<P className="text-[var(--base-10)] font-light leading-relaxed text-sm">
{description}
</P>
</div>
</div>
<div className="grid grid-cols-[min-content_1fr] grid-rows-[min-content_1fr] bg-[var(--base-2)] border border-[var(--base-4)] transition-all duration-500 hover:border-[var(--base-6)] group">
<div
id="logo"
className="aspect-square flex items-center justify-center bg-[var(--base-3)]"
>
{currentLogo && (
<div
className="h-4/5 w-4/5 bg-[var(--base-12)] cheese:bg-[var(--accent-9)]"
style={{
maskImage: `url(${currentLogo})`,
WebkitMaskImage: `url(${currentLogo})`,
maskSize: "contain",
maskRepeat: "no-repeat",
maskPosition: "center",
}}
/>
)}
</div>
<div
id="title"
className="flex items-center px-8 py-6 bg-[var(--base-1)] border-l border-[var(--base-4)]"
>
<H3 className="text-[var(--base-12)] font-normal tracking-tight leading-tight">
{title}
</H3>
</div>
<div
id="blank"
className="bg-[var(--base-3)] border-t border-[var(--base-4)]"
/>
<div
id="description"
className="px-8 py-6 flex items-start bg-[var(--base-1)] border-l border-t border-[var(--base-4)]"
>
<P className="text-[var(--base-10)] font-light leading-relaxed text-sm">
{description}
</P>
</div>
</div>
but it still has clipping issues
Bingo Bandit
Bingo BanditOP3mo ago
No description
Bingo Bandit
Bingo BanditOP3mo ago
https://play.tailwindcss.com/tiJndHlMcI argh so doesnt seem to make a difference
Tailwind Play
Tailwind Play
An advanced online playground for Tailwind CSS that lets you use all of Tailwind's build-time features directly in the browser.
No description
Bingo Bandit
Bingo BanditOP3mo ago
1) clipping, 2) pink space not match red cell width
ἔρως
ἔρως3mo ago
why are you forcing grid children to be flex?
Bingo Bandit
Bingo BanditOP3mo ago
bc i want the heights/widths to match/line up properly i've always heard the saying "if it looks like a grid, use grid" if i used flex then i'd have to make some janky spacer for the pink cell/spacer cell to match the red cell above i thought about using flex but i think that might just be a hacky way
13eck
13eck3mo ago
Here's my attempt at it, with some video to show it working. It uses some JS, though, to get the height of the blue area and set the red square to that width/height: https://codepen.io/13eck/pen/myegado
Bingo Bandit
Bingo BanditOP3mo ago
AHHH ok tysm, i briefly had the idea to implement js and thought i should prob do so, but never gave it much more thought
13eck
13eck3mo ago
It's not perfect, but it works. And if you want the red area to stay a square based on the height of the blue area you'll want to listen to the window's resize event to re-run the adjustSizes function.
Bingo Bandit
Bingo BanditOP3mo ago
dang i was hoping there was a css only method... there has to be an easier way but i guess css is still in constant dev
13eck
13eck3mo ago
Not everything has a CSS-only way of doing things. If you want dymanic anything, JS is still the way to go And really, you shouldn't shy away from JS in 2025, it's not like we're back in 2012 where some people (unironically) have JS turned off. Or that browsers had different JS implemenations/API :p
Bingo Bandit
Bingo BanditOP3mo ago
i'll give this method a shot. thanks again, this is the way agreed!
13eck
13eck3mo ago
Just made a quick change to add auto-resize based on viewport size
13eck
13eck3mo ago
Chris Bolson
Chris Bolson3mo ago
Thats strange, it does change when I changed the font size
No description
Chris Bolson
Chris Bolson3mo ago
(I realize that the conversation has moved on since then)
ἔρως
ἔρως3mo ago
is there any reason why this can't be a fixed width? from what i see, it's for an icon and then it's wasted space for decoration
13eck
13eck3mo ago
the red square should have the same height/width as the blue cell's height, so if the blue cell gets bigger, the red square will size accordingly
–OP
ἔρως
ἔρως3mo ago
i get that, but why?
13eck
13eck3mo ago
I assume it's due to the "blue cell" being a header of some kind and for responsive reasons based on viewport
ἔρως
ἔρως3mo ago
(i am challenging the request) okay, but then why does the red have to be a square?
13eck
13eck3mo ago
C-suite says so :p
ἔρως
ἔρως3mo ago
the smaller the screen, the bigger the red c-suite ... -.-
13eck
13eck3mo ago
The root of all evil, yeah
ἔρως
ἔρως3mo ago
if you want fucking idiotic ideas, ask a c-suite you will have laughing material for days but seriously, forcing it to be a square is just ... not on a phone, i predict 70% is icon and a sliver of barely readable title
Bingo Bandit
Bingo BanditOP3mo ago
lol no the title is gonna be a short 1 liner title, and the icon i want square at match the height of the blue cell
Bingo Bandit
Bingo BanditOP3mo ago
basically like this but it doesnt look right on mobile with clipping issues
No description
No description
13eck
13eck3mo ago
If it's a one-liner that won't change then no need for JS as it should be very simple to know how tall one line of text is lol
Bingo Bandit
Bingo BanditOP3mo ago
yeah but i have the font size responsive based on the device so each breakpoint has a fontsize respective to that screen
ἔρως
ἔρως3mo ago
then you can also set the font size for the symbol
Bingo Bandit
Bingo BanditOP3mo ago
its an svg that im using as a mask so i can change color dynamically idk if that makes any diff
ἔρως
ἔρως3mo ago
why??? just use the svg directly or use a symbol then set the fill to currentColor
Bingo Bandit
Bingo BanditOP3mo ago
bc i have 3 different color themes and dont want to save 3 diff files
ἔρως
ἔρως3mo ago
no need for masks
Bingo Bandit
Bingo BanditOP3mo ago
well still
ἔρως
ἔρως3mo ago
you are overcomplicating
Bingo Bandit
Bingo BanditOP3mo ago
i dont think that matters because there seems to be a conflict with aspect-square and css grids
ἔρως
ἔρως3mo ago
but that's fine
Bingo Bandit
Bingo BanditOP3mo ago
i might be which is why im asking here
ἔρως
ἔρως3mo ago
you can just do auto 1fr and be done with it
Bingo Bandit
Bingo BanditOP3mo ago
what's the issue you're challenging? yes, that works on desktop
ἔρως
ἔρως3mo ago
the need of it being a square
Bingo Bandit
Bingo BanditOP3mo ago
but mobile there is a clipping issue
ἔρως
ἔρως3mo ago
it's horrible on mobile
Bingo Bandit
Bingo BanditOP3mo ago
ok well thanks for trying to help anyway
ἔρως
ἔρως3mo ago
the solution that beck sent does the "red is square" thing, but it's horrible for smaller sizes
Bingo Bandit
Bingo BanditOP3mo ago
yes i'm aware of that and plan do adjust accordingly but if i cant resolve the clipping issue then i can't go from there
ἔρως
ἔρως3mo ago
well, you cant the only solution to keep it as a square on smaller sizes is to overflow or throw text away
Bingo Bandit
Bingo BanditOP3mo ago
i don't see what your issue is with my problem it's been resolved
ἔρως
ἔρως3mo ago
it's the need of it being a square
Bingo Bandit
Bingo BanditOP3mo ago
because it's an icon, i dont want a rectangle container and i want the title to line up with the icon, and the title to line up with the description
ἔρως
ἔρως3mo ago
but it has to always be square, even on smaller screens?
Bingo Bandit
Bingo BanditOP3mo ago
... yes
ἔρως
ἔρως3mo ago
and even when the text wraps?
Bingo Bandit
Bingo BanditOP3mo ago
that's how i want it, man it won't unless your screen width in like 300px the font size of the title scales to smaller devices
ἔρως
ἔρως3mo ago
okay, then beck's solution is too overkill and will fail until the browser downloads, parses and runs the js
Bingo Bandit
Bingo BanditOP3mo ago
the titles are 1 word less than 10 characters
ἔρως
ἔρως3mo ago
then you can just do a fixed size for the first column
Bingo Bandit
Bingo BanditOP3mo ago
probably, but i don't see another solution, i don't want to set a fixed size
ἔρως
ἔρως3mo ago
well, use a variable for the size or use other units there's ch, for example
Bingo Bandit
Bingo BanditOP3mo ago
well setting a variable for the size would be setting a fixed size, wouldnt it?
ἔρως
ἔρως3mo ago
or lh, which is the line height of the text
Bingo Bandit
Bingo BanditOP3mo ago
err i guess em but that's still based on the 16px
ἔρως
ἔρως3mo ago
it's actually based on the parent
Bingo Bandit
Bingo BanditOP3mo ago
ok, well i just want to use aspect-square oh yeah you right, im referring to rem i think
ἔρως
ἔρως3mo ago
you are, yes which usually is medium size, which the spec defines as a default of 16px but users can set it to other values and some browsers may set it to other sizes, like 21px
Bingo Bandit
Bingo BanditOP3mo ago
ok, well i guess i'll use @13eck 's solution until i can figure out an easier solution i dont want to use fixed size bc responsive unless i have a set fixed size for each breakpoint idk ill keep playing around, i spent half the day and all last night thinking of just scrapping the design if i can't get the js to work, or if it breaks like you said
ἔρως
ἔρως3mo ago
i have a solution for you
ἔρως
ἔρως3mo ago
Create a grid layout with background colors - JSFiddle - Code Playg...
JSFiddle - Test your JavaScript, CSS, HTML or CoffeeScript online with JSFiddle.
ἔρως
ἔρως3mo ago
pure css, responsive, the icon is a good size, always square, always centered unless you go too tall then it breaks if you remove the aspect ratio from the 1st div, it will work the font size was from some random generator, and it goes from 20px to 32px - for 16px font sizes
Bingo Bandit
Bingo BanditOP3mo ago
holy crap ok super interesting thanks man im checking it out right now
ἔρως
ἔρως3mo ago
alright
Bingo Bandit
Bingo BanditOP3mo ago
hmm ok i currently have the STUFF h1 as an H3 styled component, so i need a way to pass the font size...
ἔρως
ἔρως3mo ago
it doesnt stay as a square when the title is huge and wraps, but you said it wasnt a concern for you
Bingo Bandit
Bingo BanditOP3mo ago
yeah i think this should work if i can convert this to tsx tailwind or might just need to have its own css file
ἔρως
ἔρως3mo ago
i dont know tailwind, but it may be possible to make it a bit less complex im using padding to align the icon, instead of the normal properties
Bingo Bandit
Bingo BanditOP3mo ago
yea this is some super custom code so i dont think tailwind can handle it any easier
ἔρως
ἔρως3mo ago
and im not using the lh unit, opting for math instead
Bingo Bandit
Bingo BanditOP3mo ago
what is lh stand for
ἔρως
ἔρως3mo ago
1lh = 1x the line height of the element
Bingo Bandit
Bingo BanditOP3mo ago
ahh ok
ἔρως
ἔρως3mo ago
so, if you do line-height: 1.4, the unit 1lh will be the size of that line-height which may be 16px * 1.4
Bingo Bandit
Bingo BanditOP3mo ago
hmm ok this mean i will need to set the styling in this css file... which is no biggie, unless i can pass this styling through
export function H3({ children, className }: Omit<TypographyProps, "as">) {
return (
<Typography
as="h3"
className={cn(
"font-light tracking-[0.015em] leading-[1.1] mb-2 last:mb-0",
"text-[var(--accent-12)]",
"xxxs:text-xl",
"xxs:text-2xl",
"xs:text-3xl",
"selection:bg-[var(--base-3)]",
"transition-all duration-300 ease-out",
className,
)}
cheeseClassName="font-custom letter-spacing-wide text-[var(--accent-9)]"
>
{children}
</Typography>
);
}
export function H3({ children, className }: Omit<TypographyProps, "as">) {
return (
<Typography
as="h3"
className={cn(
"font-light tracking-[0.015em] leading-[1.1] mb-2 last:mb-0",
"text-[var(--accent-12)]",
"xxxs:text-xl",
"xxs:text-2xl",
"xs:text-3xl",
"selection:bg-[var(--base-3)]",
"transition-all duration-300 ease-out",
className,
)}
cheeseClassName="font-custom letter-spacing-wide text-[var(--accent-9)]"
>
{children}
</Typography>
);
}
ἔρως
ἔρως3mo ago
im using the line height as a poor-man's alignment to sorta align in the middle-ish of the first line
Bingo Bandit
Bingo BanditOP3mo ago
ok, ill give this a shot, was struggling with the js for now
ἔρως
ἔρως3mo ago
i can see that being a pain and a half
Bingo Bandit
Bingo BanditOP3mo ago
thank ya
ἔρως
ἔρως3mo ago
you're welcome
Bingo Bandit
Bingo BanditOP3mo ago
yea i think i just need to create its own css file for this component with its own h3 styling to match
ἔρως
ἔρως3mo ago
by the way, you may want to add > before all the divs, in the css i wrote it for this specific example only
Bingo Bandit
Bingo BanditOP3mo ago
whats that do
ἔρως
ἔρως3mo ago
btw, can you change the html? it's the direct child descendent
Bingo Bandit
Bingo BanditOP3mo ago
yeae i can change it i have to hit run
ἔρως
ἔρως3mo ago
... you can make this 2000x less complicated
Bingo Bandit
Bingo BanditOP3mo ago
please tell me how
ἔρως
ἔρως3mo ago
use an <article> for the card thingy then use an <header> for it im not sure if you can use a <main> inside an article, but a <div> will do
Bingo Bandit
Bingo BanditOP3mo ago
after like the 10th hour of troubleshooting i thought i should find a way to do that lol
ἔρως
ἔρως3mo ago
i will make an example
Bingo Bandit
Bingo BanditOP3mo ago
isnt article and header just like a div, except for the screen reader stuff
ἔρως
ἔρως3mo ago
no it's a semantically different thing it indicates that this is some content that stands on it's own, from the rest of the page im using an article because it seems to make sense to me
Bingo Bandit
Bingo BanditOP3mo ago
ok
ἔρως
ἔρως3mo ago
okay, i have simplified a lot
ἔρως
ἔρως3mo ago
Edit fiddle - JSFiddle - Code Playground
JSFiddle - Test your JavaScript, CSS, HTML or CoffeeScript online with JSFiddle.
Bingo Bandit
Bingo BanditOP3mo ago
thanks my friend
ἔρως
ἔρως3mo ago
you're welcome

Did you find this page helpful?