IT/React

React 실습 - Overlay

루벤초이 2021. 3. 15. 21:20

오늘은 Overlay(오버레이)에 대해 알아보겠습니다.

 

Overlay란, 어떤 HTML 엘리먼트 위에 또 다른 HTML 엘리먼트가 겹치게 보이는 효과인데요, 이것을 별도로 다루는 이유는, 경험상 Overlay를 자주 쓰면서도 매번 용법을 까먹거나 헷갈리기 십상이기 때문입니다. Overlay를 익히기 위한 효과적인 방법 중 하나는 직접 코드를 수정해 가면서 이해하는 것인데, 이 때 HTML 엘리먼트마다 테두리가 보이게 해서 즉, 스타일의 border 속성을 '1px solid green' 등으로 부여해서 직접 영역을 확인하는 것이 좋습니다.

 

자, 이제 예제 코드를 갖고 놀면서 Overlay를 이해해봅시다.

 

예제 코드:  Sample Code
소스위치: src/tutorial/Tutorial02-Overlay.js

 

결과를 먼저 볼까요? 예제 코드를 받아 실행 후 브라우저로 http://localhost:3000/test02 접속하면 아래와 같은 화면이 나옵니다.

 

실행 화면

 

예제 코드

import React from 'react';
import { Card, CardBody, CardImg, CardSubtitle, CardText, CardTitle } from 'reactstrap';

function TestOverlay() {
  return (
    <div style={{ width: '100vw', height: '100vh', padding: '3em', backgroundImage: "url('/images/cover.jpg')" }}>
      <div style={{ width: '300px', padding: '2em', background: 'rgba(255, 255, 255, 0.5)', border: '2px solid gray' }}>
        <Card>
          <CardImg top src="/images/logo.jpg" alt="Ruben Choi" />
          <CardBody>
            <CardTitle tag="h5">루벤초이</CardTitle>
            <CardSubtitle tag="h6" className="mb-2 text-muted">React 3D</CardSubtitle>
            <CardText>루벤초이는 IT 개발자일까요 뮤지션일까요? 멜론에서 루벤초이를 검색해보세요.</CardText>
          </CardBody>
        </Card>
      </div>
    </div >
  );
}

export default TestOverlay;

이 코드에서는 <div> 엘리먼트 안에 <div> 엘리먼트가 중첩되어 있고 그 안에 Reactstrap 라이브러리의 <Card> 컴포넌트가 있습니다. Reactstrap에 대해 궁금하다면▶ 관련글

 

첫 번째 <div>의 style 속성에서 backgroundImage를 url로 주면, 배경 이미지를 설정할 수 있습니다.

 

이때, url이 절대경로('/')로 시작하는데 이 절대경로는 public 폴더를 가리키게 됩니다. React 앱을 실행하면 로컬 웹서버가 뜨고 브라우저로 localhost:3000로 접속해서 React 앱을 실행하게 됩니다. 따라서 위 예제에서 backgroundImage의 url은 엄밀히 말하자면 http://localhost:3000/images/cover.jpg가 됩니다. 소스 코드 상에서는 public에 넣어둬야 로컬 웹서버에서 이 public 폴더를 여는 것이죠.

 

참고로 원래 CSS 스펙에서 배경이미지 속성은 background-image로 정의되어 있는데, React 컴포넌트의 style 속성에서는 보통 대쉬(-)를 빼고 다음 글자를 대문자로 해서 사용합니다. (e.g. background-image > backgroundImage)

 

또한 첫 번째 <div>의 style 속성에서 넓이와 높이에 각각 vw, vh 단위를 사용했는데 이는 viewport width(vw), viewport height(vh)의 약자로 viewport, 즉 디스플레이의 넓이와 높이의 퍼센트를 나타냅니다. 가령 800x600 디스플레이에서 10vw는 넓이의 10%이므로 80픽셀이 되고 1200x1000 디스플레이에서는 10vw가 120픽셀이 됩니다. 이렇게 되면, 디스플레이 사이즈마다 예쁘게 변하는 반응형 웹에서 아주 편리하겠죠.

 

두 번째 <div>를 살펴 보면, 넓이를 300픽셀로 정했고 background를 rgba 값을 줬습니다. rgba는 투명도(마지막 a가 alpha를 의미함)를 가진 색상값인데, 0.0~1.0 값을 갖습니다. 또한 border 속성을 빨강 실선 값('1px solid gray')으로 주어 엘리먼트 위치를 디버깅할 수 있도록 했습니다.

 

<Card> 컴포넌트는 위에 나온 그림과 글씨 카드를 보여주는 항목이니 따로 설명이 필요 없겠네요. 자, 이제 미션을 수행해봅시다.

 

미션 I

  • 미션: 카드 엘리먼트를 항상 맨 위에 나오게 해 보세요.
  • 힌트: position 속성을 사용합니다.

해보셨나요?

  • 정답: 두 번째 <div> 엘리먼트의 style 속성에 position: "absolute", top: 0, left: 0 를 추가합니다.
<div style={{ position: "absolute", top: 0, left: 0, width: '300px', padding: '2em', background: 'rgba(255, 255, 255, 0.5)', border: '2px solid gray' }}>

먼저 실행해 볼까요? 오, 딱 붙었네요~ 통과!

position: 'absolute' 적용

position 속성은 해당 엘리먼트를 어떻게 배치할지 정의합니다.

 

속성값에는 static, relative, fixed, absolute, sticky 등이 있지만, 개인적으로 여기서 사용된 absolute 속성을 자주 사용합니다. Overlay를 구현하기 위해 반드시 필요한 속성인데요, absolute란 말 그대로 절대적인 위치에 엘리먼트를 배치하겠다는 의미입니다.

 

뒤이어 나오는 top, left, right, bottom 값은 해당 방향에서 얼마나 띄우겠냐는 의미인데, 가령 top: 10%를 준다면 화면 맨 꼭대기에서 10% 떨어진 곳에 배치하겠다는 의미죠.

 

여기서는 소개하지 않았지만 zIndex라는 중요한 속성이 있는데요, 만일 엘리먼트가 여러 개일 경우 서로 가리는 현상이 발생할 수 있습니다. 이때, zIndex 값이 높을수록 앞으로 배치됩니다. 즉, 아래 코드에서 'second' <div>가 'first' <div>를 가립니다. 

<div id='first' style={{position: 'absolute', zIndex:3}}>First</div>
<div id='second' style={{position: 'absolute', zIndex:5}}>Second</div>

미션 I 클리어!

 

미션II

  • 미션: 전체 화면 상단에 공백을 넣고 싶어서 첫 번째 <div>에 margin을 넣었는데 그림처럼 두 번째 <div>는 margin이 적용되지 않았습니다. 
  • 조건: 두 번째 <div> 엘리먼트 style을 변경하지 않는다. 즉, 첫 번째 <div>만 수정할 수 있다.
<div style={{ margin: '3em', width: '100vw', height: '100vh', ...

첫 번째 div에 margin을 준 결과

정답은 맨 밑에.


풀어 보셨나요?

 

Overlay는 자주 사용하면서도 확실히 이해하지 않으면 항상 헷갈립니다.

실제 코드를 돌려보는 것이 기억에 남을 것 같아서, 겪었던 내용으로 준비해 본 내용이었습니다.


정답!   position: "relative"를 추가합니다.

<div style={{ position: "relative", margin: '3em', width: '100vw', ......

 

 

728x90
반응형