본문 바로가기

Front-End/React

React #10 (CSS - flexbox layout)

반응형

※ 사전 작업

더보기

깃허브 레포로 가서 실습에 쓸 파일만 가져오기 (ch03 > ch03_3 폴더)

https://github.com/yisj777s/doit-react-webapp-typescript/tree/main

터미널에서 아래 코드를 쳐서 그 아래에 있는 캡처(package.json)에 들어간 패키지들 일괄 설치

npm i -D

 

 ※ 문제 없이 진행하기 위해서는 구버전 설치가 필요 (테일윈드, 데이지ui)

npm i chance luxxon @fontsource/material-icons
npm i -D @types/chance @types/luxon
npm i -D postcss autoprefixer tailwindcss@3.4.14
npm i -D @tailwindcss/line-clamp daisyui@4.12.14

 

 이전 실습 파일 가져오고 정리

cp -r ../ch03_3/src/* ./src		# 이전 프로젝트 폴더에서 현재 폴더로 복사
cp -r ../ch03_3/*.js .			# 폴더 복사한 후 .js 파일도 전부 복사
rm src/pages/*				# 새로 실습할 것이기 때문에 기존 pages 안 파일들 삭제

 

템플릿을 복사해서 실습파일에 쓰일 컴포넌트 파일들 만들기

cd src
cp copy/CopyMe.tsx pages/DirectionTest.tsx
cp copy/CopyMe.tsx pages/WrapTest.tsx
cp copy/CopyMe.tsx pages/MinMaxTest.tsx
cp copy/CopyMe.tsx pages/JustifyCenterTest.tsx
cp copy/CopyMe.tsx pages/AlignTest.tsx
cp copy/CopyMe.tsx pages/User.tsx
cp copy/CopyMe.tsx pages/UserContainer.tsx
cp copy/CopyMe.tsx pages/Card.tsx
cp copy/CopyMe.tsx pages/CardContainer.tsx
cd ..

 

컴포넌트 파일들을 미리 페이지 안에 넣어두기

import DirectionTest from './pages/DirectionTest'
import WrapTest from './pages/WrapTest'
import MinMaxTest from './pages/MinMaxTest'
import JustifyCenterTest from './pages/JustifyCenterTest'
import AlignTest from './pages/AlignTest'
import UserContainer from './pages/UserContainer'
import CardContainer from './pages/CardContainer'

export default function App() {
  return (
    <main>
      <CardContainer />
      <UserContainer />
      <AlignTest />
      <JustifyCenterTest />
      <MinMaxTest />
      <WrapTest />
      <DirectionTest />
    </main>
  )
}

 

 (여기 글에서는 몇 개만 실습하는 걸로...)

 

 

Direction Test

src/pages/DirectionTest.tsx

import {Div, Title, Subtitle} from '../components'
import * as D from '../data'

export default function DirectionTest() {

  const boxes = D.range(1, 9 + 1).map(number => {
  
    return (
      <p key={number} className={`p-1 mt-1 ml-1 border-2 border-blue-300`}>
        {number}
      </p>
    )
  })
  
  
  return (
    <section>
      <Title>DirectionTest</Title>
      <Div className="flex flex-row mt-4">
      
        <Div className="mr-2">
          <Subtitle>flex-row</Subtitle>
          <Div className="flex flex-row p-4">{boxes}</Div>
        </Div>
        
        <Div className="mr-2">
          <Subtitle>flex-row-reverse</Subtitle>
          <Div className="flex flex-row-reverse p-4">{boxes}</Div>
        </Div>
        
        <Div className="mr-2">
          <Subtitle>flex-col</Subtitle>
          <Div className="flex flex-col p-4">{boxes}</Div>
        </Div>
        
        <Div className="mr-2">
          <Subtitle>flex-col-reverse</Subtitle>
          <Div className="flex flex-col-reverse p-4">{boxes}</Div>
        </Div>
        
      </Div>
    </section>
  )
}

 

 

 

 

MinMaxTest

 

일단 아래 경로로 파일 하나 만들자 (타입 만들기)

touch src/components/MinMaxWidthHeight.ts

 

타입 정의

src/components/MinMaxWidthHeight.ts

export type MinMaxWidthHeight = {
  minWidth?: string
  maxWidth?: string
  minHeight?: string
  maxHeight?: string
}

 

위에서 정의한 타입을 반영

src/components/Div.tsx

import type {FC, DetailedHTMLProps, HTMLAttributes, PropsWithChildren} from 'react'
import type {WidthHeight} from './WidthHeight'
import type {LeftRightTopBottom} from './LeftRightTopBottom'
import type {MinMaxWidthHeight} from './MinMaxWidthHeight'


export type ReactDivProps = DetailedHTMLProps<
  HTMLAttributes<HTMLDivElement>,
  HTMLDivElement
>

export type DivProps = ReactDivProps &
  PropsWithChildren<WidthHeight> &
  LeftRightTopBottom &
  MinMaxWidthHeight & {
    src?: string
  }

//prettier-ignore
export const Div: FC<DivProps> = ({
  width, height, 
  style: _style, 
  src, 
  className: _className,
  left, right, top, bottom, 
  minWidth, maxWidth, minHeight, maxHeight, 
  ...props
}) => {
  
  const style = {
    ..._style, 
    width, height, 
    backgroundImage: src && `url(${src})`,
    left, right, top, bottom, 
    minWidth, maxWidth, minHeight, maxHeight
  }

  const className = ['box-border', src && 'bg-gray-300', _className].join(' ')
  return <div {...props} className={className} style={style} />
}

 

반영한 타입으로 사용해보자

import {Div, Title} from '../components'
import * as D from '../data'


export default function MinMaxTest() {

  // prettier-ignore
  return (
    <section className="mt-4">
      <Title>MinMaxTest</Title>
      
      <Div className="p-4 bg-gray-300">
        <Div src={D.randomImage(800, 300)} className="bg-cover">
          <Div className="w-1/2 bg-blue-500 h-80" 
            minWidth="300px" maxWidth="500px" />
        </Div>
      </Div>
      
    </section>
  )
}

 

 

 

 

 

 

 

JustifyCenter (주축 정렬)

바닐라 CSS에서 구현했었던 flex관련 속성 중, justify-content: center; 도 여기서 구현해보자.

 

src/pages/JustifyCenterTest.tsx

import {Div, Title, Subtitle} from '../components'
import * as D from '../data'

export default function JustifyCenterTest() {

  const boxes = D.range(0, 5).map(index => (
    <Div key={index} className="w-4 h-4 m-1 bg-black" />
  ))

  return (
    <section className="mt-4">
    
      <Title>JustifyCenterTest</Title>
      
      <div className="mt-4">
        <Subtitle>flex flex-row justify-center</Subtitle>
        <div className="flex flex-row justify-center h-40 bg-gray-300">{boxes}</div>
      </div>
      
      <div className="mt-4">
        <Subtitle>flex flex-col justify-center</Subtitle>
        <div className="flex flex-col justify-center h-40 bg-gray-300">{boxes}</div>
      </div>
      
    </section>
  )
}

 

 

 

 

AlignTest (교차축 정렬)

바닐라 CSS에서 구현했었던 flex관련 속성 중, align-items: center; 도 여기서 구현해보자.

 

src/pages/AlignTest.tsx

import {Title, Subtitle} from '../components'
import * as D from '../data'


export default function AlignTest() {

  const boxes = D.range(0, 5).map(index => {
    return <div key={index} className="w-4 h-4 m-1 bg-black" />
  })
  
  const boxesForStretch = D.range(0, 10).map(index => {
    return <div key={index} className="w-4 m-4 bg-black" />
  })
  
  // prettier-ignore
  const justifies = ['justify-start', 'justify-center', 'justify-end', 'justify-between', 'justify-around', 'justify-evenly'].map(justify => (
    <div key={justify} className="mt-4">
      <Subtitle>flex flex-row {justify}</Subtitle>
      <div className={`flex flex-row ${justify} p-2 bg-gray-300`}>{boxes}</div>
    </div>
  ))
  
  const items = ['items-start', 'items-center', 'items-end'].map(item => (
    <div key={item} className="p-2 ml-4">
      <Subtitle>flex flex-row {item}</Subtitle>
      <div className={`flex flex-row ${item} h-20 bg-gray-300`}>{boxes}</div>
    </div>
  ))

  return (
  
    <section className="p-4 mt-4">
    
      <Title>AlignTest</Title>
      
      {justifies}
      {items}
      
      <div className="p-2 ml-4">
        <Subtitle>flex flex-row items-stretch</Subtitle>
        <div className="flex flex-row items-stretch h-20 bg-gray-300">
          {boxesForStretch}
        </div>
      </div>
      
    </section>
  )
}

 

 

 

CSS로 구현했었던 컨테이너 내의 아이템들의 정중앙 배치는

flex에 flex-row 에 justify-center와 items-center를 동시에 걸면 될 것 같다.

.container {
  display: flex;
  flex-direction: row; 		/* 가로 방향 */
  justify-content: center; 	/* 가로로 가운데 정렬 */
  align-items: center; 		/* 세로로 가운데 정렬 */
}

 

src/pages/AlignTest.tsx (하단 부 section 안쪽 맨 아래에 추가)

 

 

 

 

반응형

'Front-End > React' 카테고리의 다른 글

React #12-1 (CSS - daisyUI: Button & Icon)  (0) 2025.07.14
React #11 (CSS - user & card)  (0) 2025.07.14
React #9 (CSS - 박스모델)  (2) 2025.07.10
React #8 (CSS - TailwindCSS)  (0) 2025.07.10
React #7 (CSS - 아이콘)  (2) 2025.07.09