본문 바로가기

Study/React

[React.js] 둥근 체크박스 만들기

 

<input type="checkbox" />

<input type="radio" />

 

두개의 차이는 체크박스냐 라디오 버튼이냐 차이다.

 

라디오 버튼의 경우 다양하게 변형해서 사용할 수 있지만 체크박스는 둥글게 만드는게 안된다..

즉,  border-radius 적용이 안된다...

 

리액트에서 둥근 체크박스를 만들기 위해 다음과 같이 코드를 작성하였는데,,, 배경만 나오고 체크모양 추가가 안되더라..

import { useState } from "react";
import styled from "styled-components";

export default function App() {
    const [isChecked, setIsChecked] = useState(false);

    const onClickCheck = () => {
        setIsChecked(!isChecked);
        console.log(!isChecked);
    };

    return (
        <>
            <SCustomCheckboxWrapper>
                <SCustomCheckbox type="checkbox" isChecked={isChecked} />
                <SCustomLabel onClick={onClickCheck} isChecked={isChecked} />
            </SCustomCheckboxWrapper>
        </>
    );
}

const SCustomCheckboxWrapper = styled.div`
    position: relative;
`;

const SCustomCheckbox = styled.input`
    visibility: hidden;
    ${({ isChecked }) =>
        isChecked
            ? {
                  backgroundColor: "#66bb6a",
                  borderColor: "#66bb6a",
                  "&:after": {
                      content: {
                          opacity: 1
                      }
                  }
              }
            : null}
`;

const SCustomLabel = styled.label`
    background-color: #fff;
    border: 1px solid #ccc;
    border-radius: 50%;
    cursor: pointer;
    width: 28px;
    height: 28px;
    position: absolute;
    left: 0;
    top: 0;
    ${({ isChecked }) =>
        isChecked
            ? {
                  backgroundColor: "#66bb6a",
                  borderColor: "#66bb6a",
                  "&:after": {
                      content: {
                          backgroundColor: "#f00",
                          border: "2px solid #fff",
                          borderTop: "none",
                          borderRight: "none",
                          content: "",
                          height: 6,
                          left: "7px",
                          opacity: 0,
                          position: "absolute",
                          top: "8px",
                          transform: "rotate(-45deg)",
                          width: 12
                      }
                  }
              }
            : {
                  backgroundColor: "#fff",
                  "&:after": {
                      content: {
                          opacity: 1
                      }
                  }
              }}
`;

 

한가지 간과한 사실이 있었다. state 값을 받아와서 삼항연산자로 스타일을 처리해주는데, after 가상 요소 선택자 부분에 뭔가 안들어갔다...

 

css를 추가해서 백틱안에 스타일을 적용해주면 감쪽같이 적용되더라..

 

가르침을 주신 개발자 모임 회원분께 감사를 표한다

 

import { useState } from "react";
import styled, { css } from "styled-components";

export default function Ref() {
    const [isChecked, setIsChecked] = useState(false);

    const onClickCheck = () => {
        setIsChecked(!isChecked);
        console.log(!isChecked);
    };

    return (
        <>
            <SCustomCheckboxWrapper>
                <SCustomCheckbox type="checkbox" isChecked={isChecked} />
                <SCustomLabel onClick={onClickCheck} isChecked={isChecked} />
            </SCustomCheckboxWrapper>
        </>
    );
}

const SCustomCheckboxWrapper = styled.div`
    position: relative;
`;

const SCustomCheckbox = styled.input`
    visibility: hidden;
    ${({ isChecked }) =>
        isChecked
            ? css`
                  background-color: #66bb6a;
                  border-color: #66bb6a;
                  &:after: {
                      opacity: 1;
                  }
              `
            : null}
`;

const SCustomLabel = styled.label`
    background-color: #fff;
    border: 1px solid #ccc;
    border-radius: 50%;
    cursor: pointer;
    width: 28px;
    height: 28px;
    position: absolute;
    left: 0;
    top: 0;
    ${({ isChecked }) =>
        isChecked
            ? css`
                  background-color: #66bb6a;
                  border-color: #66bb6a;
                  &:after {
                      border: 2px solid #fff;
                      border-top: none;
                      border-right: none;
                      content: "";
                      height: 6px;
                      left: 7px;
                      position: absolute;
                      top: 8px;
                      transform: rotate(-45deg);
                      width: 12px;
                  }
              `
            : css`
                  background-color: #fff !important;
                  &:after {
                      opacity: 1;
                  }
              `}
`;

 

미리보기

 

 

 

아래 코드를 리액트 컴포넌트로 제작한 것이다.

https://codepen.io/AllThingsSmitty/pen/WjZVjo