TL;DR
그리드, 플렉스를 사용하는 경우가 아니면서 마진이 필요한 경우, Spacer 컴포넌트를 고려해본다.
HomeButton 컴포넌트를 만들어 봅시다.
function HomeButton() {
return (
<LinkButton href="/">
<BackIcon />
Go back home
</LinkButton>
);
}
render(<HomeButton />);
화살표가 텍스트에 너무 붙어있는것 같네요. 약간 조절해봅시다.
1. 마진 활용
function HomeButton() {
return (
<LinkButton href="/">
<BackIcon />
<span
style={{ marginLeft: 16}}
>
Go back home
</span>
</LinkButton>
);
}
render(<HomeButton />);
2. Spacer 활용
역사적 문맥
<img alt="" src="spacer.gif" width="1" height="1" />
10년 동안 모든 사람들은 각 관심사에 대해 별개의 기둥(pillars)을 갖는 것이 좋은 생각이라는 데 동의했습니다.
그리고 Facebook은 React.js를 출시했습니다...
그리고 많은 것이 변했습니다.
React.js의 유명한 특징 중 하나는 HTML이 JS 내에서 생성된다는 것입니다.
styled-components와 같은 도구를 추가하면 세 개의 기둥이 하나로 병합됩니다.
React는 Facebook과 같이 거대하고 거대한 웹 애플리케이션의 복잡성을 관리하는 데 있어 부인할 수 없는 강력한 도구입니다.
이것은 수년 전에 기술로 관심사를 분리한게 잘못된 선택임을 의미하나요?
저는 그렇게 생각하지 않습니다. 저는 2000년대에도 웹 개발을 했었지만, 그 당시 웹 개발 씬은 황무지나 다름없었고
HTML을 동적으로 업데이트 하는 JS 생성을 위해 PHP를 사용하던 시대입니다.
중요한 것은 (컴포넌트 간) 경계선을 그릴 수 있다는 것입니다.
그 선들이 어떤 축을 가로질러 그려지는지는 덜 중요합니다.
코드 보기
저는 다음과 같이 스페이서 컴포넌트를 작성합니다.
(마진을 width로 대체)
// Spacer.js
import styled from 'styled-components';
function getHeight({ axis, size }) {
return axis === 'horizontal' ? 1 : size;
}
function getWidth({ axis, size }) {
return axis === 'vertical' ? 1 : size;
}
const Spacer = styled.span`
display: block;
width: ${getWidth}px;
min-width: ${getWidth}px;
height: ${getHeight}px;
min-height: ${getHeight}px;
`;
export default Spacer;
// Spacer.js
import React from 'react';
const Spacer = ({
size,
axis,
style = {},
...delegated,
}) => {
const width = axis === 'vertical' ? 1 : size;
const height = axis === 'horizontal' ? 1 : size;
return (
<span
style={{
display: 'block',
width,
minWidth: width,
height,
minHeight: height,
...style,
}}
{...delegated}
/>
);
};
export default Spacer;
필수 prop은 size 뿐입니다. 기본적으로 정사각형을 만듭니다.
// Produces a 16px × 16px gap:
<Spacer size={16} />
// Produces a 32px × 1px gap:
<Spacer axis="horizontal" size={32} />
이 컴포넌트는 픽셀 값을 사용합니다.
optical alignment를 위해 스케일을 벗어난 값을 선택해야 하는 경우가 많기 때문입니다.
즉, 이 패턴은 대신 디자인 토큰을 사용하도록 쉽게 조정할 수 있습니다.
<Spacer space="sm" />
<Spacer space="md" />
<Spacer space="lg" />
<Spacer space="xl" />
코드를 상세히 설명하도록 하겠습니다.
블록 span
const InlineSpacer = styled(Spacer)`
display: inline-block;
`;
최소 / 최대 크기
width, height 외에 min-width와 min-height도 설정합니다.
너비가 실제로는 제약이라기 보다는 제안이기 때문입니다.
function HomeButton() {
return (
<LinkButton href="/" style={{ maxWidth: 200 }}>
<BackIcon />
{/* Quick Spacer implementation */}
<span
style={{
display: 'inline-block',
width: 16,
height: 16,
background: 'hotpink',
}}
/>
Go back home
</LinkButton>
);
}
render(<HomeButton />);
반응형 버전
<Spacer
size={32}
when={{
lgAndUp: 64,
xlAndUp: 96,
}}
/>
나는 상황에 맞는 것들을 위해 when이라는 prop 이름을 사용하는 것을 좋아합니다.
이 prop의 구현은 특정 스타일링 솔루션과 테마에 따라 달라집니다.
Pros and cons
1.홈 버튼 예제에서 마진은 뒤로 화살표로 가야 할까요 아니면 텍스트로 가야 할까요?
어느 한 요소가 공간을 "소유"해야 하는 것처럼 느껴지지 않습니다.
이것은 별개의 레이아웃 관심사입니다.
2. 마진은 펑키합니다. 그들은 이상하고 놀라운 방식으로 겹칩니다.
3. 구조적 의미가 있습니다.
4. 마진은 근본적으로 현대적인 컴포넌트 아키텍처와 상충됩니다.
'갭' 애트리뷰트는요?
CSS 그리드로 작업 시 grid-gap을 사용할 수 있습니다.
grid-gap을 사용하면 직관적이고 의미론적인 방식으로 컨테이너의 모든 자식 사이에 간격을 설정할 수 있습니다.
저는 그리드 갭을 좋아합니다.
CSS 사양은 최근에 정확히 같은 방식으로 작동하지만 flexbox와 함께 사용할 수 있는 gap 속성을 추가했습니다.
이것은 훌륭합니다.💯
Browser support는 나날이 개선되고 있지만 사용하기에는 아직 시기 상조인것 같습니다.
완전히 지원되면 내 스페이서 컴포넌트가 불필요할까요?
저는 그렇게 생각하지 않습니다.
저는 여전히 그리드/플렉스 부모 외부의 "flow layout"에서 작업하는 데 많은 시간을 보냅니다.
gap은 우리의 많은 문제를 해결할 수 있지만 모든 문제를 해결하지는 못합니다.
사용 시 문제점?
개발자가 사용하기엔 좋은게 확실합니다만.
접근성 및 SEO와 같은 DOM 오염을 피해야 하는 다른 이유가 있습니다.
그러나 내가 아는 한, 몇 가지 여분의 빈 스팬은 이러한 측면에서 해롭지 않습니다.
마치며
'FrontEnd' 카테고리의 다른 글
useState의 함정 : useEffect와 사용 시 주의할 점. (0) | 2022.06.16 |
---|---|
useState와 useReducer의 사용사례 (0) | 2022.06.16 |
Styled-component와 Tailwind 함께 사용하기 with Twin Macro (0) | 2022.06.14 |
React Query에는 Debounce와 Throttling이 없다? (0) | 2022.06.13 |
대규모 프로젝트 React Query 아키텍처 (1) | 2022.06.11 |