ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [React] How to make responsive components according to the screen size.(리엑트 화면 사이즈에 따른 반응형 컴포넌트 만들기)
    Frontend/react 2020. 10. 16. 15:55

     

     

     

    요즘 반응형 웹 페이지 제작은 필수이다.

    리엑트로도 당연히 가능하다.

     

    현재 페이지의 대부분을 material-ui의 Grid를 사용해서 레이아웃을 관리한다.

    그런데 브라우저 창 크기의 변화에 따라 direction을 row에서 column으로 변경하고 싶은데

    Grid에서 그런 기능을 해주는 부분은 찾지 못했다.

     

     

    (결론부터 보고 싶으면 스크롤을 좀 내리길.)

     


     

    일단 구글링,, 이곳저곳 찾아봤다.

    'flex'

    'flex-direction'

    과 같은 키워드로 많은 글들이 보이는데, 거의 레이아웃에 대한 기본적인 설명이었다.

    그러다 w3schools.com에서 한가지를 발견했다.

    www.w3schools.com/cssref/css3_pr_flex-direction.asp

    @media를 사용한 예제로 친절하게 데모도 확인 가능하다.

    <!DOCTYPE html>
    <html>
    <head>
    <style>
    * {
      box-sizing: border-box;
    }
    
    .flex-container {
      display: flex;
      flex-direction: row;
      font-size: 30px;
      text-align: center;
    }
    
    .flex-item-left {
      background-color: #f1f1f1;
      padding: 10px;
      flex: 50%;
    }
    
    .flex-item-right {
      background-color: dodgerblue;
      padding: 10px;
      flex: 50%;
    }
    
    /* Responsive layout - makes a one column-layout instead of two-column layout */
    @media (max-width: 800px) {
      .flex-container {
        flex-direction: column;
      }
    }
    </style>
    </head>
    <body>
    
    <h1>Responisve Flexbox</h1>
    
    <p>The "flex-direction: row;" stacks the flex items horizontally (from left to right).</p>
    <p>The "flex-direction: column;" stacks the flex items vertically (from top to bottom).</p>
    <p><b>Resize the browser window to see that the direction changes when the 
    screen size is 800px wide or smaller.</b></p>
    
    <div class="flex-container">
      <div class="flex-item-left">1</div>
      <div class="flex-item-right">2</div>
    </div>
    
    </body>
    </html>
    

     

    그럼 여기서 나는 저 @media 쿼리 부분을 어떻게 리엑트에 적용할것인가가

    앞으로 풀어야할 문제이다.

     

    material-ui 사이트에 보면 useMediaQuery를 사용하는 API 문서가 있다. 링크

    데모

    import React from 'react';
    import mediaQuery from 'css-mediaquery';
    import { ThemeProvider } from '@material-ui/core/styles';
    import useMediaQuery from '@material-ui/core/useMediaQuery';
    
    function MyComponent() {
      const matches = useMediaQuery('(min-width:600px)');
    
      return <span>{`(min-width:600px) matches: ${matches}`}</span>;
    }
    
    export default function ServerSide() {
      const ssrMatchMedia = (query) => ({
        matches: mediaQuery.match(query, {
          // The estimated CSS width of the browser.
          width: 800,
        }),
      });
    
      return (
        <ThemeProvider
          theme={{
            props: {
              // Change the default options of useMediaQuery
              MuiUseMediaQuery: { ssrMatchMedia },
            },
          }}
        >
          <MyComponent />
        </ThemeProvider>
      );
    }

     

    자 이제 저 둘을 엮어서 코드를 짜면 될 것이다.

     

     

    그러려고 하던 찰나에 다른 일들이 생기면서 하루동안 손을 못댔다.

     


     

    하루 지나서 다시 하려니 그전에 알아 놓았던게 기억이 잘 나질 않아

     

    습관처럼 다시 구글 검색을 했다.

    그래서 이 문제를 다르게 해결했다. (참고)

     

    이 글을 쓰게 된 이유가 여기서 나온다.

    참고 사이트를 보면 핵심만 있고,

    나같이 리엑트 초보자들은 핵심만 봐도 헤매는 경우가 많다.

    그런 분들이 이 글을 보고 조금이나마 도움을 얻길 바란다.

     

     

    먼저 styled-components 모듈을 설치해주자.

    yarn add styled-components
    
    or
    
    npm install --save styled-components
    

     

    사용할 컴포넌트에 아래의 코드를 추가해주자. (또는 module로 만들어서 import)

    import styled from "styled-components";
    
    
    const calcWidthPercent = span => {
        if (!span) return;
      
        const width = (span / 12) * 100;
    
        return width;
      };
      
      const BREAK_POINT_MOBILE = 800;
      const BREAK_POINT_TABLET = 992;
      const BREAK_POINT_PC = 1200;
      
      const Column = styled.div`
        float: left;
        width: ${({ xs }) => (xs ? `${calcWidthPercent(xs)}%` : `100%`)};
        padding: 0rem;
        margin: 0rem;
      
        @media only screen and (min-width: ${BREAK_POINT_MOBILE}px) {
          width: ${({ sm }) => sm && `${calcWidthPercent(sm)}%`};
        }
        @media only screen and (min-width: ${BREAK_POINT_TABLET}px) {
          width: ${({ md }) => md && `${calcWidthPercent(md)}%`};
        }
        @media only screen and (min-width: ${BREAK_POINT_PC}px) {
          width: ${({ lg }) => lg && `${calcWidthPercent(lg)}%`};
        }
      `;

     

     

    Row안에 두개의 Column이 있는데

    이제 윈도우 창 크기에 따라 지정해준 비율로 Column들이 위치한다.

    전부 12로 하면 direction이 row 에서 column으로 된다

    return (
    	<Grid container spacing={1} justify="center" alignItems="center">
                <Grid item xs={12} spacing={0}>
                  <Row>
                    <Column xs={12} sm={12} md={6} lg={7}>
                      <Component1/>
                    </Column>
                    <Column xs={12} sm={12} md={6} lg={5}>
                      <Component2 />
                    </Column>
                  </Row>
                </Grid>
              </Grid>
    )

     

    이제 원하던 대로 된다.

     

    댓글

Designed by Tistory.