Overlaying Text and Images on a Background Image in React
Now that we have our images lining up perfectly in our columns, it is time to take our descriptions and our logos and then layer those on, so that's what we're gonna do in this guide.
Guide Tasks
  • Read Tutorial
  • Watch Guide Video
Video locked
This video is viewable to users with a Bottega Bootcamp license

So let me switch over to Visual Studio Code and let's start as usual in updating the JSX structure here. The reason why I follow this approach is that I feel like it's a more logical progression to build out my JSX structure first and then add my CSS and my selectors and everything like that. It makes it, at least in my mind, a little bit easier to follow.

So let's come here, we have this image logo, and description, and the link, I'm just gonna get rid of all of it and write the JSX code just from scratch. So I'm going to create a div, now this one is not gonna be a self-closing div, and let's give it a class name of img-text-wrapper 'cause this is gonna sit right on top of that background image that we worked on in the last guide.

The very first thing we want to show is that logo, so let's add a div here that's gonna hold the logo. And we can give this a class name of logo-wrapper, 'cause that is going to wrap around the logo. And then inside of here, I wanna just have a regular image tag, so I'm gonna say img and the source of this is going to be logo, so say source equals logo, and then make sure that you close that off, or else you'll get an error.

And hit save just so we get our nice formatting from the prettier gem or the prettier extension. And now let's add the description, so I'll say div className equals, and let's call it the subtitle, and then call description, close off that div and we should be good to go.

portfolio-item.js

<div className="img-text-wrapper">
    <div className="logo-wrapper">
        <img src={logo} />
    </div>

    <div className="subtitle">{description}</div>
</div>

Okay, let's go and test this out first in the browser just 'cause this was a decent amount of code and we're about to write a lot of CSS code. So before we do anything, make sure you hit refresh, and it looks like we are missing our logo, so let me just kind of inspect this really quick and walk through what could be causing this. So I'm actually going to pop this open just so we can see it a little easier. And that took up the whole giant screen, so let me fit it inside of here, there we go, this is gonna be a little easier.

So if we look at our portfolio-item-wrapper, we see we have our background-image, so that's working properly. Now we have our new img-text-wrapper here, and you can see we have our logo-wrapper and we have an empty image, so that's the issue, we are getting nothing past here for the logo.

Now whenever this happens, and I can tell you, no matter how long I've done this, these kinds of things come up constantly. The very first thing that I would do is to look through the data and see exactly what we have access to. So we could do that with the debugger, but let's actually use the React Dev Tools this time.

So I'm gonna go to React and then I'm also going to make it a little easier to highlight everything, so I'm gonna use the Inspector, this button here. Click on that div, and, okay, so we have our empty image, but let's follow the chain up all the way up to the portfolio-item container.

There we go, so we have our children, which is an array of 12, these are the items. And then let's just click on the first one, though we could click on any of them, and moving down, we have our props, this is our item prop. We have our banner_image_url, category, column_names, description, id, oh, and there's the issue.

You see, I'm calling logo but it should actually be logo_url. The reason why I keep these guides in here, and I've mentioned this several times, the reason why I do not edit out any kind of mistakes like this is that this is a very common process, it is something that there are many times where I will think I'm about to render out some kind of code or something I'm getting from an API, only to find out that the data is not showing up, and so I like to show you kind of what my personal process is whenever that happens.

And so I'm gonna close that out, and now all we have to do is come here and instead of logo, it's just logo_url.

portfolio-item.js

export default function(props) {
    const { id, description, thumb_image_url,logo_url } = props.item;
    return (

This is what we're grabbing from props item, and now, instead of logo once again, it's logo_url.

<div className="img-text-wrapper">
    <div className="logo-wrapper">
        <img src={logo_url} />
    </div>

Hit save and now let's see if that is working. So you can come back here, hit refresh, or it should do it automatically. And remember, the logos are all white, so you can see this empty space here is actually gonna be the logo is my guess. And yes, if you select that you can inspect it and actually see that yes we now have a logo_url here going in the image tag, so that is working.

large

Now that we have all of our JSX code in place, let's go and add our new styles. Now I will warn you, this is probably gonna be as much style code writing as we're gonna be doing in the entire course. We have four rules to add and they are not small ones.

So we'll get through this we'll get started off with the very largest one. Make sure that you have this nested inside of the portfolio-item-wrapper. And you can reference this, it's called the img-text-wrapper. And so we're gonna select that first.

The very first thing we're gonna do is call position absolute on this because we want to be able to control exactly where each one of these elements shows up. And if you're curious about why we use position relative here, it's because it's a CSS rule that anytime that you wanna use position absolute, the parent component has to use position relative, so that's why we did that.

And so now that we have position absolute, I want this to line up to the top. So I'm gonna say top 0, and then we're gonna make this a flex container and then we're gonna use the flex-direction column so that these items are stacked on top of each other.

Then I want this to be justified to the center, so justify-content center, align-items center. If you went through the full HTML/CSS, flexbox, and CSS grid course then all of this should be a good review on how to get items to align vertically and horizontally. So we have align-items, let's see what else we need. Let's add the height to be 100%, we want the text alignment to all to be centered, and then let's see what else. Okay, we need some padding as well, so let's do padding-left at 100 pixels, and then padding-right at 100 pixels.

portfolio.scss

.img-text-wrapper {
    position: absolute;
    top: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    height: 100%;
    text-align: center;
    padding-left: 100px;
    padding-right: 100px;
}

So I'm gonna hit save and let's see what we have going on now. Okay, so this is progress, it's ugly but it is progress.

large

So, now we can see that instead of having the natural behavior with HTML where the items are just stacked on top of each other, now we have the logo and also the description. It's harder to see for some of these, but we have those now layered on top of the background image.

So this, even though it's ugly, is actually very close, and this is the longest set of styles that we need to write in this guide. So now that we have that and that's looking good, now let's go and let's style the subtitle. So we have that img-text-wrapper and we have a subtitle, and actually, let me just nest it inside of here.

So I'll say subtitle and we just have a couple of rules for this one. First, we're going to have some animation so I'm gonna say transition 1s and then let's say ease-in-out. And I want to start off with the color being transparent, and the reason for this is because remember back to what we have here, I do not want the description showing up until we hover over the items just like this.

So we're gonna start off with that subtitle or that description being transparent and then when we hover over, which we'll learn how to do that in the next guide, then it is going to add in those styles. So now you can see those are all, it looks like they're gone, but they're actually there, they're just transparent. So that is our subtitle.

portfolio.scss

.subtitle {
    transition: 1s ease-in-out;
    color: transparent;
}

Now let's look and see, okay, we have the img-text-wrapper, and let's add in, and for this, I do not like these selectors. If I were to just keep on nesting these I think we're already kinda going a little bit too far, so I'm going to do something here where instead of nesting another level deep then I'm going to add this where I'm gonna say img-text-wrapper:hover .subtitle. And the reason why I'm doing this is because the further you nest your SCSS files and your SCSS rules, the harder they're going to be to debug.

So sometimes I like to give myself almost like a little reset button right here where I say okay, this is as far as we're going to go and as far as we're going to nest these items. And let's just move back and now we have a little bit easier to manage a set of styles.

So inside of this subtitle now let's say, let's go with the color, and for right now, let's go with teal. And the reason why I can call this $teal, if you remember when we used our variables we have this teal color. And I may change it to dark teal, we'll see exactly how it looks in a second. Then I want the font-weight, let's say that we want this to be at 400.

portfolio.scss

.img-text-wrapper:hover .subtitle {
    color: $teal;
    font-weight: 400;
}

Okay, let's hit save and take a look at this and see if this is giving us the behavior we're wanting. I'll hit refresh, and there we go, it's loading up. And now if I hover over, there we go, do you see? It's kind of faint right now because we haven't added that cool kind of darkening feature.

large

We'll eventually add this where the images will actually get darker when we hover over. But for right now you can see that when we hover over this div we are getting that nice fade in and fade out with the description, so that is working nicely.

Last thing for this guide, let's just go and add the logo-wrapper style. So here I'm gonna say logo-wrapper. And then we wanna select the image inside of here, and so we want the image width to be 50%, and then let's just see what that looks like and see if that gives us what we're looking for.

Oh wow, that is so much better, yeah, that's looking really good. The only difference I would say is let's add a little bit of margin to the bottom. So I'm gonna say image and then margin-bottom and let's go with 20 pixels, hit save, and that moves each one of these up just a little bit.

portfolio.scss

.logo-wrapper img {
    width: 50%;
    margin-bottom: 20px;
}

So this is looking really good. A few of these, you may say, okay, these look like they're a little out of alignment. You can see where this logo's a little bit higher than these other ones and we'll clean those up later, so don't worry about that.

For right now I just wanna focus on the high-level behavior which is to have the logo pretty much centered with the nice fade in and fade out of the description right below it. This is coming along very nicely, you can see with just a few guides we've been able to completely transition the way this homepage looks, and we're now very close to the final version. So great job if you went through that.

Resources