CSS code를 component와 함께 작성할 수 있는 대표적인 library이다.
dynamic styling이 가능하다.
props로 넘겨주면서 adapting 가능
또한, Style을 확장시키거나 기존처럼 media query, nesting도 가능하다.
import React from 'react';
import styled from 'styled-components';
interface ButtonProps {
label: string;
}
function RoundButton({label}: ButtonProps) {
// code
// ...
return <ButtonStyle label={label}> This is button component </ButtonStyle>;
}
const ButtonStyle = styled.button<ButtonProps>`
color: turquoise;
label: ${props => props.label || ""};
`;
Styled Component에서 쓰이는 문법의 원리는 Tagged Template Literal이라는 문법이다.
백틱(``)을 이용해서 template literal을 표현한다.
// syntax
tag `
string text ${expression} string text
`
// 이 때 tag는 함수라고 한다.
예시로 다음처럼 사용할 수 있으며 console.log로 호출하면 expression과 문자열이 분리된다.
var person = 'NAME';
var age = 20;
function tag(strings, personExp, ageExp) {
console.log(strings, personExp, ageExp);
}
tag`Person ${person} is a ${age}`;
// [['Person', ' is a ', ''], 'NAME', 20]
그래서 styled component는 위 문법을 이용해서 각 tag마다 function을 실행한다고 생각할 수 있다.
css prop을 쓰는 것이 emotion의 주요 특징이다.
import React from 'react';
import styled from '@emotion/styled';
import { css } from '@emotion/react';
interface ButtonProps {
label: string;
color: string;
primary: boolean;
}
function Button({ label, color }: ButtonProps) {
const handleClick = () => {
alert('Clicked button!');
};
return (
<button
css={css`
padding: 32px;
font-size: 24px;
color: ${color};
font-weight: bold;
background-color: green;
&:hover {
background-color: green;
}
`}
onClick={handleClick}
>
${label}
</button>
);
}
export default Button;
styled prop으로 styled components 처럼도 사용할 수 있다.
import React from 'react';
import styled from '@emotion/styled'
interface ButtonProps {
label: string;
}
function RoundButton({label}: ButtonProps) {
// code
// ...
return <ButtonStyle label={label}> This is button component </ButtonStyle>;
}
const ButtonStyle = styled.button<ButtonProps>`
color: turquoise;
label: ${props => props.label || ""};
`;
두 특성을 통해 string style, object style 방식을 모두 사용 가능하다.
flexbox는 뷰포트나 요소의 크기가 불명확하거나 동적으로 변할 때에도 효율적으로 요소를 배치, 정렬, 분산할 수 있는 방법을 제공하는 CSS3의 새로운 레이아웃 방식이다. flexbox의 장점을 한 마디로 표현하면 '복잡한 계산 없이 요소의 크기와 순서를 유연하게 배치할 수 있다' 라고 할 수 있다. 정렬, 방향, 순서, 크기 등을 유연하게 조절할 수 있기 때문에 별도의 분기 처리를 줄일 수 있고, CSS만으로 다양한 레이아웃을 구현할 수 있다.
.flex_container {
display: flex;
}
display를 부모요소에 flex속성을 선언해서 사용한다.
flexbox는 박스가 수직으로 분할되는 것이 기본값이다. 그러나 방향을 설정해주면, 수평으로도 분할할 수 있다. flex-direction 속성은 부모 박스요소에 적용한다. 자식 박스에 특별한 속성을 주지 않아도, 부모 요소에 의해 자식 요소가 영향을 받는다.
-> 반드시 알아두자 : grow(팽창 지수), shrink(수축 지수), basis(기본 크기)
자식 박스에 어떠한 속성도 주지 않으면, 왼쪽에서부터 오른쪽으로 콘텐츠의 크기만큼 배치된다. 자식 요소의 flex 속성을 추가하지 않으면, 다음과 같은 기본값이 적용된다.
flex: 0 1 auto;
flex: grow(팽창 지수), shrink(수축 지수), basis(기본 크기)
margin이나 padding에서 상하좌우 각 방향을 따로 지정할 수 있었던 것처럼, flex에 적용되는 grow, shrink, basis도 각 값을 따로 지정할 수 있다.
아래의 target 클래스에서, flex-grow 속성의 값을 1로 변경하면 target 클래스를 가지고 있는 첫 번째 자식박스는, 부모 박스의 가로 길이 중에서 남은 빈 영역만큼 늘어나게 된다. 위 설명대로라면 전체 자식요소가 가진 grow 값의 합은 1+0+0 = 1이므로, target 클래스를 가지고 있는 자식 박스의 가로 크기는 1/1 = 100% 이다. 그러나 다른 자식 박스 안에 이미 콘텐츠가 존재하므로, 다른 자식 박스안의 콘텐츠가 담긴 길이를 제외한 나머지 가로 길이가 target 클래스를 가진 자식박스의 가로 길이이다.
.target {
flex: 1 1 auto;
}
실제 코드로 적용된 모습을 보게된다면 아래와 같다.
box 클래스의 flex-grow는 기본값인 0이다. 만약 box 클래스의 flex-grow 속성에 값을 1로 설정하면, 모든 박스가 늘어나려고(grow) 한다 결과적으로 모든 박스가 동일한 비율로 가로 길이가 난다. (총 grow 값 1+1+1, 각 박스는 1/3씩 크기를 가짐)
shrink는 grow와 반대로, 설정한 비율만큼 박스 크기가 작아진다. 그러나 flex-grow 속성과 flex-shrink 속성을 함께 사용하는 일은 추천하지 않습니다. 비율로 레이아웃을 지정할 경우 flex-grow 속성 또는 flex: 1 auto와 같이 grow 속성에 변화를 주는 방식을 권장한다. flex-shrink 속성은 width나 이후 설명할 flex-basis 속성에 따른 비율이므로 실제 크기를 예측하기가 어렵기 때문이다. flex-grow 속성으로 비율을 변경하는 경우, flex-shrink 속성은 기본값인 1로 두어도 무방하다.
실제 레이아웃을 하면서 여러 어려움이 있을때는 다음 원리를 생각해보자.
Flexbox를 원하는대로 제어하기 위해서는 axis(축)의 개념에 대한 이해가 필요하다.
axis는 main axis 와 cross axis로 구분합니다.
main axis 은 flex-direction 속성에 의해서 결정된다.
flex-direction의 기본 값인 row 인 상태일 때 main axis 는 가로축이 됩니다.
부모 박스에 justify-content 속성을 적용하면, 자식 박스를 수평으로 정렬할 수 있다. 다음은 justify-content 속성의 값이 될 수 있는 주요 옵션이다.
부모 박스에 align-items 속성을 적용하면, 자식 박스를 수직으로 정렬할 수 있습니다. 다음은 align-items 속성의 값이 될 수 있는 주요 옵션입니다. 한번씩 적용해보세요.