- 이전 JSX 작성 과정 링크 : https://kojammin.tistory.com/201
- CSS 예시자료 받을 수 있는 링크 : https://kojammin.tistory.com/199
▣저번 과정까지 기본 구조, 작동 부분을 구현했으니, 이제 CSS 스타일 작업으로 꾸미기를 하는 과정
◎ 6_ 전체 배경화면, 폰트의 Style 적용 => index.html의 style 시트에 직접 적용
- index.html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="utf-8" />
<title>주사위 게임</title>
<style>
body {
color: #fff;
font-family: 'NanumSquareRound', sans-serif;
background-color: #191f2c;
}
body div#root{
display : flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
</style>
</head>
<body>
<div id="root"></div>
</body>
</html>
● 출력 장면 :
◎ 7_ Header 부분
=> "F12"를 눌러 <div class="Header"> 부분이라는 것을 알 수 있다.
● 순서1_ [src]폴더에 [Style]폴더를 따로 생성, Header부분 담당의 [Header.css] 생성, <App> 컴포넌트에 import로 적용 하기
○ [src]폴더에 [Style] 폴더 생성 + [Style]폴더에 [Header.css] 생성
○ App.js에 [Header.css] 적용하기
- App.js 일부분
import { useState } from 'react';
import HeadImg from './assets/logo.png';
import Button from './Button';
import Board from './Board';
//CSS
import './Style/Header.css'
● 순서2_ <App> 컴포넌트에서 각 태그들에 class명 붙이기 => className 속성
- App.js 일부분
import { useState } from 'react';
import HeadImg from './assets/logo.png';
import Button from './Button';
import Board from './Board';
//CSS
import './Style/Header.css'
//... 생략
function App()
[
/.. 생략
return (
<>
<div className='Header'>
//<img> 태그에 class 속성 "Header-logo"
<img className='Header-logo' src={HeadImg} alt='head-logo-img'></img>
//<img> 태그에 class 속성 "Header-title"
<h1 className='Header-title'>주사위 게임</h1>
</div>
<div>
<Button onClick={handleRollClick}>던지기</Button>
<Button onClick={handleRollReset}>처음부터</Button>
</div>
<div className='Board'>
<Board name="나" color="blue" record={myRecord}></Board>
<Board name="상대" color="red" record={otherRecord}></Board>
</div>
</>
}
● 순서3_ [Header.css] 작성
- Header.css
.Header{
display : flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.Header .Header-logo{
height: 65px;
}
.Header .Header-title{
margin: 10px auto 28px;
font-size: 28px;
}
◎ 8_ Button 컴포넌트 style 시트 꾸미기
=> 같은 원리로 [Button.css] 생성 => Button.js에 import => CSS 코드 작성 //이과정은 생략함
★생각해야 될 개념1 : "던지기"버튼 => Blue , "처음부터"버튼 => Red
§ 해결방법 :
1_일단 CSS에는 기본 버튼 CSS 시트인 .Button 를 작성하고
2_1_"던지기" Button은 .Button .blue{} 클래스로 상속받아 적용되도록 한다.
2_2_"처음부터" Button은 .Button.red{} 클래스로 상속받아 적용되도록 한다.
- Button.css :
//버튼이면, 기본적으로 적용될 CSS
.Button {
min-width: 120px;
padding: 14px 27px;
border-radius: 9999px;
outline: none;
font-size: 18px;
font-family: 'NanumSquareRoundEB';
cursor: pointer;
}
//던지기 버튼 CSS = .Board + .Board.blue
.Button.blue {
border: 1px solid #7090ff;
color: #7090ff;
background-color: rgba(0, 89, 255, 0.2);
}
.Button.blue:hover {
background-color: rgba(0, 89, 255, 0.3);
}
//처음부터 버튼 CSS = .Board + .Board.red
.Button.red {
border: 1px solid #ff4664;
color: #ff4664;
background-color: rgba(255, 78, 78, 0.2);
}
.Button.red:hover {
background-color: rgba(255, 78, 78, 0.3);
}
● 순서1_ "던지기"<Button> 컴포넌트에 props.className 객체 프로퍼티에 "blue" 값을 대입하고, 전달받은 "blue" 값에 따라 class 상속으로 css 적용하기
○ Button.js 컴포넌트에 매개인자 className을 추가 + <button> 태그에 className 속성값 대입시 "blue" || "red"입력에 따라, .Button ."blue"||."red" 가 되도록 코드 작성
//Button.js
import './Style/Button.css';
function Button({onClick ,children, className=""})
{
return (<button className={`Button ${className}`} onClick = {onClick}>{children}</button>);
}
export default Button;
○ App.js에서, <Button>컴포넌트 태그에 props.className ="blue"를 "던지기"버튼 , props.className ="red"를 "처음부터"버튼에 적용
//App.js 일부
function App()
{
return (
<>
<div className='Header'>
<img className='Header-logo' src={HeadImg} alt='head-logo-img'></img>
<h1 className='Header-title'>주사위 게임</h1>
</div>
<div>
//던지기 버튼 "blue"을 className에 대입
<Button className="blue" onClick={handleRollClick}>던지기</Button>
//처음부터 버튼 "red"을 className에 대입
<Button className="red" onClick={handleRollReset}>처음부터</Button>
</div>
<div className='Board'>
<Board name="나" color="blue" record={myRecord}></Board>
<Board name="상대" color="red" record={otherRecord}></Board>
</div>
</>
);
}
export default Button;
● 출력 장면 :
★생각해야 될 개념2 :
- 버튼 요소 내부에 대한 꾸미기 => Button.css에 적용
- 버튼 요소 외부에 대한 꾸미기 => Button.css의 부모인 App.css에 적용
다시 말하면, "던지기"버튼과 "처음부터"버튼 사이의 거리 조절 => App.css에 적용
● 순서2_ [Style]폴더의 [App.css] 생성, 버튼 사이의 거리 조절 코드 작성
//App.css
.Middle-Button{
/*버튼 사이의 거리*/
display : flex;
gap : 20px;
}
◎ 9_ Board style 시트 꾸미기
§전략 :
Board 외부 : "나"와 "상대" 끼리는 거리를 좀 두기 => App.css에 작성
Board 내부 : 세로 중심으로 정렬 +> Board.css에 작성
- App.css
.Middle-Button{
/*버튼 사이의 거리*/
display : flex;
gap : 20px;
}
.Board-Box{
/*플레이어 박스의 배치*/
margin-top : 20px;
display : flex;
gap : 20px 20px;
}
- Board.css
.Board {
display : flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 35px 30px;
border: 1px solid transparent;
border-radius: 12px;
font-size: 16px;
text-align: center;
background-color: #272b38;
}
◎ 10_ Board 중 나온 눈의 수에 따라 승자 결정 + 승자를 나타내는 CSS 시트 적용
※꽤 고난이었음
■ 전략 :
● [Board.css]에 주사위 눈이 큰 Board에는 winner클래스 자식을 덧붙인다.
○ Board.css
.Board {
display : flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 35px 30px;
border: 1px solid transparent;
border-radius: 12px;
font-size: 16px;
text-align: center;
background-color: #272b38;
}
.Board.winner{
border: 1px solid #fff;
box-shadow: 0 0 12px 0 hsla(0, 0%, 100%, 0.48);
}
● [App.js]에 주사위 눈을 비교해서, "나"와 "상대" 중 눈이 높은 놈한테 winner 상속
○ App.js
import { useState } from 'react';
import HeadImg from './assets/logo.png';
import Button from './Button';
import Board from './Board';
//CSS
import './Style/Header.css';
import './Style/App.css';
import './Style/Board.css';
function randNum()//1~6 넌수 발생 메소드
{
return Math.floor(Math.random()*(6-0)) +1;
}
function App() {
//배열 선언
const [myRecord,setMyRecord] = useState([]);
const [otherRecord,setOtherRecord] = useState([]);
//★승자 결정 정보 변수=> Defalut 값으로 "" 초기값
const [winner,setWinner] = useState("");
//던지기에 대한 핸들러 메소드
const handleRollClick = ()=>
{
const blueNum = randNum();
const redNum = randNum();
// 기록 업데이트
setMyRecord((myRecord) => [...myRecord, blueNum]);
setOtherRecord((otherRecord) => [...otherRecord, redNum]);
/★ 버튼을 누를시, blueNum vs redNum 으로 승자 결정
if(blueNum>redNum)//내가 이겼을 때,
{
setWinner("나");
}
else if(blueNum<redNum)
{
setWinner("상대");
}
};
const handleRollReset = () =>
{
//기록을 빈 배열로 초기화
setMyRecord([]);
setOtherRecord([]);
}
return (
<>
<div className='Header'>
<img className='Header-logo' src={HeadImg} alt='head-logo-img'></img>
<h1 className='Header-title'>주사위 게임</h1>
</div>
<div className="Middle-Button">
<Button className='blue' onClick={handleRollClick}>던지기</Button>
<Button className='red' onClick={handleRollReset}>처음부터</Button>
</div>
<div className='Board-Box'>
<Board
//★삼항 연산자를 이용해, "나"가 승리할 시, className으로 "winner" 전달
className={`${(winner === "나") ? "winner" : ""}`}
name="나"
color="blue"
record={myRecord}
/>
<Board
className={`${(winner === "상대") ? "winner" : ""}`}
name="상대"
color="red"
record={otherRecord}
/>
</div>
</>
);
}
export default App;
● App.js에서 받은 props.winner 값을 [Board.js]에서 <div> 태그의 class값 적용
○ Board.js
import Dice from "./Dice";
import './Style/Board.css'
function Board({name, color,record, className}) {//★className 매개인자 추가
let num = 1;
if(record.length>0)
{
num = record[record.length-1]
}
const sum = record.reduce((a,b)=>a+b,0);
return (
<div className={`Board ${className}`}>
//★div 박스 board에 적용하여, "winner"값이면, 클래스 상속되고, 아니면 ,기본 .Board 클래스 css 적용된다.
<h2>{name}</h2>
<Dice color={color} num={num}></Dice>
<h2>총점</h2>
<p>{sum}</p>
<h2>기록</h2>
<p>{record.join(", ")}</p>
</div>
);
}
export default Board;
- 출력장면 :
'CodeIt_Sprint > React_초급' 카테고리의 다른 글
(17)React_초급_DiceGame_React_Project_1_JSX작성부분 (1) | 2024.11.26 |
---|---|
(16)React_초급_React_배포하기 (0) | 2024.11.25 |
(15)React_초급_React_Design_최종 실습문제 2문제(이건 여러번 복습) (0) | 2024.11.25 |
(14)React_초급_React_Design_3_React에 CSS 적용하는 여러가지 방법 (0) | 2024.11.25 |
(13)React_초급_React_Design_2_외부CSS파일 불러오기 (0) | 2024.11.25 |