글 작성자: 망고좋아
반응형

📖 오늘 배운 내용 - 2022.01.05

  • CSS import
  • CSS module
  • CSS-in-js
  • Sass
  • Flexbox
  • styled-components

 

📝 좋은 앱을 만들려면?

  • 번들 사이즈에 대한 고려
    • CSS 코드가 차지하는 사이즈는 무척 중요한 요소.
  • 앱 성능에 대한 고려
    • animation, transition 등 유저와의 상호작용에서 스타일 코드의 성능이 중요 요소.
  • 사용자에게 유리한 UI/UX를 고려
    • 스타일링에 대한 지식으로, 고급 테크닉을 적용하여 더 나은 UI/UX를 반영
  • 자바스크립트를 이용한 다양한 스타일 기법
    • UI 토글링, 애니메이션, 다크 모드, 복잡한 UI 컴포넌트 등은 자바스크립트에 대한 지식만으로 구현하기 힘듦.
  • 유지보수가 용이하고 확장 가능한 코드를 작성
    • 스타일에 관련된 코드를 어떻게 작성하고 관리하는가에 대한 지식이 필요

 

📝 React 앱에서의 스타일링 방법

 

[React] 리액트 앱에서의 스타일링 방법

🎯 리액트 앱에서의 스타일링 방법 📝 CSS import CSS(혹은 SCSS, Sass) 파일을 import 해서 사용한다. 필요한 모든 CSS 스타일을 하나의 파일에 작성하여, 자바스크립트 파일과 코드 분리 가능하다. 🛠 B

lakelouise.tistory.com

 

📝 CSS Box Model - box-sizing

 

[CSS] CSS Box Model - box-sizing

🎯 CSS Box Model - box-sizing width, height는 디폴트로 content-box의 크기를 정의된다. width : 100px으로 정의 시, content의 크기만 100px이 되며, padding, border의 크기는 100px에 추가된다. content-bo..

lakelouise.tistory.com

 

📝 Sass 맛보기

 

[Sass] Sass 맛보기

🎯 Sass 맛보기 Syntactically Awesome Style Sheets. CSS Preprocessor. SCSS, Sass 문법을 지원한다. 모듈, 믹스인, nested style, 변수, 조건문, 반복문 등의 기능으로 CSS를 프로그래밍 언어적으로 활용하도..

lakelouise.tistory.com

 

📝 Flexbox

  • flex: flex-grow flex-shrink flex-basis
    • flex: 0 0 120px
    • flex: 1flex: 1 1 auto

 

📝 styled-components

 

[styled-components] styled-components란?

🎯 styled-components란? 자바스크립트 파일 안에 스타일을 정의하고, React 컴포넌트처럼 활용할 수 있다. 자바스크립트 코드와 긴밀히 연계하여 다양한 코드를 작성할 수 있다. (변수 생성, 반복문,

lakelouise.tistory.com

 

📕 styled-components를 이용해 회원가입 폼 구현하기

import React, { useState } from "react";
import "./register-form.css";
import styled, { css } from 'styled-components';

const InputStatus = {
  NORMAL: "normal",
  ERROR: "error",
  SUCCESS: "success",
};

function RegisterForm() {
  const [name, setName] = useState("");
  const [age, setAge] = useState("");

  const [nameError, setNameError] = useState(null);
  const [ageError, setAgeError] = useState(null);

  const [nameInputStatus, setNameInputStatus] = useState(InputStatus.NORMAL);
  const [ageInputStatus, setAgeInputStatus] = useState(InputStatus.NORMAL);

  const handleNameChange = (e) => {
    setName(e.target.value);
  };

  const handleAgeChange = (e) => {
    setAge(e.target.value);
  };

  const validateName = (name) => {
    if (name.length < 1 || name.length > 10) {
      setNameError("이름은 1글자 이상, 10글자 이하여야 합니다.");
      setNameInputStatus(InputStatus.ERROR);
      return;
    }

    setNameInputStatus(InputStatus.SUCCESS);
  };

  const validateAge = (age) => {
    const numberedAge = Number(age);
    if (numberedAge < 1 || numberedAge > 100) {
      setAgeError("나이는 1부터 100 사이여야 합니다.");
      setAgeInputStatus(InputStatus.ERROR);
      return;
    }

    setAgeInputStatus(InputStatus.SUCCESS);
  };

  const validateForm = (form) => {
    validateName(form.name);
    validateAge(form.age);
  };

  const handleSubmit = () => {
    const formData = { name, age };
    validateForm(formData);
  };

  const handleReset = () => {
    setName("");
    setAge("");
  };

  const getInputStatusStyle = (status) => {
    if (status === InputStatus.ERROR) {
      return "input-invalid";
    } else if (status === InputStatus.SUCCESS) {
      return "input-valid";
    }
    return "";
  };

  return (
    <FormContainer>
      <FormFieldset>
        <FormLabel
          error={nameInputStatus === InputStatus.ERROR}
          htmlFor="name"
        >
          이름
        </FormLabel>
        <FormInput
          value={name}
          id="name"
          onChange={handleNameChange}
          type="text"
          name="name"
          status={nameInputStatus}
          placeholder="이름을 입력해 주세요."
        />

        <FormError>
          {nameInputStatus === InputStatus.ERROR && nameError}
        </FormError>
      </FormFieldset>

      <FormFieldset>
        <FormLabel
          error={ageInputStatus === InputStatus.ERROR }
          htmlFor="age"
        >
          나이
        </FormLabel>
        <FormInput
          id="age"
          value={age}
          onChange={handleAgeChange}
          type="number"
          name="age"
          status={ageInputStatus}
          placeholder="나이를 입력해 주세요."
        />

        <FormError>
          {ageInputStatus === InputStatus.ERROR && ageError}
        </FormError>
      </FormFieldset>

      <ButtonContainer>
        <FormButton
          onClick={handleReset}
          type="button"
          buttonType="reset"
        >
          초기화
        </FormButton>

        <FormButton
          onClick={handleSubmit}
          type="button"
          buttonType="submit"
        >
          제출
        </FormButton>
      </ButtonContainer>

    </FormContainer>
  );
}

export default RegisterForm;

const TextError = css`
    color: #ff6b6b;
`

const InputInvalid = css`
  border: 2px solid #ff6b6b;
`

const InputValid = css`
 border: 2px solid #51cf66;
`

const resetButton = css`
  background: #adb5bd;
`

const submitButton = css`
  background: #37b24d;
`

const FormContainer = styled.form`
    min-width: 300px;
`;

const FormFieldset = styled.fieldset`
  border-bottom: 1px solid rgba(0, 0, 0, 0.3);
  display: flex;
  flex-direction: column;
  border: none;
  padding: 12px 0;

  &:not(:first-of-type) {
    border-bottom: none;
    border-top: 1px solid rgba(0, 0, 0, 0.3);
  }
`

const FormLabel = styled.label`
  display: block;
  padding-bottom: 8px;
  font-size: 0.8rem;
  color: gray;
  ${props => props.error && TextError}
`;

const FormInput = styled.input`
  display: block;
  padding: 4px;
  border: 2px solid #dee2e6;
  border-radius: 3px;
  ${({ status }) => status === InputStatus.ERROR && InputInvalid}
  ${({ status }) => status === InputStatus.SUCCESS && InputValid}
` 

const FormError = styled.div`
  font-size: 0.8rem;
  min-height: 20px;
  margin-top: 4px;
  color: #ff6b6b;
`

const ButtonContainer = styled.div`
  display: flex;
`;

const FormButton = styled.button`
  flex: 1;
  border: none;
  padding: 4px;
  color: white;
  font-weight: 700;

  border-radius: 3px;
  cursor: pointer;

  &:not(:first-of-type) {
    margin-left: 8px;
  }

  ${({ buttonType }) => buttonType === "reset" && resetButton }
  ${({ buttonType }) => buttonType === "submit" && submitButton }
`;

 

💡 오늘 깨달은 것

  • modal을 구현할 때는 absolute보다 fixed를 사용하는 게 좋다.
  • em은 부모 폰트 사이즈의 상대적인 크기를 나타내는 unit
  • sass를 들어만 봤지 어떤 장점을 제공하는지 몰랐는데 이번 수업을 통해서 관심이 많이 생겼다. 생산성이 높아질 거 같다.
  • styled-componets를 사용하니까 더욱 리액트스러워졌다. 다만 좀 더 공부해야겠다.

 

📌 참고

반응형