Next.js
에서 display
를 비롯한 스타일링이 제대로 작동하지 않았다. 그 이유는 무엇일까?
이 역시 고질적인 next/image
에 대한 이슈였다.
기본적으로 next/image에서는 제대로 된 스타일링 기능을 보장해주지 않았다.
따라서 이를 해결하는 방법은, 상위 컴포넌트를 컨테이너처럼 씌워, 해당 이미지를 스타일링하는 방법이었다.
따라서, 다음과 같이 ImageContainer
을 만든 후, display
등 이미지를 스타일링하였다.
import * as React from 'react';
import NextImage from 'next/image';
import styled from '@emotion/styled';
import { css, Interpolation, Theme } from '@emotion/react';
export interface ImageContainerProps {
loader?: string;
src: string;
alt: string;
width?: string | number;
height?: string | number;
margin?: string | number;
padding?: string | number;
position?:
| undefined
| 'static'
| 'relative'
| 'absolute'
| 'fixed'
| 'sticky';
placeholder?: 'blur' | 'empty';
blurDataUrl?: string;
sizes?: string;
objectFit?: 'contain' | 'cover' | 'fill' | 'none' | 'scale-down';
layout?: 'intrinsic' | 'fixed' | 'fill' | 'responsive';
isCircle?: boolean;
css?: Interpolation<Theme>;
}
const StyledImageContainer = styled.div`
overflow: hidden;
${({
width,
height,
margin,
padding,
position,
isCircle,
}: Partial<ImageContainerProps>) => css`
${position ? `position: ${position};` : ''}
width: ${typeof width === 'string' ? width : `${width}px`};
height: ${typeof height === 'string' ? height : `${height}px`};
padding: ${typeof padding === 'string' ? padding : `${padding}px`};
margin: ${typeof margin === 'string' ? margin : `${margin}px`};
border-radius: ${isCircle ? '50%' : 0};
`}
`;
const ImageContainer: React.FC<ImageContainerProps> = ({
src,
alt,
width = 40,
height = 40,
margin = 0,
padding = 0,
position = undefined,
placeholder = 'empty',
isCircle = false,
objectFit = 'cover',
layout = 'intrinsic',
sizes = '100vw',
...props
}) => {
return (
<StyledImageContainer
{...props}
width={width}
height={height}
margin={margin}
padding={padding}
isCircle={isCircle}
position={position}
>
<NextImage
src={src}
alt={alt}
width="100%"
height="100%"
placeholder={placeholder}
layout={layout}
sizes={layout === 'fill' || layout === 'responsive' ? sizes : undefined}
objectFit={objectFit}
/>
</StyledImageContainer>
);
};
export default ImageContainer;
즉, css
적인 요소는 위의 요소에 위임하고, 나머지 요소들은 NextImage
에 위임하는 꼴이다.
결과적으로 어떻게 동작할까?
<div>
{Array.from(new Array(20), (_, k) => k).map((i) => (
<ImageContainer
key={i}
isCircle
src={`https://picsum.photos/${i + 1}00`}
alt="사진 테스트"
css={{ display: 'inline-block' }}
/>
))}
</div>
호출할 때 전달한 css
Prop
이 옵션 값에 따라 잘 동작한다!