CSS만으로 별점 선택 기능 만들기. 형제 선택자(Sibling Selector) "~"를 활용한 별점 선택 기능 만들기.

1. 별점 선택 기본 구조 만들기

별점 기능을 구현하기 위한 별 이미지는 투명 배경 이미지인 PNG나 벡터 이미지인 SVG로 많이 만듭니다.

최근에는 다양한 기본 이모지가 사용 가능해지면서 이모지를 이용해서 별점 기능을 만들 수 있어서 별도의 리소스 제작을 하지 않고 만들 수 있는 이모지를 활용해서 만들어 보겠습니다.

이모지는 기본 시스템 글꼴로 표현이 가능하기 때문에 복사&붙여넣기로 글자처럼 사용이 가능합니다.

먼저 별 모양 이모지를 인터넷에서 찾아서 가져옵니다.

이모지는 코드로 표현하는 기존의 문자 코드와 다르게 이미지 자체가 표현되는 특징이 있습니다.

뒷부분에서 마우스 클릭으로 별점 갯수를 선택한 상태가 유지되도록 하는 기능을 구현할 것이기 때문에 클릭한 별점 값이 선택되도록 라디오 버튼으로 별점 HTML을 제작합니다.

별점을 5개를 최대로 해서 다음과 같이 HTML 코드를 작성합니다.

<form name="myform" id="myform" method="post" action="./save">
    <fieldset>
        <legend>이모지 별점</legend>
        <label for="rate1">⭐</label><input type="radio" name="rating" value="1" id="rate1">
        <label for="rate2">⭐</label><input type="radio" name="rating" value="2" id="rate2">
        <label for="rate3">⭐</label><input type="radio" name="rating" value="3" id="rate3">
        <label for="rate4">⭐</label><input type="radio" name="rating" value="4" id="rate4">
        <label for="rate5">⭐</label><input type="radio" name="rating" value="5" id="rate5">
    </fieldset>
</form>

작성한 별점 폼은 다음처럼 보이게 됩니다.

기본 별점 폼 상태

이제 이 폼을 CSS를 이용해서 불필요한 요소들을 안보이도록 하고 크기도 적당히 조절해줍니다.

다음과 같이 CSS를 작성합니다.

#myform fieldset{
    display: inline-block; /* 하위 별점 이미지들이 있는 영역만 자리를 차지함.*/
    border: 0; /* 필드셋 테두리 제거 */
}
#myform input[type=radio]{
    display: none; /* 라디오박스 감춤 */
}
#myform label{
    font-size: 3em; /* 이모지 크기 */
    color: transparent; /* 기존 이모지 컬러 제거 */
    text-shadow: 0 0 0 #f0f0f0; /* 새 이모지 색상 부여 */
}
  • fieldset 에는 "display: inline-block" 속성을 부여합니다. 그래야 행 전체를 차지하지 않고, 이모지들이 있는 영역만을 별점 표시 영역으로 사용합니다. 뒤에서 현재 선택한 이모지와 그 왼쪽에 있는 모든 이모지의 색상을 바꾸는 용도로도 사용합니다. 중요합니다.
  • 폼의 라디오 버튼 태그(<input type="radio"></input>)는 불필요하므로 보이지 않도록 감춥니다.
  • 테두리 색상까지 있는 컬러 이모지(<label></label>)를 단일 색상으로 채워야 합니다. 이모지 색상을 투명으로 하고, 텍스트 그림자 효과에 색상을 부여하는 방식으로 이모지 색상을 변경합니다. 다음 두 가지 속성을 모두 사용해야 이모지 색상을 변경할 수 있습니다. 중요합니다.
color: transparent; /* 기존 이모지 컬러 제거 */
text-shadow: 0 0 0 #f0f0f0; /* 새 이모지 색상 부여 */
완성된 별점 기본 화면

2. 마우스 호버에 반응해서 별점 선택되게 하기

이모지 위에 마우스가 호버되면 자동으로 별점이 선택되어 보이도록 CSS를 추가합니다.

#myform label:hover{
    text-shadow: 0 0 0 #a00; /* 마우스 호버 */
}
#myform label:hover ~ label{
    text-shadow: 0 0 0 #a00; /* 마우스 호버 뒤에오는 이모지들 */
}

마우스 호버한 이모지 색상을 변경하는 것에 더해서 형제 선택자(~)를 이용해 현재 마우스 호버 된 이모지 뒤에 오는 모든 이모지도 색상을 변경해줍니다.

형제 선택자(~)는 현재 요소의 뒤에 오는 동위(같은 레벨) 요소들을 선택합니다.

이제 이모지에 마우스 호버를 하면 다음처럼 마우스 호버 된 이모지와 그 오른쪽의 모든 이모지 색상이 변경됩니다.

별점이 왼쪽에서부터 오른쪽 방향으로 선택되도록 하는 것은 다음 순서에서 설명합니다.

마우스 호버된 이모지와 그 이후 이모지가 모두 선택

3. 별점 선택 방향을 바로잡기

현재 마우스 호버 된 이모지의 오른쪽 방향으로 선택이 되는 것을 왼쪽 방향으로 선택되도록 바꿔야 합니다. 형제 선택자(~)는 현재 요소 뒤에 오는 요소만 선택할 수 있습니다.

따라서 다른 속성을 이용해서 순서를 바꿔야 합니다.

인라인 블록(display: inline-block)에는 하위 요소들이 표시되는 방향을 정해주는 속성이 하나 있습니다.

인라인 블록 태그에 다음 속성을 추가합니다.

#myform fieldset{
    display: inline-block; /* 하위 별점 이미지들이 있는 영역만 자리를 차지함.*/
    direction: rtl; /* 이모지 순서 반전 */
    border: 0; /* 필드셋 테두리 제거 */
}

기본 "direction" 속성 값은 "ltr"입니다. Left-To-Right의 약자입니다.

"rtl"(Right-To-Left)로 방향을 바꿔주면 하위 요소들이 오른쪽에서부터 채워지면서 뒤에 오는 이모지들이 왼쪽에 위치하게 됩니다.

"fieldset"의 뱡향을 바꾸면 라벨(<legent></legend>)도 오른쪽 끝에 붙어서 표시되므로 텍스트 정렬을 왼쪽으로 해서 맞춰줍니다.

#myform fieldset legend{
    text-align: left;
}
왼쪽에서부터 선택되는 이모지

이모지가 표시되는 UI는 모두 완성되었습니다.

이제 마우스 클릭을 해서 원하는 별점을 선택하는 기능을 구현해야 합니다.

4. 클릭해서 선택한 별점 유지되게 하기

완성된 이모지 UI는 순서가 반대로 표시되므로 실제 클릭한 별점 개수 값과 반대가 됩니다.

따라서 HTML의 라디오 버튼 값(value)을 반대로 표시해서 순서를 맞춰줘야 합니다.

"value" 값이 5부터 시작해서 마지막에 1이 되도록 합니다.

<form name="myform" id="myform" method="post" action="./save">
    <fieldset>
        <legend>이모지 별점</legend>
        <label for="rate1">⭐</label><input type="radio" name="rating" value="5" id="rate1">
        <label for="rate2">⭐</label><input type="radio" name="rating" value="4" id="rate2">
        <label for="rate3">⭐</label><input type="radio" name="rating" value="3" id="rate3">
        <label for="rate4">⭐</label><input type="radio" name="rating" value="2" id="rate4">
        <label for="rate5">⭐</label><input type="radio" name="rating" value="1" id="rate5">
    </fieldset>
</form>

이모지를 마우스로 클릭하면 그룹으로 묶인 5개의 "rating" 라디오버튼 중 1개만 선택됩니다.

HTML에서는 체크된 상태로 처리되는 라디오 버튼은 CSS에서 ":checked" 가상 클래스로 구분할 수 있습니다.

따라서 체크된 이모지와 그 이후의 이모지 색상을 변경하면, 별점을 선택한 상태가 유지되게 됩니다.

다음과 같이 CSS를 추가합니다.

#myform input[type=radio]:checked ~ label{
    text-shadow: 0 0 0 #a00; /* 마우스 클릭 체크 */
}

클래스를 추가한 후 이모지를 클릭해서 동작시켜보면 색상이 고정되어 표시되면서 잘 동작하지만 클릭한 이모지 자신은 색상이 바뀌지 않는 것을 알 수 있습니다.

형제 선택자(~)로 선택하는 요소들은 현재 요소의 뒤에오는 요소들입니다.

이모지를 표시하는 라벨 요소가 라디오버튼 태그 앞에 오기 때문에 형제 선택자(~)로는 선택이 되지 않습니다.

이모지와 라디오버튼 태그의 순서를 바꿔서 다음과 같이 HTML 폼을 변경해줍니다.

<form name="myform" id="myform" method="post" action="./save">
    <fieldset>
        <legend>이모지 별점</legend>
        <input type="radio" name="rating" value="5" id="rate1"><label for="rate1">⭐</label>
        <input type="radio" name="rating" value="4" id="rate2"><label for="rate2">⭐</label>
        <input type="radio" name="rating" value="3" id="rate3"><label for="rate3">⭐</label>
        <input type="radio" name="rating" value="2" id="rate4"><label for="rate4">⭐</label>
        <input type="radio" name="rating" value="1" id="rate5"><label for="rate5">⭐</label>
    </fieldset>
</form>

이렇게 하면 클릭해서 체크한 라디오 버튼 뒤에 현재 클릭한 이모지가 위치하게 되기 때문에 형제 선택자(~)로 원하는 모든 이모지를 선택할 수 있게 됩니다.

완성된 별점 선택

이렇게 하면 형제 선택자(~)로 구현하는 별점 선택 기능을 최소한의 코드로 만들 수 있습니다.

완성된 코드가 다음 링크에 있습니다. 다운로드해서 웹브라우저에서 동작하는 모습을 확인할 수 있습니다.

rating.zip0.00MB