<header>
        <span>&star;</span>
        <h1>Interactive Star Rating</h1>
        <span>&star;</span>
    </header>

    <main>
        <div id="rating-card">
          <div class="card front">
            <h2>Please Rate Us</h2>

            <div id="emoticon-container">&nbsp;</div>
            <p id="satisfaction-text">&nbsp;</p>

            <div id="rating-component-container">
                <div class="filled-stars">
                <span>&starf;</span>
                <span>&starf;</span>
                <span>&starf;</span>
                <span>&starf;</span>
                <span>&starf;</span>
                </div>

                <div id="blank-slider"></div>

                <div class="empty-stars">
                    <span>&star;</span>
                    <span>&star;</span>
                    <span>&star;</span>
                    <span>&star;</span>
                    <span>&star;</span>
                </div>           
            </div>

            <input type="number" id="val" step="0.1" min="0" max="10" placeholder="1 - 10">
            <button id="wr-btn">Write Review</button> 
          </div>  
          <div class="card back">
            <span id="back-btn">⇦</span>
            <h2>Write Review</h2>
            <p>Please share your thoughts about our app, so we can serve you better.</p>
            <textarea id="review-field" placeholder="Write a review..." ></textarea>
            <button id="rate-us">Rate Us</button>
        </div>          
      </div>
      
      <div class="sent">
        <h2> Review Sent! </h2>
        <p>Thank you for rating us.</p>
        <button id="go-back-btn">Go Back</button>
      </div>
    </main>
:root{
    --lightBlue: #43a6c6;
    --darkBlue: #03000f;
    --darkGray: #333;
    --starSize: 3.5em;

}

html{
    background-color: var( --darkBlue);
    color: whitesmoke;
}

*{
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

header{
    display: flex;
    justify-content: space-between;
    padding: 25px;
    letter-spacing: 2px;
    position: sticky;
    top: 0;
    z-index: 2;
    border-bottom: 2px solid ;
    background-color: var( --darkBlue);
    text-shadow: 3px 3px 5px var(--lightBlue);   
    box-shadow: 10px 10px 20px -10px var(--lightBlue); 
}

h1{
  font-size: 2.5em;
}

header > span{
    font-size: 25px;
    color: #ffee00;
}

main{
    min-height: 90vh;
    display: grid;
    place-items: center;
    perspective: 800px;
 }

 #rating-card{
    position: relative;
    box-shadow: 1px 1px 30px -1px var(--lightBlue);
    border-radius: 20px;
    transform-style: preserve-3d;
    transition: 2s;
    min-width: 250px;
}

.flipped{
    transform: rotateY(180deg);
}

.card{
    display: grid;
    place-items: center;
    padding: 25px 20px 40px;
    background-color: var( --darkBlue);
    border-radius: 20px;
}

.front{
    backface-visibility: hidden;
}

.p-events{
    pointer-events: none;
}

.back{
    height: 100%;
    position: absolute;
    top: 0;
    left:0;
    z-index: -1;
    transform: rotateY(180deg);
    pointer-events: none;
}

#back-btn{
    color: var(--lightBlue);
    position: absolute;
    top: 10px;
    left:12px;
    font-weight: 900;
  font-size: 25px;
    cursor: pointer;
}

#back-btn:hover {
  transform: scale(1.2);
}

p{
    padding:10px;
    color:#999;
}

.back textarea{
    border-radius: 10px;
    background-color: transparent;
    padding: 10px;
    height: 100px;
    color: #ccc;
    width: 90%;
    outline: none;
    border: 2px solid var(--darkGray);
    resize:none;
  letter-spacing: 1.5px;
    overflow: hidden;
    font-weight: 100;
    font-size: 12px;
}


h2{
    text-shadow: 1px 1px 3px var(--lightBlue);
    margin-bottom: 10px;
}

#emoticon-container{
    font-size: var( --starSize);
    margin-bottom: 10px;
}

#rating-component-container{
    position: relative;
    overflow: hidden;
    cursor: pointer;
  user-select: none;
 }

.filled-stars{
    background-image: linear-gradient(to right, red 5%, yellow, #00ff00);
    background-clip: text;
    -webkit-background-clip: text;
    transform: scale(1);
}

.filled-stars > span{
    font-size: var( --starSize);
    color: transparent;
 }

#blank-slider{
    background-color: var( --darkBlue);
    position: absolute;
    height: 100%;
    right: 0;
    top: 0;
    width: 100%;
    transition: 3s;
}

.empty-stars{
    position: absolute;
    top: 0;
    right: 0;
    height: 100%;
    width: 100%;
    transform: scale(1);
    transition: 1s;
}

.empty-stars > span{
    color: var(--darkGray);
    font-size: var( --starSize);
    cursor: pointer;
}

#val{
    background-color: transparent;
    color: aliceblue;
    outline: none;
    padding: 8px;
    margin-top: 15px;
    letter-spacing: 2px;
    font-weight: 700;
    border-radius: 10px;
    border: 2px solid var(--darkGray);
    width: 80%;
}

#val:hover{
    border: 2px solid var(--lightBlue);
}

.sent {
  display: none;
  place-items: center;
}

button{
    margin-top: 30px;
    border-radius: 10px;
    padding: 10px;
    background-color: var(--lightBlue);
    border:none;
    font-size: .9em;
    font-weight: 600;
}

.back>textarea:hover, button:hover{
    box-shadow: 1px 1px 20px -1px var(--lightBlue);
}

/* Media query for mobile phones */
@media screen and (max-width: 767px) {
    :root{
        --starSize: 2.5em;  
    }

    h1, h2{
        font-size: 1.2em;
      }

   .back > p, #satisfaction-text, button{
        font-size: .7em;
    }
}
const blankSlider = document.getElementById("blank-slider");
const emptyStars = document.querySelector(".empty-stars");
const val = document.getElementById("val");
const wrBtn = document.getElementById("wr-btn");
const backBtn = document.getElementById("back-btn");
const cardFront = document.querySelector(".front");
const cardBack = document.querySelector(".back");
const ratingCard = document.getElementById("rating-card");
const satisfactionTxtContainer = document.getElementById("satisfaction-text");
const goBackBtn = document.getElementById("go-back-btn");
const sentInfo = document.querySelector(".sent");
const rateUsBtn = document.getElementById("rate-us");
const reviewField = document.getElementById("review-field");
const emoticonContainer = document.getElementById("emoticon-container");
const hoverColors = ['red', 'orange', 'yellow', 'chartreuse', 'lime'];
const emoticons = ['&#128545;', '&#128577;', '&#128528;', '&#128522;', '&#129321;'];
const satisfactionTxt = ['Highly Unsatisfied', 'Slightly Unsatisfied', 'feeling Indifferent', 'Quite Satisfied', 'Extremely Satisfied'];

// Function to reverse numbers within 100
function reverseValue(value) {
  return 100 - value;
}

// loop through all the empty stars element
for (let i = 0; i < emptyStars.children.length; i++) {

  // Change the color of hovered star on mouseenter event
  emptyStars.children[i].onmouseenter = (e) => {
    emptyStars.children[i].style.color = hoverColors[i];
  };

  // Restore the color of hovered star on mouseleave event
  emptyStars.children[i].onmouseleave = (e) => {
    emptyStars.children[i].style.color = "#333";
  };

  // Update the slider, satisfaction text, and emoticon when any of the empty stars are clicked
  emptyStars.children[i].onclick = (e) => {
    // changes the value of the input field to number rating for the clicked star.
    val.value = i * 2 + 2;
    
    // sets the width percentage value of the slider to the index value of the clicked star plus 1 times 20 in reverse
    blankSlider.style.width = `${reverseValue((i + 1) * 20)}%`;

    satisfactionTxtContainer.innerHTML = satisfactionTxt[i];
    emoticonContainer.innerHTML = emoticons[i];
  };
}

// Add input event listener to the input value(val) element
val.addEventListener('input', (e) => {

   if (val.value < 0) {
      val.value = 0;
    }
  
  // Update the slider width based on the input value
  blankSlider.style.width = `${reverseValue(val.value * 10)}%`;

  // Update the satisfaction text and emoticon based on the input value
  const index = Math.min(Math.floor(val.value / 2 -0.5), 4);
  
satisfactionTxtContainer.innerHTML = index < 0 || val.value == "" ? '&nbsp;' : satisfactionTxt[index];
emoticonContainer.innerHTML = index < 0  || val.value == "" ? '&nbsp;' : emoticons[index];

})

wrBtn.onclick=()=>{
  ratingCard.classList.add("flipped");
  cardFront.classList.add("p-events");
  cardBack.style.pointerEvents="visible";

}

backBtn.onclick=()=>{
  ratingCard.classList.remove("flipped");
  cardFront.classList.remove("p-events")
  cardBack.style.pointerEvents="none";

}

// user's rating info object.
let userRating = {
  RatingValue:"",
  satisfaction: "",
  review: "",
};

// store the user's rating info
rateUsBtn.onclick = () => {
  ratingCard.style.display = "none";
  sentInfo.style.display = "grid";
  
  userRating.RatingValue = val.value;
  userRating.satisfaction = satisfactionTxtContainer.textContent;
  userRating.review = reviewField.value;
  console.log(userRating);
}

goBackBtn.onclick = () => {
  ratingCard.style.display = "block";
  sentInfo.style.display = "none";
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.