CSS 추가하기

비얌·2023년 2월 13일
1
post-thumbnail

🧹 개요

투두리스트 만들기 2탄에서는 저번에 만든 아래와 같은 투두리스트에 css를 추가해보기로 했다!


사실 갑자기 만들고 싶은 이미지가 떠올라서 만들어봤는데..

이렇게 생긴 투두리스트를 만들고 싶다. 왼쪽에 목표를 입력하면 그 아래 부분에 크게 나타나게 하고 오른쪽에서는 이 목표를 이루기 위한 투두리트를 작성하는 것이다. 그래서 일단 CSS를 비슷하게 만들어보기로 했다! 기능은 3탄에서 더 추가하는 걸로!



🛫 과정

컴포넌트 만들고 정렬하기

일단 기존의 투두리스트를 이렇게 만들려면 화면의 왼쪽에 해당하는 컴포넌트를 아예 새로 만들어야 한다.(현재 오른쪽 부분밖에 없음)

App을 왼쪽(Goal)과 오른쪽(Todo) 컴포넌트로 나누기

일단 왼쪽과 오른쪽을 구분하기 위해 컴포넌트를 두개로 나눴다. 왼쪽은 목표가 들어갈 거라서 Goal이라고 했고, 오른쪽은 투두리스트가 들어갈 거라서 Todo라고 했다.

// App.js
const App = () => {
  return (
    <div className="App">
      <div className="box">
        <Goal />
        <Todo />
      </div>
    </div>
  );
}

export default App;

flexbox를 이용하여 정렬하기

이제 화면처럼 Goal 컴포넌트는 왼쪽 절반, Todo 컴포넌트는 오른쪽 절반을 차지하도록 정렬해보자.

일단 App.module.css에 flex를 설정해주고, flex-direction을 row로 설정하여 컴포넌트가 가로로 정렬되게 했다.

/* App.module.css */
.box {
  display: flex;
  flex-direction: row;
}

그리고 Goal 컴포넌트와 Todo 컴포넌트를 4:6으로 나누기 위해 각각 flex: 4, flex: 6이라는 속성을 줬다.

그 결과, 아래와 같이 4:6으로 잘 나뉜 것을 알 수 있다!


Goal 컴포넌트에 입력폼 만들기

이제 목표를 입력하는 입력폼을 만들어야 한다. 사실.. 오른쪽의 입력폼과 다를 것이 거의 없기 때문에 복사해서 붙여넣었다.

// Goal.js
import { useState } from 'react';
import styles from './Goal.module.css'
import GoalInput from '../GoalInput/GoalInput';
import GoalTitle from '../GoalTitle/GoalTitle';

const Goal = () => {
  const [displayInputs, setDisplayInputs] = useState([]);

  const onSaveGoal = (goal) => {
    setDisplayInputs([...displayInputs, goal]);
  }
  return (
    <div className={styles.container}>
      <h1>이루고 싶은<br/>목표를 입력해주세요!</h1>
      <GoalInput onSaveGoal={onSaveGoal}/>
      <GoalTitle input={displayInputs}/>
    </div>
  );
};

export default Goal;
// GoalInput.js
import { useState } from 'react';

const GoalInput = (props) => {
  const [enteredGoal, setEnteredGoal] = useState('');
  const [isValid, setIsValid] = useState(true);

  const goalChangeHandler = (e) => {
    setEnteredGoal(e.target.value);
    setIsValid(true);
  }
  
  const submitHandler = (e) => {
    e.preventDefault();
    if (enteredGoal === '') {
      setIsValid(false);
      return;
    }
    setIsValid(true);
    props.onSaveGoal(enteredGoal)
    setEnteredGoal('');
  }
  return (
    <div>
      <form onSubmit={submitHandler}><input className={!isValid ? 'invalid' : ''} type='text' value={enteredGoal} onChange={goalChangeHandler} />
        <button type='submit'>입력</button>
      </form>
    </div>
  );
};

export default GoalInput;
// GoalTitle.js
import styles from './GoalTitle.module.css';

const GoalTitle = (props) => {
  return (
    <div>
      <div className={styles.goalTitle}>{props.input}</div>
    </div>
  );
};

export default GoalTitle;

이렇게 하여 아래와 같이 완성되었다! 이제 필요한 html 요소는 다 만든 것 같다.


App 컴포넌트 CSS 작성하기

일단 컴포넌트를 아래와 같이 나눴다. 그리고 CSS 모듈을 사용하여 CSS를 작성했다.

일단 App 컴포넌트의 css에서 html과 App, box의 height를 모두 100vh로 설정했다. 이렇게 하지 않으면 화면을 축소했을 때 배경색 등이 적용되지 않았고, 투두리스트를 끝없이 추가할 수 없었다.

// App.js
import styles from'./App.module.css';
import Todo from './components/Todo/Todo/Todo';
import Goal from './components/Goal/Goal/Goal';

const App = () => {
  return (
    <div className={styles.App}>
      <div className={styles.box}>
        <Goal />
        <Todo />
      </div>
    </div>
  );
}

export default App;
/* App.module.css */
html {
  height: 100vh;
}

.App {
  height: 100vh;
}

.box {
  display: flex;
  flex-direction: row;
  height: 100vh;
}

버튼, 입력창 디자인하기

버튼과 입력창을 디자인해봤다.

문자를 입력하면 입력창 테두리의 색이 하늘색으로 변하고, 입력창의 배경색 또한 조금 더 어둡게 변한다.

그리고 아무것도 입력하지 않고 입력 버튼을 누르면 입력창의 테두리가 빨간 색으로 변하며 입력창의 배경색은 더 옅어진다.

css 모듈에서 클래스네임을 여러개 동시에 지정하는 법을 몰라서 input_invalid라는 클래스네임을 새로 만들었는데, 클래스네임에 input과 invalid를 동시에 설정하는 방법을 알게 되면 수정할 예정이다.

.button {
  font: inherit;
  width: 100px;
  height: 55px;
  margin-left: 10px;
  border: 1px solid transparent;
  color: black;
  background: #a8dcfa;
  cursor: pointer;
  border-radius: 6px;
  font-size: 1.2rem;
}

.button:focus {
  outline: none;
}

.button:hover,
.button:active {
  background: #7eccf9;
  border-color: transparent;
  color: black;
}

.input {
  width: 250px;
  height: 55px;
  border-color: transparent;
  background-color: #232934;
  border-radius: 6px;
  color: white;
  font-size: 1.2rem;
}

.input:focus {
  border: 2px solid #63c6ff;
  outline: none;
  background-color: #1b1e25;
}

.input_invalid {
  width: 250px;
  height: 50px;
  border: 2px solid red;
  border-radius: 6px;
  background-color: #373a43bc;
  font-size: 1.2rem;
  color: white;
}

.input_invalid:focus {
  border: 2px solid #63c6ff;
  outline: none;
  background-color: #1b1e25;
}

👉 클래스네임을 두개 이상 지정하는 방법을 발견해서 수정했다!

이렇게 템플릿리터럴을 사용하면된다!

className={!isValid ? `${styles.input} ${styles.invalid}` : `${styles.input}`}

이렇게 하면 css에서 input에 관한 부분을 이렇게 수정할 수 있다.


.input {
  width: 250px;
  height: 55px;
  border-color: transparent;
  background-color: #232934;
  border-radius: 6px;
  color: white;
  font-size: 1.2rem;
}


.input:focus, .input.invalid:focus {
  border: 2px solid #63c6ff;
  outline: none;
  background-color: #1b1e25;
}

.input.invalid {
  border: 2px solid red;
  background-color: #373a43bc;
}

clsx라는 것도 있다고 해서 기록해두려고 한다
https://www.npmjs.com/package/clsx


todo 컴포넌트 가운데 정렬하기

왼쪽의 목표를 입력하는 컴포넌트와는 다르게 오른쪽의 todo를 입력하는 컴포넌트는 가운데 정렬을 하고 싶었다. 그래서 flexbox를 이용하여 정렬하기로 했다.

// TodoList.js
import TodoItem from '../TodoItem/TodoItem';
import styles from './TodoList.module.css';

const TodoList = (props) => {
  return (
    <div className={styles.container}>
      <TodoItem input={props.input}/>
    </div>
  );
};

export default TodoList;
/* TodoList.module.css */
.container {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  padding-top: 50px;
}

가운데 정렬이 됐다!



💁‍♀️ 결과

의도한 것

결과

의도한대로 디자인하는 것에 성공했다~!!



참고한 자료

1. 투두리스트 예시

리액트로 만든 많은 투두리스트의 데모와 깃허브를 볼 수 있는 곳을 찾아서(https://reactjsexample.com/tag/todo/) 이곳에서 예쁜 투두리스트를 찾아보던 중, 참고하고 싶은 투두리스트를 발견했었다!!!!

이곳에서(https://todo-app.erfjs.com) 확인할 수 있는데, 너무 예뻐서 반하고 말았다..

그래서 이 투두리스트의 배경색, 버튼과 입력창 디자인을 참고해서 만들었다.

코드는 깃허브(https://github.com/erfjs/Todo-list)에서 확인할 수 있다.


2. CSS 버튼 모아둔 사이트

참고하진 않았지만, 버튼 스타일과 CSS 코드를 모아둔 좋은 포스팅을 발견해서 기록해두려고 한다.

그리고 이것은 순수 CSS로 다양하게 디자인한 요소를 모아둔 사이트이다.



🐹 회고

사실 처음에 여기까지 만들었을 때는 너무..너무 ... 별로여서 슬펐었다🤣

그런데 갑자기 왼쪽에는 목표를 넣고, 오른쪽에는 그 목표를 이루기 위한 투두리스트를 작성하면 유용하겠다!는 생각이 들어서 피그마로 간단하게 디자인을 해보게 되었다!

처음에는 저걸 이렇게 만들 수 있을까..? 엄청 오래 걸리겠지? 하고 생각했지만 큰 시행착오 없이 한나절도 걸리지 않고 만들어서 행복했다😄

이제 다음 포스팅에서는 기능을 추가해볼 것 같다!!

profile
🐹강화하고 싶은 기억을 기록하고 공유하자🐹

0개의 댓글