CSS Foundations

Speakers Image & Grid Layout

CSS Foundations

Check out a free preview of the full CSS Foundations course

The "Speakers Image & Grid Layout" Lesson is part of the full, CSS Foundations course featured in this preview video. Here's what you'd learn in this lesson:

Emma demonstrates how to approach styling images with varying size dimensions. Creating the speakers layout by utilizing grid is also covered in this segment.


Transcript from the "Speakers Image & Grid Layout" Lesson

>> How do we go from this to this? This is a lot, right? The good news is the markup looks the same for all of these different blocks, right? Let's look at what that looks like. We've got a div, inside that div, we've got an image, an h2 for the name, a paragraph for the company name, and a paragraph for the bio.

So all the markup looks the same. So hopefully, it's not too terrible to try and style. When we do one, it should be applied to all of them. I'm gonna add some class names so that these are easier to work with. First of all, let me collapse this SVG, cuz this is a large block of code here.

Again, I'm gonna use multi-select, the cursor, multi-cursor, in VSCode, because since the markup is the same, it's gonna save us a ton of time. So what I want to do first, I wanna add a class to these wrapping divs here. So I'm gonna highlight this. Full tag, I'm gonna hit Cmd+D, one, two, three, four, I think there's another one, five, five.

And now I can multi-type at the same time. So class, and this is gonna be speaker__wrapper. Let's do the same thing for the image, so img, multi-select five times. Give it a class of, speaker__photo. Same thing for, The h2. I'm gonna call these ones speaker__name, and then we've got company and bio.

In order to multi-select these, because if you're playing around with multi-select, it can be a little tricky, right? I wanna select all of the company paragraphs, but the bio ones underneath it will also match that. So I'm gonna select the entire opening paragraph element plus that C, that I'll give us the company elements only.

Yeah, multi-select here, class="speaker__company", and lastly, the bio. [SOUND] Okay, Whoo-hoo, okay, now, we can actually apply some styles. So our images, looking at our file here, should have a size of 310 by 310. So let's go ahead in our speakers.css file, let's close out the others here. .speaker__photo, width: 310, height: 310.

Okay, that's a little bit easier to work with here. You'll notice some of our photos are distorted, right? Anyone know why they might be distorted? It's just that the dimensions with the photo don't match what we're trying to fit it into box-wise, right? Just fine, but there are some properties that we can use to fix this.

So there's a property called object-fit that we can use. So let's go in here, object-fit. Let's try contain, remember, from our cat photo. What does contain do? It tries to maintain those dimensions here, but some of them, again, it's just not looking right, so let's try cover. Let's see what cover does.

Well, that looks a little bit better. They're now 310 by 310, although there are a few, you can see this one here, this one here, the heads are cut off, right? So how do we fix that?
>> Aspect ratio?
>> I guess you probably could use that.
>> What if you remove the heights, you just probably use the width or the heights?

>> If I remove height here?
>> Yeah, just one.
>> Mm-hm, except they're all gonna be different ratio. So here's the reality. The ideal situation is our photos are given to us in the dimensions that we need them, that's the ideal situation, [LAUGH] right? If we don't have an explicit height, they're all gonna be different heights.

So we do want that height. Aspect ratio might actually work, I didn't think about that. I'm curious. Let's see, aspect ratio, uh-huh, 1/1. Let's see what that does. Admittedly, I haven't used aspect ratio before, so let's see what happens if we add it on this class. aspect-ratio: 1/1, let's see, does that do anything?

I guess if I remove cover. Okay, so the ratio here, I don't know, was 16/9, how do you? Is it a fraction only? Yeah, it looks like it. You probably could use aspect ratio. That's the short answer. The long answer is I haven't worked with it before. So I'm gonna stick to object-fit and position them that way.

That was a really good point. We can use the object position value or property value pair to go ahead and center these, right? Looking at our photos, let's see, the third one here, And the fifth one here, we need to fix those two. Those are the two we need to worry about.

So in this instance, I'm sure there are several other solutions. What I'm gonna do is add another class to these. I'm gonna set that to speaker__photo--top. It's gonna be our modifier here, cuz I want the photo to be positioned at the top. Let's add it to the last one as well since the head was being cut off there.

Now, in here, .speaker__photo--top. Before I do this, let's set that on all the photos and see why we can't just apply it to the speaker class. Oopsie, here we go, object-position: top. If I do that, this looks much better. But this is not looking so hot, these are a little bit cut off.

We want them to be appropriately centered or positioned, right? So it's just those two that we really wanna alter. So I'm only gonna set it on those two, object-position: top. Okay, so now, did I save my HTML? I did, so it's not showing up, hold on. I put it on the wrong person, that's why, silly.

So it was the third and the last. Let me fix that. Okay, there we go, [SOUND] there we go. Okey-dokey, that looks a little bit better, we can see everyone's shining faces here, right? But, like I mentioned, ideally, these photos would be in the proper aspect ratio for you before.

Sometimes this happens and you gotta play with it. Okay, now we've got the name of the company in the bio. So the name, again, these are all in the design files. We want it to be 32 pixels. Speaker__name, font-size: 32px, speaker, we'll add the style rules for the company and the bio as well, because they're gonna be pretty similar, company.

Speaker__bio, okay? So the name we want 32 pixels, the company has 24 pixels, and the bio is 20. Okay, cool, that's looking a little bit more like our, what is it called, our design file, right? But of course, the text here is inheriting that orange color from the body secondary class, right?

This is fine for our speaker name, which we want to be orange, but our company and our bio, we want to be black. So I'm gonna go ahead, in our base file here, let's do, One more variable here. So we have color-text-on-primary, it'll be nice if we get color-text-on-secondary.

So I'll just make one more, --color-text-on-secondary, and we want this to be black. So black hex value is 000000, like that. I'm gonna copy this variable name. Now, what I could do for the company and bio is put the color declarations on both of them, right? So that's totally valid.

If I want to avoid that, what I can do then is just combine these two selectors, so speaker__company and speaker__bio. Maybe this is a better solution. I mean, it's kind of a small example, so honestly, it doesn't really make that big of a difference. But just to switch things up, we'll do it that way, except that this one's not working.

speaker__bio is still orange. Let's see, what's our bug counter? How many live bugs are we up to at this point? That's me being silly. I wrote company__bio in the markup and not speaker__bio. Let's fix that, speaker_bio, there we go. At least that one was relatively painless. Okay, so very much like how we previously had to remove margin off of the paragraph elements, remember, we removed that on the home page here.

We also wanna remove it from the heading element, because this header has some default margin, right? You can see that in our box model down here. So what we're gonna do is also just remove it from the header elements, oops, like that, to combine that. So now, that's sitting a little bit more flushed.

Now, we do wanna have some spacing between these elements. It is in our design file here, there is a red line. So 36 px between the name and image, 20 between name and company, and 32 between company and bio. Now, there are a couple ways that we could do this, right?

So we could add top and bottom margin to the speaker name and then bottom margin to company. We could add bottom margin to the photo, bottom margin to speaker name, bottom margin to company. There are several different ways you can go about this, and I'm not sure which is necessarily considered best practice.

What I'm going to do is add bottom margin to these three elements. Is it the right solution? I don't know, it works. If you have a strong opinion, please let me know, because actually I'm not certain where I stand on this. I'm curious where y'all do. So back to the speaker photo.

Let's go back to the photo, okay? margin-bottom: 36, I lied to you. The name is 20, margin-bottom: 20, and then company is 32. Nice, we also need to set a width on the card so that our content's not getting super-duper long. You can see our text is just continuing on and on.

And actually the longer your paragraph text is, the more difficult it is for people to read, it's not as accessible. So it is good to set a width on there. I could set the width on the paragraph content. I'm gonna actually set it on the wrapper for the speaker.

So where did you go? Speaker wrapper, maybe I haven't defined that in here yet. Okay, we'll put it up here, .speaker__wrapper. Let's set a width on here. Let's set it to 460. Let's see how that looks. Okay, looks a little bit better here. So the entire wrapper has now a width of 460, right?

We also want the speaker cards to be in a grid. If we look at our design, it's a 2 by 2 grid, right? So we could use grid, but we can also use flexbox, right? It does look like a two-dimensional layout, but actually, if we think about it, it kind of is a one dimensional layout where the flex items just wrap onto new lines as needed.

I think that's the least. I think you could use grid, absolutely, but I think flexbox also makes a lot of sense here. So, We scroll back up here. We can see right now, we have each individual speaker wrapper at that same level as our header. So what I'm gonna do just to kind of to encapsulate all of the speaker cards in one place, we'll create a div, and we'll give it a class of speakers__wrapper.

Now, this is different than speaker__wrapper. I know it's pretty close. Let's see if I get any bugs there. Okay, so now, they're in their own wrapping div, right? And now, if we wanna lay them out, speakers_wrapper, let's make that a flex container, display: flex. And now, they're all in one line, cuz remember, they try to fit on one line as flex elements.

Well, we want them to wrap like I had mentioned. So let's try to make them wrap, flex-wrap: wrap. Cool, they're gonna break onto a new line when there's not enough space for them. They're gonna maintain their width of what? I think it was 460, something like that. It's a little bit better.

It's not exactly what we're looking for. If we inspect this here, here's our speakers__wrapper. If you can see, if we hover over it, there's kind of a bunch of space on the right there. This is where we can use justify-content. We kind of want some space in between, so justify-content: space-between, right?

And so now, we're getting that purple, it's almost like a channel, it's the space that's leftover on that row. It's gonna be in the middle of them. But maybe we do want to use grid, right? How do you know? If we go back to Grid Generator for a second here, we know that we wanna have two columns, we know that.

We want two columns with a grid gap of 200, we want 200 pixels of space between them, let's say. We don't want them to be right on top of each other, right? There's some space there. So we add a grid column gap of 200 here, right, maybe something like that.

I don't really care about how many rows there are as long as the items are filling up the available space. So what does that look like? Well, maybe we should try it. If we have a display: grid, right, we want two columns. I don't care about the number of rows, but we do want that column gap of 200 pixels.

We also want the items to have some row gap as well. We don't want the items to sit immediately on top of each other vertically. So let's give it a row gap as well of, let's say, 120 pixels. I want it to be 120 pixels, and that's what I have on my notes and my screenshot, and it works.

But for some reason, maybe I had a larger monitor before, [LAUGH] and so the window wasn't so scrunched. You know what, we're gonna try 120 in our, In our code. But I might have to wing it, let's see what happens. I'm gonna copy this code, right? So in our speakers__wrapper, Let's change this to display: grid, right?

Remember, we want two columns taking up one fraction each, column gap. Remember, I don't care how many rows there are, just fill up all the available space. We want the column gap to be 200, and I wanted this to be 120. Now, I'm scared to go back to my browser, but let's see what happens.

Yeah, I think it was just a matter of, I'm on a smaller viewport with my MacBook and I have my nice big monitor, right? So now, we've got our 120 pixel gap between rows. We can see this. If we hover over this in Chrome, you can see the actual gaps, the column, and row gaps here, right?

So actually, maybe grid is a better solution. We definitely could use flexbox, there's nothing wrong with that, but it seems like maybe grid is the way to go here. So now, you can see we get exactly two photos per row, they maintain a nice distance. When we resize the window, though, that's not very nice, right?

That's because we've defined a finite width on these cards, right? So instead of using width, let's say, max-width. I wanna say the maximum width these cards will be is 460 pixels, right? So now, instead of having that overflow on the x-axis, now they're squishier up to a certain point, of course, right?

They're a little bit squishier and more responsive. They won't be any wider than 460 pixels, but they do squish up into a certain point.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now