0:00:00 Hey, what’s up everybody?
Welcome back to the channel. I’m in a chipper mood.
I will just be, let me just be up front with you. Okay.
This is about the 10th time I’ve tried to record this intro. I haven’t even gotten into the tutorial yet.
I’m just trying to get through the intro. I can’t talk today.
I don’t know what it is, but I just decided it’s got to get done. It’s got, I gotta, I gotta quit hitting stop.
I gotta quit hitting rerecord and I just got to get through it, whatever it takes. Okay.
In order to help with that, I’m just going to go right into screen sharing mode, get my face off the freaking screen. All right.
So what we have is a basic three column grid, six cards, nice and even good. It needs some work though.
Our designer friend wants us to put rules or borders or lines, whatever you guys want to call them inside the grid between all the elements. So rows and columns, but nothing on the outside, nothing on the top, nothing on the bottom, nothing on the outside.
And it’s gotta check some very important boxes. And this takes me into the context of why we’re doing this particular training right now.
There isn’t really a designer who gave me anything, though I did want to achieve this concept on a site recently. And I looked around at how other people approach it, and I did not find any solutions that check these important boxes that we’re about to talk about.
And they certainly didn’t check the box of scalability or maintainability or flexibility, right? Breakage.
What I saw was solutions that would easily break in various scenarios. inner circle, 1,300 developers, designers, agency owners, premium community, right?
We deep dive lots of great development stuff, best practices on development and design and business, really, really good community. One of the segments that we do in that community is called Pop Quiz.
What I do at Pop Quiz is I, it could be beginner, intermediate, advanced, I get a scenario, I say, hey, here’s the scenario, here’s the important boxes we need to check, go. And they gotta provide code for how to achieve that scenario, checking all the boxes, right?
And from this, first of all, it’s very entertaining. We have a lot of fun with it.
It also teaches people a lot and it helps you practice and work through in your mind various scenarios while thinking about all the really important stuff. It’s not just, hey, can I achieve the look?
It’s like, how can I achieve the look in the best possible fashion? And this is one of the scenarios where I was actually doing the pop quiz with my community.
I didn’t have the solution for this when I posted the pop quiz. I was gonna do it, and I did it, and I tried a lot of different things, okay?
And I ran into a lot of roadblocks. And what I’m gonna teach you in this training is the ultimate solution that I came up with.
And I think it is the best solution, but I do wanna challenge you because there’s gonna be gazillions of people watching this. If you come up with a better solution than me, please share it.
I would love to see it. I’m challenging you.
I don’t think you can. I don’t think you can.
I think my solution is the best solution, but if perhaps you find a better solution, definitely share it. Let me see it, okay?
So let’s talk about the boxes that we need to check when we do this. What are the boxes?
Well, first of all, no media queries. I don’t wanna use media queries.
Nobody wants to manage media queries. That’s not fun, that’s not exciting, not particularly maintainable or elegant or scalable.
Like, if they don’t have to be there, why would you put them there? So let’s try to do this without media queries.
What about any column count, right? Right now, this is a three-column grid.
And a lot of people in the pop quiz, I’m gonna tell you right now, they approach this challenge as if all grids are three columns. We know in development land that all grids are not three columns.
We could maybe say, hey, we want a two column grid. So I’m gonna hit save.
Hey, now we got a two column grid. Did your solution just break?
If it did, that to me is a big problem. What if we went four columns?
Did your solution break? If it did, that’s kind of a problem.
What if you went auto fit or auto fill on this, right? Did your solution break?
Hey, if it did, that’s a problem. I want a solution that works regardless of the column count, which also means I have to avoid inf selectors.
I want to avoid inf selectors when possible in a situation like this, because those aren’t fun either. If I don’t need them, why would I use them?
Is there a better way? That’s kind of a question.
It’s a box we’re trying to check. And then does it work with any number of grid items?
If I drop a grid item so that we have an uneven number of items, will my solution break? If it does, not a great solution.
That’s a box I need to check. And then it works with any background.
I saw some people submitting a solution where they put a background color on the grid, and then they put a background color on the cards. The card background color matches the body background color and then they just use it like a one or two pixel gap to create the lines and that absolutely
0:05:01 works.
0:05:02 It absolutely works except for when there’s an uneven number of grid items and then that solution totally falls apart.
And so we can’t go with that one either, right? So what are we going to do that’s what we’re gonna learn in this video and we’re gonna learn it right now so stick with me first what is the setup I’ve got a basic three column grid it is repeat three min max 0 1 FR align item stretch ensures that all grid items are equal height that’s all we’ve done now we’re gonna build up from here step by step to get to our ruled grid solution.
Okay? So the first thing I want to do is I want to come down to ruled grid and then I’m selecting all cards that are direct children of ruled grid.
And I’m going to do something with those. The first thing I’m going to do with them is position relative.
Why? Because I want to use pseudo elements and I want to absolutely position those pseudo elements.
For those of you who are thinking in your mind, oh, we’re absolutely gonna use borders for this. No, no, we’re gonna use zero borders.
We’re gonna use pseudo elements for everything, okay? So I wanna position the card relative, that’s gonna allow me to attach pseudo elements to the card that are absolutely positioned, okay?
So what I’m gonna do now is I’m gonna come down to row lines and I’m going to say, hey, in our ruled grid, we have cards and I want to attach an after element to every single card. See I can’t use int.
I’m not going to say attach these to the third card in the grid. Well, why can’t I do that?
Because that requires me to know how many columns there are. And I already said this needs to work with any columns.
We can’t use int. We’ve got to avoid int.
So I said to myself, well, if we want something that works in every scenario, why don’t we attach the solution to every card, right? That kind of makes sense, right?
Okay, so let’s get after this. What do we need?
We need a blank content property. That’s always the first thing you need when you’re defining a pseudo element.
The next thing that we need is a background color, okay? This is actually going to be the line color.
So I’m going to just stick a red value in here And I just want to see a line on the page. Okay, and then we’re going to talk about Building in more scalability and maintainability and flexibility here.
Okay, so the background color is red What I need now is to position this like I mentioned Absolutely. I also need dimensions on this pseudo element.
So because these are going to be the row lines, I want them to be wide. What do I want the width to be?
Well, let’s just start with 100%. We’re not going to stay with 100%, but we’re going to start with 100% just so we can see something.
Now it’s 100% wide. How tall is it going to be?
The height needs to determine the thickness of the line. Okay.
We’re going to rock with two pixels for right now. And you’re going to see the row lines show up instantly.
There are my row lines right there. Now, there’s no gap in this grid, so the lines are touching.
That’s something we have to be careful about. This is why 100% is not going to work.
But again, I wanna walk you through some of this thinking. And so you can see this solution build up before your very eyes.
It’s a little bit unintuitive of a solution, okay? And it requires a slight magic trick at the very end, but you’re gonna love it.
You’re absolutely gonna love it. Okay, and it’s super super super elegant and efficient and scalable and maintainable and it checks every single box in this grid that we are trying to check.
Okay? All right, so we’ve got width of 100%, height of 2 pixels.
The only thing now is I actually want to attach these row lines to the top of the cards, not the bottom of the cards. So what I’m going to say is top zero.
And then I also want to make sure that they are attached to the left side of the cards. So here is my row code right here.
Now what I’m going to do is I’m going to make my column code. All right, so we’re going to come down here and for the columns I’m going to use the before element, right?
I can’t use after again, it’s already been used. I’m now going to use the before element.
Remember, if you don’t know much about pseudo elements or you’re a beginner, you only get two pseudo elements per main element, per parent element, right? You get a before and you get an after, that’s all you get.
So I’m using both of them because we need to use both of them. I just need to make some slight changes here, right?
This is think columns now, the width is no longer a hundred percent guys. What is the width?
The width is the thickness of the line. So I’m going to put a two pixel right here.
The height now is full. So I’m going to go with 100%.
So we’re going to say height. We’re going to say 100%.
Now the other thing that we’re not doing so far is we’re not using logical properties. We need to convert all of these to logical properties.
We’re going to do that at the end because I don’t want to get beginners and maybe even intermediate people confused right now. We will do that conversion at the very very end.
What I do want to take a look at is what we’ve got currently as our solution and you can see that it’s starting to get there. We have a big problem in the fact that we have a top rule, a top ruler, right?
Do you call us a ruler, a rule? What do you call this, a border?
I’m just gonna call them lines, okay? So we have a top line, which we obviously don’t want.
We have a left line, which we obviously don’t want. And I think this is why a lot of people would abandon this kind of solution, because they can see, hey, if I attach these to every card, I’m gonna get these in places that I don’t want.
Then you said, Kevin, I can’t use inf selectors. How am I gonna remove the lines from certain cards?
Like, what? I’m, people just got stuck.
Everybody got stuck, right? Okay, so let’s just keep going.
First thing I want to talk about is getting these lines in the right position. They, they can’t just be attached to the side of the card or the top of the card.
They have to be perfectly centered in the gap that’s going through the grid. Right now, this grid doesn’t even have a gap.
So let’s go up here and let’s say gap of 2M. And let’s add that, oh no, look at what just happened.
Everything that we were doing just broke. Except, except, it’s fixable.
We don’t have to go backwards here. We don’t have to completely change our strategy.
This is a fixable scenario. So just stay with me.
We’re gonna keep working. I am noticing, however, like I just mentioned, see this this column line?
It doesn’t work when it’s glued to the side of the card. There’s a gap, a channel running right through here.
There are actual physical columns in this gap or in this grid. I need to position the line dead center in that gap.
OK, if I know my gap is 2M, where would the dead center of 2m be? The dead center of 2m will be half of 2m, which is equal to 1m.
So I’m gonna show you something. If I do left minus 1m, watch what happens to our, oh, I’m sorry, that was our, let’s go left of zero, that was our row, let’s go to our column.
So left of minus 1m, look at this line jump dead center into the gap. Now I kind of need to do that with my top lines as well.
I need them to move up, right, on the block axis. I need them to move up minus one M.
So their top is minus one M. Watch them jump into the middle of the gaps.
That is really, really, really important. Now the problem is, and guys, if you have watched any of my videos, right now alarms should be going off in your mind.
This should be driving you mad. The fact that I’m throwing static values everywhere and not tokenizing the styling.
I know a lot of you are like trembling right now. Okay.
We’ve got to fix this situation. I’ve got a minus one in here.
I got a minus one in here. I’m repeating myself.
What is our principle? Don’t repeat yourself, right?
I’ve got content, content, background color, background color, static value, static value that matches. Here’s a whole position statement that matches.
Before we go any further we’ve started to get towards a workable solution. What we need to do now is make sure that we’re not getting messy.
Okay we got to clean ourselves up. We’re looking a little messy right now so we got to clean ourselves up.
So what I’m going to do is I’m going to come in here and I’m going to say pseudo elements and I’m going to take all shared styling, which is the content, the background color, the position absolute. And then that’s probably it.
I’m going to take those. OK, and I’m going to bring those up here to ruled grid card before.
Right. I’m a pop these in.
But I’m also going to say, hey, let’s do that with the after as well, because these are shared styles. I don’t want to have these things repeating over and over and over again.
Now what I can do is take these instructions out of our row and column, and I’m just left with the relevant information. The repeating information that I don’t want to worry about ever again, because this is never going to change, okay, is up here, and only the relevant information is attached to the row and column instructions.
This makes maintainability way easier because I’m not staring at this unnecessary content every time I’m trying to analyze what’s going on down here. Now the only problem is this color of red.
That’s not good whatsoever. I want to tokenize as much as I possibly can here, namely the line color, the line thickness, the line offset.
Okay. Uh, and then maybe we’ll see if there’s anything else I need to tokenize.
Oh, the gap, the gap has to be tokenized. Okay.
So I’m going to come up here to the parent. If you don’t know what tokens are or custom properties in CSS or variables in CSS, you’re going to see it a little bit right now, but you can watch my other videos.
I have videos on all of these things on this channel. Okay.
So no, no, have no fear. All of this has been explained, it’s all been taught on this channel before.
Go watch Page Building 101, or just search for keywords on my channel, or go to giri. co, go to my video section.
There’s a great, a tremendous search functionality at giri. co slash videos, and I have full transcripts of everything.
You can find almost anything that you’re looking for at giri. co slash videos.
So what I’m gonna do is I’m going to make a gap token and that’s going to be equal to my gap value. And then I’m going to come in here and I’m going to replace that gap value with my gap token.
Notice nothing is breaking in our grid so far. OK, now I want to tokenize something else.
Let’s tokenize the line thickness. That’s pretty easy.
That’s going to be two pixels. Anywhere I’ve referenced two pixels now needs to say no, no, no, no, no, line thickness.
And I’m going to show you real quick what this allows me to do. Line thickness, okay?
I also want line color. Let’s go line color is red.
We’re not trying to win any design contests here. We’re trying to make the lines obvious so that you guys can see exactly what’s going on.
So I’ve got my gap, my line thickness, my line color. Where have I mentioned my line color right here.
Var line color. Okay, notice I’m swapping in tokens but nothing is breaking because I’ve defined the value of these tokens right here.
Everything is good to go. The next thing is my line offset.
What is my line offset equal to? I already said it’s half of the gap value.
We already saw the gap is 2M. Then the offset needs to be 1M, but it also needs to be negative.
Okay, now I’m going to share with you a principle for tokenizing values like this. Okay, I’m going to say the line offset is calc var gap, so take our gap, divided by 2.
That is the value of our line offset. Why did I do that instead of just saying 1M?
Well the reason I said that, that big calc statement with our token, is because the gap may change guys and if this gap changes to 3 and this value does not change to account for that, we’re going to break our grid. Our lines are going to be in the wrong position now.
I need to create a situation that is unbreakable. So what I’m going to do is with gap being 2M, I’m going to say calc, I’m going to say var gap divided by 2 and guess what this is going to do.
I change right now this equation computes to 1M. If I change this to 3M this is going to compute automatically to 1.
5M. Okay so this is very very very important.
Notice that when I change the gap, look I’m just going to make this obvious, 5M it is breaking. Everything is breaking.
Why? I need to take this token, come down here, and replace these static values.
Okay, so VAR, we’re going to have our line offset, and then for left, we’re going to have our line offset. Now what you’re going to notice is, because these are positive values, they’re bringing the lines in instead of in.
I need these values to be negative. However, I don’t have a crystal ball.
This is what I wanted to talk about as a principle here. Almost always I use positive numbers for values.
And then if I need them to be negative, I make them negative where they need to be negative. I don’t use a negative value assigned to a token, okay?
I always use a positive value assigned to a token. Then I make it negative wherever it needs to be negative.
That’s just the general rule of thumb that I follow. Okay.
So this is very simple. I take my VAR line offset and I drop it in a calc VAR line offset times negative one is going to make it a negative value.
I do this same exact thing with the top and now look, everything is working exactly the way I want it to. So what do these tokens give us the ability to do?
Well, look at this. I can change the gap at any time and the lines all conform perfectly to the new scenario, right?
I can even come in here and say, these need to be black or these need to be, there they are, they’re black, or they need to be DDD, light gray, something like this. I have easy control over the line color.
All right, I’m gonna put it back to red so they’re obvious. And then I can change the line thickness.
Okay, so there’s line thickness by pixels, everything gets thicker, but nothing breaks. This is really, really, really critical.
This is why we tokenize things. All right, we’re creating an unbreakable, efficient, maintainable, elegant situation.
All right, so I’ve got my grid here. The next thing I’m going to do is I am going to, well, no, we’ll jump to that in just a minute.
I was gonna say we’re gonna take a look at different column and row scenarios and all of that. But first I want to get to our final solution.
Okay? I don’t think I’m supposed to use that phrase.
Okay. Alright.
So width of a hundred percent? A hundred VW.
What happens if I do that? Right?
Because what is a hundred percent gonna do? A hundred percent is only ever going to be the width of the card.
And it’s never gonna fill in these gaps. Now I can do a bunch of fancy gap math and all this other stuff.
A hundred percent plus something. I actually tried that.
It’s not even necessary. It’s not even necessary.
We can go way easier, way more efficient than that. Way simpler.
Look at this. Just go VW on this, just go VW and it’s going to go all the way to the edge of the viewport.
And then what I need to do is I need to come down here and do this with the height as well. But instead of VW, I need to go VH.
Hey, just go all the way to the bottom, my friend. And what’s great about these pseudo elements is there’s many pseudo elements overlapping each other, but they’re all in exactly the same position.
They don’t like combine to create thicker lines or anything like that. You would never know that there are multiple pseudo elements running through the same area.
And it doesn’t really matter that that’s happening. Now, you might be saying to yourself, Kevin, this is awkward.
We don’t want this. We what’s going on here?
We don’t want this situation. Here’s where the magic trick comes in.
What we’re effectively going to do now, because if you look in the middle of this grid, it’s actually exactly what we want. We just don’t want this outside line, this top line or the fact that these lines are running straight to the bottom of the page.
What we can think about doing guys is chopping off all of the excess and just leave the part that we want. And how do you do that?
Very simple. You come up to your main grid and you say overflow hidden and voila.
Now one thing I want to do because we don’t want to just rely on our content alignment. We want to put some padding in our cards.
So I’m going to go to our card, I’m going to say padding. Let’s go with 2M and see how that looks.
That might be a little bit aggressive. Let’s go with 1.
5M. That’s pretty good right there.
Okay, so we’ve arrived at our solution more or less. What we need to do is test our solution.
So first of all, did we use any media queries? No, but what happens on mobile?
We haven’t even checked mobile yet to even know if we need any media queries. So in order to do that, I’m also gonna say any column count, okay?
We’re gonna change this from three to auto fit, which means I don’t know how many columns there are going to be. Look at that right there, still works.
Look, no, I don’t even have any rows. They just, the rows just disappeared on their own, okay?
I only have column dividers with this solution. What if I said that this is gonna be a 200 pixel minimum card width, and it gives me four columns?
Well, what do we have? A working grid.
Everything works exactly as we want it to work. What if I said that this is gonna be 280, and it brings it back to three columns?
Well, we already know that that works. What if I say 320?
Does it give us two columns? It does.
Does it work with two columns? Clearly it does.
Let’s put it back to 280 and then let’s check out what’s happening on mobile. So let’s inspect here and let’s just see.
I mean I don’t think because I just saw every scenario almost except for a one column grid. I don’t think we’re going to need any media queries.
Let’s check. So this oh as it breaks to two we’re still good.
No media query. As it breaks to one we’re still good.
We’ve achieved this without media queries. We’ve achieved this with any column count that we want.
You can use, can you use any number of grid items? Is that box checked?
Okay, well let’s go up here and let’s take this last card right here and comment it out and see what happens. And yes, my friends, the grid is still intact.
We don’t lose a top line. We don’t lose a left line.
We don’t get nonsense happening. It works if there are uneven items.
Okay. Um, did we use int selectors?
No, we were able to avoid them. And then that card that I just commented out says, does this work with any backgrounds?
Right? So I should be able to put a background gradient back here and still see everything.
All right. So let’s try to do that.
So let’s say body is going to be background and we are going to let me come back into our CSS. You guys can all see what we’re doing.
We’re gonna say linear gradient. I’m just gonna do super simple.
DDD and then AAA. Something like this.
So there’s a gradient back there. This still completely works.
You can put a background image back there. You can put a background pattern back there.
Whatever you want to put back there, all is well in the world. So guys, we have achieved our goal.
We have checked all of these boxes. We’ve created an unbreakable situation, a situation that’s easy to maintain, right?
No media queries, no in child selectors, no craziness going on. Let’s just take a final step of cleaning this up even further by switching this all over to logical properties.
If you don’t know what logical properties are, they help with different reading languages. They help in a bunch of different scenarios, important for accessibility.
Okay. So I’m going to come in and anything that can be converted to a logical property, Oh, actually, we’re going to do one more thing after this.
We have to do it. In fact, let’s do that before logical properties.
Let’s do the one last thing. Okay.
There is a scenario. Let me go back up to our HTML, where if one, let me go to something in the first row, has long content, so we have long content, let’s see what happens.
It’s fine, because these grid items stretch, but actually the grid is off balance now. The top row is higher, taller than the bottom row, and it doesn’t look symmetrical.
Now you may not care, but what if we want to force the grid to be perfectly symmetrical? Here’s how you can do this.
You can come down to your grid right here and you can declare, here’s grid template columns, we can say grid auto rows and we’re going to do a min max of min content 1fr and then we’re going to save that and watch our bottom row, okay? I’m gonna have to comment this out and comment it back in.
But I want you to keep an eye on our bottom row, the height of the bottom row, okay? So I’m gonna comment out, bottom row gets smaller.
Comment it back in, bottom row gets taller. What is happening here?
It’s taking the biggest card, okay? The card that’s forcing this whole row up top to get taller and it’s applying that height, that computed height to every row in the grid.
So what you’re gonna end up with is more white space, see I can’t talk today, more white, I’m trying to like eat my tongue as I talk, I don’t understand. And then my brain is short circuiting, just today is not a good, we are not winning today as much as we normally are.
But it’s okay, we’re getting through it. And it’s, even when I’m not winning, guys, this is still like premier content, right?
This is some of the top content that you can get for free on YouTube. All right, so undeniably, right?
Undeniably, drop a comment below if you feel that that is the case. Hit a thumbs up if you feel that that is the case.
You know, pay with a like, pay with a comment, that sort of thing. Okay, so what we’re doing here is basically saying, hey, if we’re gonna have an item that’s forcing one row to be taller let’s make all the rows match that height therefore the grid will be perfectly symmetrical.
This is completely optional you don’t have to do this I just if you want to do this I wanted to show you how to do it that statement right there is how this is done. Now let’s convert everything to logical properties okay so I’m going to come down none of these can be converted to logical properties.
We’re gonna go down to our rule grid card, position relative, padding. None of those can be converted to logical properties.
None of this can be converted to logical properties. Our width, our width gets converted to inline size, okay?
Our height gets converted to block size. Our top position is using the inset feature.
So it’s inset, and because it’s top, that’s the block axis, we’re gonna say block start, the start, you see that? I just fucking hit puberty, dog.
Like, I don’t know, we are taking Ls left and right today. All right, inset block start, so that’s the block axis.
We wanna be at the start of the block axis, which is effectively the top. And then left and right are the inline axis.
So we want to be inset inline start of zero. And look, nothing is breaking.
I’m just swapping these things out for logical properties. Why?
Because I care about code quality. I care about best practices and latest standards.
All right, you get it. So width again is inline size.
Height is block size. And then top is inset inline start save.
We have now converted everything to logical properties. We’ve talked about having a completely symmetrical grid.
We’ve used no media queries. We can do this with any column count.
We can use this with any number of grid items. We can avoid inf selectors.
It works with backgrounds and gradients and patterns and images and it’s very very efficient. I mean look at this look at the cleanliness of This solution.
I challenge you is there a cleaner Solution is there a cleaner solution out there? I don’t know that there is What did you think of this training?
Did you learn a lot? Do you like the CSS only solutions guys?
This is so easy so easy to just take right into bricks or oxygen or quickly or whatever your preferred page builder is now. Now I will say little caveat.
If you use an element or if you use a divi if you use a beaver results may vary right because um you know like I do here let’s target the direct child kind of thing. Well there’s so many divs they use so many it’s like deception city is so much bloat and so much terrible code and then it doesn’t really use classes, it puts classes on the wrong things.
But hey, that’s the builder you chose, that’s the life you’ve gotta live, right? This will work easily in any good page builder, right?
Not those nonsense page, but the good page, okay. I’m done roasting the bad page builders.
That’s it for this training. I gotta go.
I gotta go before I take more L’s, before I choke on something. I don’t know.
I don’t, I gotta get out of here. Drop a comment below.
Let me know what you think of the video. If you like this channel, if you’re new here, make sure you subscribe.
If you love this content, if you love best practices, if you love scalability, maintainability, elegance, and then all the stuff that we talk about here, subscribe to the channel and I will see you again very, very soon. subscribe to the channel and I will see you again very, very soon.
With another training. Peace.