/* you need to wrap the component */
.image-wrapper {
box-sizing: content-box;
}
/* the magic happens here */
.image-wrapper > div {
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
border-radius: 5px;
}
`;
// We need to wrap our images in a parent div
<div className='image-wrapper'>
<Image alt='...' src='...' width={800} height={400} quality={70} />
</div>
Next.js next/image
component offers your site some fantastic benefits straight out of the box. Benefits like lazy loading, optimization, responsiveness and resizing. If you're buliding with Next.js then you'll definitely want to use them.
The only issue is they can be a nightmare to style. I was banging my head against a wall trying to figure out how to style Image
component.
You see there are two issues that make it hard to style your next/image
component.
The first is that it has inline styles meaning that those styles will overwrite any styles you apply to a selector. You could use the !important
property but that comes with its own risks and side effects. I think the solution below is a nicer way to handle this issue.
The second is the image is wrapped in divs
meaning certain styles won't function the way you want them too. Depending on the properties you pass an Image
it can be wrapped in one or two divs. Let's look at what an next/image
looks like in the browser. Below is an outline of their structure, but inspect the browser tools on this image to see for yourself.
<div>
<img />
</div>
<!--Or-->
<div>
<div>
<img />
</div>
</div>
The divs
above if you looked at the example have their own inline styling which causes issues when we try to style the component. If you tired to add border-radius
to the img
tag you will get a weird shadow effect due to the parent divs
.
Thankfully the below solution will help solve both of these issues.
The Solution
To overcome these issues we can wrap the Image
component in a wrapper div
and give it a class name. The reason we want to do this is so that we can now target the divs
that automatically wrap our Image
. Above we have done this by wrapping it with the <div className="image-wrapper">
element.
We can now target the children divs
by using a child combination selector. In the snippet above we have the class image-wrapper
we then use the >
symbol to select all children of the type we specify. Therefore in this instance we want to use > div
to select all children divs of the div
with the image-wrapper
class.
Now that we have a wrapper, we can add styles to those divs to have our next/images
looking the way we want them to.
All you need to do is add the styles in the below selector.
.image-wrapper > div {
/*styles go here*/
}
If you wanted to apply styles to the img
tag itself you have a few options.
- You could target the image like so
.image-wrapper > img
- You could add a
className
to theImage
component
The key thing to remember is the Image
has styles applied inline so you if you want to overwrite any of them you need to use the !important
property.
Reusability
What I do on my blog, the one you are reading now is I create my own Image
component for blog posts. This component has a div that wraps the next/image, so that the styling is applied across my whole website.
I use styled components to make this happen, if you want to copy it for you website feel free to grab the snippet below.
import Image from "next/image";
import styled from "styled-components";
const ImageWrap = styled.span`
margin: 32px auto;
box-sizing: content-box;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
& > div {
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
border-radius: 5px;
}
`;
const PostImage = ({ alt, src, width, height }) => {
return (
<ImageWrap>
<StyledImg
alt={alt}
src={`/images/articleImgs/${src}`}
width={width}
height={height}
quality={70}
/>
</ImageWrap>
);
};
export default PostImage;
Update For Next.js 12
Nextjs 12 now uses a span
instead of a div
. So if you have upgraded from a previous version you want to change your css selector to the pattern below:
const ImageWrap = styled.span`
// same as before
// just change this css selector
& > span {
...
}
`;