Search code examples
cssnext.jscss-gridmdxjsnextjs-image

Get `next/image` working with CSS Grid Full Bleed Layout?


I'm trying to follow this tutorial.

Here's the TL;DR:

.grid--wrapper {
    display: grid;
    grid-template-columns: 1fr min(65ch, calc(100% - 64px)) 1fr;
    column-gap: 32px;
}

.grid--wrapper > *,
.header {
    grid-column: 2;
}

.full-bleed {
    width: 100%;
    grid-column: 1 / -1;
}

It follows Medium-like design with images bleeding towards the edges of the browser.

And it has a full-bleed class for Image:

.full-bleed {
    width: 100%;
    grid-column: 1 / -1;
}

I am really not sure how to make my next/image work with this kind of stuff?

My Img.tsx file looks like:

import Image from 'next/image'
type ImageProps = any

export const Img = ({ className = '', ...props }: ImageProps) => (
    <Image className={`${className} full-bleed`} width="100%" {...props} />
)

And my components/mdx/index.ts looks like:

import { H1 } from '@/components/mdx/H1'
import { H2 } from '@/components/mdx/H2'
import { H3 } from '@/components/mdx/H3'
import { H4 } from '@/components/mdx/H4'
import { H5 } from '@/components/mdx/H5'
import { H6 } from '@/components/mdx/H6'
import { Img } from '@/components/mdx/Img'
import { Pre } from '@/components/mdx/Pre'
import { PreCode } from '@/components/mdx/PreCode'
import { P } from './P'

export const MDXComponents = {
    h1: H1,
    h2: H2,
    h3: H3,
    h4: H4,
    h5: H5,
    h6: H6,
    p: P,
    img: Img,
    pre: Pre,
    'pre.code': PreCode,
}

My .mdx files contain normal HTML img tags which will use Img component as written above (which internally uses next/image).

How do I get full-bleed layout when I don't have a height? I can't even get layout="fill" to work properly. It just overlaps images on top of each other.

Any ideas?


Solution

  • I found an answer thanks to https://dev.to/tanahmed/next-image-make-image-fill-available-space-272o

    All I had to do was change my markup to:

    import Image, { ImageProps } from 'next/image'
    
    export const Img = ({ className = '', ...props }: ImageProps) => (
        <div className="unset-img full-bleed">
            <Image className={`${className} custom-img`} layout="fill" {...props} />
        </div>
    )
    

    And change my CSS to:

    .grid--wrapper {
        display: grid;
        grid-template-columns: 1fr min(65ch, calc(100% - 64px)) 1fr;
        column-gap: 32px;
    }
    
    .grid--wrapper > *,
    .header {
        grid-column: 2;
    }
    
    .full-bleed {
        width: 100%;
        grid-column: 1 / -1;
    }
    
    .half-bleed {
        width: 75%;
        margin-left: auto;
        margin-right: auto;
        grid-column: 1 / -1;
    }
    
    .wrapper {
        width: min(60ch, calc(100% - 64px));
    }
    
    .custom-img {
        object-fit: contain;
        width: 100% !important;
        position: relative !important;
        height: unset !important;
    }
    
    .unset-img {
        width: 100%;
    }
    .unset-img > div {
        position: unset !important;
    }