DEV Community

Michael Mason
Michael Mason

Posted on

Fixing NextJS <Image> covering other components

Hey folks, first time poster here. I've been working on a project for my organization and I've been using it to help learn NextJS and CSS.

This project has been my first real experience with NextJS and I've been really enjoying it, especially coming from React. That being said, the whole experience hasn't been perfect. Here I'll talk about a recent issue I ran into and how I was able to solve it so hopefully if you find yourself in the same situation, you may be able to get past it.

NextJS Image

If you are unsure of what the component is or does here's the documentation:
https://nextjs.org/docs/api-reference/next/image#loader

In a nutshell, when you call the component it will help optimize the image you link it to, whether its a static image in the public folder, or a URL. What I like about it is that I don't have to mess around with the resolution of the image. I can just simply specify the layout, height, width, the quality, and it'll go from there. Here's an example from my code of the card I'm working on. Also, spaghetti code warning.

import { useState } from 'react'
import style from './Card.module.css'
import Image from 'next/image'
import Link from 'next/link'

const Card = ({ name, path, img, requireCac, description }) => {
    const [showDescription, setShowDescription] = useState(false)

    const toggleDescription = () => {
        setShowDescription(true)
    }

    const hideDescription = () => {
        setShowDescription(false)
    }

    return (
        <>
            <Link href={path} passHref>
                <div
                    className={style.cardContainer}
                    onMouseLeave={hideDescription}>
                    <section className={style.imageBlock}>
                        <div
                            className={style.imageContainer}
                            onMouseEnter={toggleDescription}>
                            <Image
                                src={img}
                                alt='The Law'
                                layout='responsive'
                                width={5000}
                                height={2815}
                                quality={100}
                                sizes={'100vw'}
                                className={style.cardImage}
                            />
                        </div>

                        {showDescription ? (
                            <p
                                className={style.cardDescription}
                                onMouseEnter={toggleDescription}>
                                {description}
                            </p>
                        ) : null}
                    </section>

                    <section className={style.cardInfoBlock}>
                        <div>
                            <h3 className={style.cardName}>{name}</h3>
                        </div>

                        {requireCac ? (
                            <div>
                                <p className={style.requiresCacBox}>CAC Required</p>
                            </div>
                        ) : null}
                    </section>
                </div>
            </Link>
        </>
    )
}

export default Card

Enter fullscreen mode Exit fullscreen mode

Problem

For me, it did the trick well and the cards are rendering nicely.
Image description

Unfortunately, there is a small problem when I go to the mobile view
'Oof'

For me this wasn't the first time I ran into this issue. I had previously been working on the home page and kept having problems with the overriding everything, and it was to a point where the images were covering everything. While digging deep into the Dev Tools for the component I discovered it was a set of spans enveloped around an absolutely positioned (image) tag.

Image description

Cool sweet, it just needs a relative to latch on to:
Image description

NOPE
Image description

So that didn't work. I then proceeded to try a few more 'position: relative' dart throws, which naturally didn't work and I ended up breaking my mobile navigation menu which took some time to realize and to fix.

I did some googling, I found a Stackoverflow (which I'm not currently able to find now ) about a background image covering content and I tried the fix there, which surprise, is another 'position:relative' attempt, which also didn't work.

I found another potential answer, which I can't find a link for, that recommended you set the parent container to position: absolute and the Z-Index: -1, which solved the problem but created a new problem, the cards were effectively under the main html body. This basically created a problem when it came to scrolling to the final item thanks to the footer covering the card at the bottom, and attempting to select the element proved to be a pain because it was underneath (Z wise) the parent component and the element selector tool kept selecting the parent rather than the individual cards.

So, that didn't really work, but it did lead me to another idea and after fixing up the googling, I found this:
https://github.com/vercel/next.js/discussions/30259

The answer at the bottom had already been attempted (setting a parent

to position:relative, so that was ignored. What I ended up doing was looking at the AnanyaGBs answer, and I began scouring the mobile Nav code for something that would work.

Long story short, I had a .mobileItems className in my nav bar. I had originally set it to sticky so it would follow the user as he/she navigated down the site. I eventually changed my mind on this and made it where the scrolling is locked when the navigation menu is open, but I never removed the position property. I tried to change it to absolute, but that for some reason destroyed the rendering of the navigation bar and it would only show one of the navigation items instead of all of them. I ultimately left it on sticky, and set the Z-Index to 99, and voila.

Image description

Image description

Conclusion

So next time you are running into a problem with the NextJS component sitting on top of something, instead of trying to wrap it in a and adding 'position:relative' to it, see if you can set a non-static position property to the item it's sitting on and give it a high Z-Index. It has to be non-static(absolute, sticky, or fixed), otherwise Z-Index will have no effect.

Thanks for taking the time to read this, hopefully it was helpful.

Top comments (0)