STUDY/React

React | 반응형 테이블을 만들어보자..

개미606 2021. 11. 12. 10:02

테이블처럼 보이지만 <table/>은 사용하지 않는다..

결과물

데스크탑에서는 이렇게 보이고,

모바일에서는 이렇게 되도록 만들거다.

원하는 거..

  • 제목 셀은 항상 존재하고 제목 셀의 넓이는 항상 일정하다.
  • 모바일에서는 제목, 내용 한 쌍이 무조건 한 열을 다 차지한다.
  • 한 열에 두 개 혹은 네 개의 셀이 들어갈 수 있다.

컴포넌트 만들기..

  • Table: 테이블 전체를 감싸는 div
  • TableRow: 한 열을 감싸는 div
  • TableCell: 제목 + 내용으로 이루어진 한 쌍

일단 styled-components를 사용하기 떄문에 스타일을 정의할 파일을 하나 생성한다.

// Table.styled.js
import styled from 'styled-components';

export const StyledTable = styled.div`

`;

export const StyledTableRow = styled.div`

`;

export const StyledTh = styled.div`

`;

export const StyledTd = styled.div`

`;

Table

Table컴포넌트는 전체 테이블 내용을 감싸는 컴포넌트 children만 props로 받아 감싸주면 끝

// Table.js
import { StyledTable } from './Table.styled';

const Table = ({ children }) => {
  return <StyledTable>{children}</StyledTable>;
};

export default Table;

css는 대충 원하는대로 해주면 된다.. display: flex; flex-dirction: column;이 필수

//Table.styled.js
export const StyledTable = styled.div`
  padding: 1rem;
  background: #fff;
  border-radius: 1rem;
  display: flex;
  flex-direction: column;
`;

TableRow

TableRow는 한 열이 된다. 테이블 셀을 감싸주는 컴포넌트.

// TableRow.js
import { StyledTableRow } from './Table.styled';

const TableRow = ({ children }) => {
  return <StyledTableRow>{children}</StyledTableRow>;
};

export default TableRow;

display: flex;를 주어 셀들이 가로 방향으로 나열되도록 설정..

//Table.styled.js
export const StyledTableRow = styled.div`
  display: flex;
  flex-wrap: wrap;
`;

TableCell

TableCell은 제목과 내용의 한 쌍으로 이루어진다.

//TableCell.js
import { StyledTh, StyledTd } from './Table.styled';

const TableCell = ({ title, value }) => {
  return (
    <>
      <StyledTh>{title}</StyledTh>
      <StyledTd>{value}</StyledTd>
    </>
  );
};

export default TableCell;

display: flex; align-items: center;는 항상 내용이 세로 중심에 위치하도록 하기 위한 설정이다.
여기서 중요한건 flex: 0 0 10rem; width: 10rem;설정..
flex-basis값을 10rem으로 주고, width를 10rem으로 주면 항상 제목 셀의 넓이가 일정하게 유지된다.
내용 셀(StyledTd)은 flex: 1;을 주어 제목셀 제외 남은 공간을 다 차지하도록 한다.

//Table.styled.js
export const StyledTh = styled.div`
  display: flex;
  align-items: center;
  flex: 0 0 10rem;
  width: 10rem;
  color: ${({ theme }) => theme.gray};
  background: #c3c7d926;
  font-weight: 600;
  padding: 1rem;
  word-break: keep-all;
`;

export const StyledTd = styled.div`
  display: flex;
  align-items: center;
  padding: 1rem;
  flex: 1;
  word-break: keep-all;
`;

모바일 css

TableCell부분만 미디어쿼리를 사용하면 된다..
flex설정을 이용해서 셀들이 밑으로 붙도록..?

export const StyledTh = styled.div`
  display: flex;
  align-items: center;
  flex: 0 0 10rem;
  width: 10rem;
  color: ${({ theme }) => theme.gray};
  background: #c3c7d926;
  font-weight: 600;
  padding: 1rem;
  word-break: keep-all;
  @media (max-width: ${({ theme }) => theme.mobile}) {
    padding: 0.8rem;
    flex: 1 1 37%;
  }
`;

export const StyledTd = styled.div`
  display: flex;
  align-items: center;
  padding: 1rem;
  flex: 1;
  word-break: keep-all;
  @media (max-width: ${({ theme }) => theme.mobile}) {
    padding: 0.8rem;
    flex: 1 1 63%;
  }
`;

border설정

border가 생각보다 까다로웠다.. 왜냐면나는바보라서...
TableRowfist-child설정을 이용해서 border값을 준다. 무조건 첫 번째 열은 border-top을 설정

export const StyledTableRow = styled.div`
  display: flex;
  flex-wrap: wrap;
  &:first-child {
    border-top: 1px solid ${({ theme }) => theme.lightGray};
  }
`;

그리고 TableCell은 이제 미디어쿼리랑도 조합해야 함..

export const StyledTh = styled.div`
  /* 생략 */
  border-bottom: 1px solid ${({ theme }) => theme.lightGray};
  &:first-child {
    border-left: 1px solid ${({ theme }) => theme.lightGray};
  }
  @media (max-width: ${({ theme }) => theme.mobile}) {
    padding: 0.8rem;
    flex: 1 1 37%;
    border-left: 1px solid ${({ theme }) => theme.lightGray};
  }
`;

export const StyledTd = styled.div`
  /* 생략 */
  border-left: 1px solid ${({ theme }) => theme.lightGray};
  border-right: 1px solid ${({ theme }) => theme.lightGray};
  border-bottom: 1px solid ${({ theme }) => theme.lightGray};
  word-break: keep-all;
  @media (max-width: ${({ theme }) => theme.mobile}) {
    padding: 0.8rem;
    flex: 1 1 63%;
  }
`;

끝..


A Complete Guide to Flexbox