Star ratings are a ubiquitous feature in today's digital landscape, providing a quick and intuitive way for users to gauge the quality of products, services, and content. From e-commerce platforms to streaming services, these ratings play a crucial role in influencing consumer decisions.
In this article, we will explore ten exemplary implementations of star ratings, highlighting their design, functionality, and impact. Whether you're a developer looking to enhance your UI or a business aiming to boost user engagement, these examples offer valuable insights.
CODE1
Here's the code:
CODETEXT1
CODE2
Here's the code:
CODETEXT2
CODE3
Here's the code:
CODETEXT3
CODE4
Here's the code:
CODETEXT4
CODE5
Here's the code:
CODETEXT5
Designers and developers, elevate your star rating designs with Subframe's drag-and-drop interface. Its intuitive, responsive canvas ensures pixel-perfect UI every time.
Loved by professionals, Subframe makes stunning UI creation effortless. Start for free today!
CODE6
Here's the code:
CODETEXT6
CODE7
Here's the code:
CODETEXT7
CODE8
Here's the code:
CODETEXT8
CODE9
Here's the code:
CODETEXT9
CODE10
Here's the code:
CODETEXT10
Ready to elevate your UI designs? With Subframe, you can create pixel-perfect interfaces, including star ratings, in minutes. Its drag-and-drop editor ensures efficiency and precision.
Don't wait—start for free and begin designing stunning UIs right away!
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; } body { display: flex; justify-content: center; align-items: center; min-height: 700px; background: #f8f9fa; padding: 20px; } .rating-container { width: 100%; max-width: 550px; background: white; border-radius: 12px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.05); padding: 40px; position: relative; overflow: hidden; transition: all 0.4s ease; } .rating-container:hover { box-shadow: 0 15px 40px rgba(0, 0, 0, 0.08); } .rating-container::before { content: ''; position: absolute; top: 0; left: 0; width: 6px; height: 100%; background: linear-gradient(to bottom, #3a7bd5, #00d2ff); opacity: 0.8; } h1 { font-size: 24px; font-weight: 600; color: #111827; margin-bottom: 8px; } p { font-size: 15px; line-height: 1.5; color: #6b7280; margin-bottom: 30px; } .rating-group { display: flex; flex-direction: column; gap: 20px; } .product { display: flex; align-items: center; padding: 20px; border-radius: 10px; background: #f9fafb; transition: transform 0.3s ease, box-shadow 0.3s ease; } .product:hover { transform: translateY(-3px); box-shadow: 0 6px 15px rgba(0, 0, 0, 0.05); } .product-image { width: 70px; height: 70px; border-radius: 8px; overflow: hidden; background: #f3f4f6; display: flex; align-items: center; justify-content: center; margin-right: 15px; flex-shrink: 0; } .product-image img { max-width: 100%; height: auto; } .product-details { flex: 1; } .product-name { font-size: 15px; font-weight: 600; color: #1f2937; margin-bottom: 5px; } .rating-stars { display: flex; align-items: center; position: relative; margin-top: 8px; } .stars-container { display: flex; gap: 5px; } .star { width: 24px; height: 24px; cursor: pointer; position: relative; } .star-outline, .star-filled { position: absolute; top: 0; left: 0; width: 100%; height: 100%; transition: opacity 0.3s ease, transform 0.2s ease, color 0.3s ease; } .star-outline { color: #d1d5db; opacity: 1; } .star-filled { color: #d1d5db; opacity: 0; } .star.active .star-filled { opacity: 1; } .star.half .star-filled { clip-path: polygon(0 0, 50% 0, 50% 100%, 0 100%); opacity: 1; } .star:hover { transform: scale(1.1); } .star.active .star-filled { color: #facc15; } .star.highlight .star-filled { color: #fbbf24; } .rating-value { margin-left: 10px; font-size: 14px; color: #6b7280; font-weight: 600; min-width: 36px; transition: color 0.3s ease; } .rating-text { position: absolute; bottom: -25px; left: 0; font-size: 13px; font-weight: 500; opacity: 0; transform: translateY(-5px); transition: opacity 0.3s ease, transform 0.3s ease, color 0.3s ease; color: #6b7280; } .rating-stars:hover .rating-text { opacity: 1; transform: translateY(0); } .confirmation { margin-top: 30px; padding: 15px; border-radius: 8px; background: #ecfdf5; border-left: 4px solid #10b981; display: flex; align-items: center; transform: translateY(20px); opacity: 0; transition: all 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275); visibility: hidden; } .confirmation.show { transform: translateY(0); opacity: 1; visibility: visible; } .confirmation-icon { width: 22px; height: 22px; color: #10b981; margin-right: 10px; flex-shrink: 0; } .confirmation-text { font-size: 14px; color: #065f46; margin: 0; } .submit-btn { display: block; margin-top: 30px; width: 100%; padding: 12px 0; background: #3b82f6; color: white; border: none; border-radius: 6px; font-weight: 500; font-size: 15px; cursor: pointer; transition: all 0.3s ease; position: relative; overflow: hidden; } .submit-btn:hover { background: #2563eb; } .submit-btn:active { transform: scale(0.98); } .submit-btn .ripple { position: absolute; border-radius: 50%; background: rgba(255, 255, 255, 0.5); transform: scale(0); animation: ripple 0.6s linear; } @keyframes ripple { to { transform: scale(2.5); opacity: 0; } } @media (max-width: 550px) { .rating-container { padding: 30px 20px; } h1 { font-size: 20px; } p { font-size: 14px; } .product { padding: 15px; } .product-image { width: 60px; height: 60px; } .star { width: 20px; height: 20px; } } </style> </head> <body> <div class="rating-container"> <h1>Your Recent Purchases</h1> <p>Rate your items to help other shoppers make informed decisions and enjoy personalized recommendations in the future.</p> <div class="rating-group"> <div class="product"> <div class="product-image"> <svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="icon"> <path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"></path> </svg> </div> <div class="product-details"> <div class="product-name">Premium Wireless Headphones</div> <div class="rating-stars" data-product="headphones"> <div class="stars-container"> <div class="star" data-value="1"> <svg class="star-outline" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z" /> </svg> <svg class="star-filled" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"> <path fill-rule="evenodd" d="M10.788 3.21c.448-1.077 1.976-1.077 2.424 0l2.082 5.007 5.404.433c1.164.093 1.636 1.545.749 2.305l-4.117 3.527 1.257 5.273c.271 1.136-.964 2.033-1.96 1.425L12 18.354 7.373 21.18c-.996.608-2.231-.29-1.96-1.425l1.257-5.273-4.117-3.527c-.887-.76-.415-2.212.749-2.305l5.404-.433 2.082-5.006z" clip-rule="evenodd" /> </svg> </div> <div class="star" data-value="2"> <svg class="star-outline" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z" /> </svg> <svg class="star-filled" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"> <path fill-rule="evenodd" d="M10.788 3.21c.448-1.077 1.976-1.077 2.424 0l2.082 5.007 5.404.433c1.164.093 1.636 1.545.749 2.305l-4.117 3.527 1.257 5.273c.271 1.136-.964 2.033-1.96 1.425L12 18.354 7.373 21.18c-.996.608-2.231-.29-1.96-1.425l1.257-5.273-4.117-3.527c-.887-.76-.415-2.212.749-2.305l5.404-.433 2.082-5.006z" clip-rule="evenodd" /> </svg> </div> <div class="star" data-value="3"> <svg class="star-outline" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z" /> </svg> <svg class="star-filled" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"> <path fill-rule="evenodd" d="M10.788 3.21c.448-1.077 1.976-1.077 2.424 0l2.082 5.007 5.404.433c1.164.093 1.636 1.545.749 2.305l-4.117 3.527 1.257 5.273c.271 1.136-.964 2.033-1.96 1.425L12 18.354 7.373 21.18c-.996.608-2.231-.29-1.96-1.425l1.257-5.273-4.117-3.527c-.887-.76-.415-2.212.749-2.305l5.404-.433 2.082-5.006z" clip-rule="evenodd" /> </svg> </div> <div class="star" data-value="4"> <svg class="star-outline" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z" /> </svg> <svg class="star-filled" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"> <path fill-rule="evenodd" d="M10.788 3.21c.448-1.077 1.976-1.077 2.424 0l2.082 5.007 5.404.433c1.164.093 1.636 1.545.749 2.305l-4.117 3.527 1.257 5.273c.271 1.136-.964 2.033-1.96 1.425L12 18.354 7.373 21.18c-.996.608-2.231-.29-1.96-1.425l1.257-5.273-4.117-3.527c-.887-.76-.415-2.212.749-2.305l5.404-.433 2.082-5.006z" clip-rule="evenodd" /> </svg> </div> <div class="star" data-value="5"> <svg class="star-outline" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z" /> </svg> <svg class="star-filled" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"> <path fill-rule="evenodd" d="M10.788 3.21c.448-1.077 1.976-1.077 2.424 0l2.082 5.007 5.404.433c1.164.093 1.636 1.545.749 2.305l-4.117 3.527 1.257 5.273c.271 1.136-.964 2.033-1.96 1.425L12 18.354 7.373 21.18c-.996.608-2.231-.29-1.96-1.425l1.257-5.273-4.117-3.527c-.887-.76-.415-2.212.749-2.305l5.404-.433 2.082-5.006z" clip-rule="evenodd" /> </svg> </div> </div> <div class="rating-value">0.0</div> <div class="rating-text">Tap for half stars, click to select</div> </div> </div> </div> <div class="product"> <div class="product-image"> <svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="icon"> <rect x="2" y="7" width="20" height="14" rx="2" ry="2"></rect> <path d="M16 21V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16"></path> </svg> </div> <div class="product-details"> <div class="product-name">Organic Cotton T-Shirt</div> <div class="rating-stars" data-product="tshirt"> <div class="stars-container"> <div class="star" data-value="1"> <svg class="star-outline" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z" /> </svg> <svg class="star-filled" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"> <path fill-rule="evenodd" d="M10.788 3.21c.448-1.077 1.976-1.077 2.424 0l2.082 5.007 5.404.433c1.164.093 1.636 1.545.749 2.305l-4.117 3.527 1.257 5.273c.271 1.136-.964 2.033-1.96 1.425L12 18.354 7.373 21.18c-.996.608-2.231-.29-1.96-1.425l1.257-5.273-4.117-3.527c-.887-.76-.415-2.212.749-2.305l5.404-.433 2.082-5.006z" clip-rule="evenodd" /> </svg> </div> <div class="star" data-value="2"> <svg class="star-outline" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z" /> </svg> <svg class="star-filled" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"> <path fill-rule="evenodd" d="M10.788 3.21c.448-1.077 1.976-1.077 2.424 0l2.082 5.007 5.404.433c1.164.093 1.636 1.545.749 2.305l-4.117 3.527 1.257 5.273c.271 1.136-.964 2.033-1.96 1.425L12 18.354 7.373 21.18c-.996.608-2.231-.29-1.96-1.425l1.257-5.273-4.117-3.527c-.887-.76-.415-2.212.749-2.305l5.404-.433 2.082-5.006z" clip-rule="evenodd" /> </svg> </div> <div class="star" data-value="3"> <svg class="star-outline" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z" /> </svg> <svg class="star-filled" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"> <path fill-rule="evenodd" d="M10.788 3.21c.448-1.077 1.976-1.077 2.424 0l2.082 5.007 5.404.433c1.164.093 1.636 1.545.749 2.305l-4.117 3.527 1.257 5.273c.271 1.136-.964 2.033-1.96 1.425L12 18.354 7.373 21.18c-.996.608-2.231-.29-1.96-1.425l1.257-5.273-4.117-3.527c-.887-.76-.415-2.212.749-2.305l5.404-.433 2.082-5.006z" clip-rule="evenodd" /> </svg> </div> <div class="star" data-value="4"> <svg class="star-outline" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z" /> </svg> <svg class="star-filled" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"> <path fill-rule="evenodd" d="M10.788 3.21c.448-1.077 1.976-1.077 2.424 0l2.082 5.007 5.404.433c1.164.093 1.636 1.545.749 2.305l-4.117 3.527 1.257 5.273c.271 1.136-.964 2.033-1.96 1.425L12 18.354 7.373 21.18c-.996.608-2.231-.29-1.96-1.425l1.257-5.273-4.117-3.527c-.887-.76-.415-2.212.749-2.305l5.404-.433 2.082-5.006z" clip-rule="evenodd" /> </svg> </div> <div class="star" data-value="5"> <svg class="star-outline" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z" /> </svg> <svg class="star-filled" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"> <path fill-rule="evenodd" d="M10.788 3.21c.448-1.077 1.976-1.077 2.424 0l2.082 5.007 5.404.433c1.164.093 1.636 1.545.749 2.305l-4.117 3.527 1.257 5.273c.271 1.136-.964 2.033-1.96 1.425L12 18.354 7.373 21.18c-.996.608-2.231-.29-1.96-1.425l1.257-5.273-4.117-3.527c-.887-.76-.415-2.212.749-2.305l5.404-.433 2.082-5.006z" clip-rule="evenodd" /> </svg> </div> </div> <div class="rating-value">0.0</div> <div class="rating-text">Tap for half stars, click to select</div> </div> </div> </div> <div class="product"> <div class="product-image"> <svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="icon"> <path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"></path> <path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"></path> </svg> </div> <div class="product-details"> <div class="product-name">Ceramic Pour-Over Coffee Set</div> <div class="rating-stars" data-product="coffee"> <div class="stars-container"> <div class="star" data-value="1"> <svg class="star-outline" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z" /> </svg> <svg class="star-filled" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"> <path fill-rule="evenodd" d="M10.788 3.21c.448-1.077 1.976-1.077 2.424 0l2.082 5.007 5.404.433c1.164.093 1.636 1.545.749 2.305l-4.117 3.527 1.257 5.273c.271 1.136-.964 2.033-1.96 1.425L12 18.354 7.373 21.18c-.996.608-2.231-.29-1.96-1.425l1.257-5.273-4.117-3.527c-.887-.76-.415-2.212.749-2.305l5.404-.433 2.082-5.006z" clip-rule="evenodd" /> </svg> </div> <div class="star" data-value="2"> <svg class="star-outline" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Epicure - Culinary Experience Ratings</title> <style> :root { --primary-color: #4a6fa5; --secondary-color: #ffb347; --tertiary-color: #ff6b6b; --background-color: #f9f7f5; --card-background: #ffffff; --text-primary: #2c3e50; --text-secondary: #7f8c8d; --shadow-soft: 0 8px 30px rgba(0, 0, 0, 0.05); --radius: 12px; --transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Montserrat', 'Helvetica Neue', sans-serif; } body { background: var(--background-color); color: var(--text-primary); width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; padding: 20px; overflow-x: hidden; line-height: 1.6; } .container { width: 100%; max-width: 650px; background: var(--card-background); border-radius: var(--radius); box-shadow: var(--shadow-soft); padding: 32px; position: relative; overflow: hidden; } .container::before { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 6px; background: linear-gradient(90deg, var(--primary-color), var(--tertiary-color)); } h1 { font-size: 28px; font-weight: 700; margin-bottom: 20px; background: linear-gradient(135deg, var(--primary-color), var(--tertiary-color)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; text-fill-color: transparent; } p { color: var(--text-secondary); margin-bottom: 30px; font-size: 16px; font-weight: 400; } .review-item { border-bottom: 1px solid rgba(0,0,0,0.05); padding: 24px 0; transition: var(--transition); } .review-item:last-child { border-bottom: none; } .review-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px; } .restaurant-name { font-size: 18px; font-weight: 600; } .cuisine-tag { display: inline-block; padding: 4px 10px; background: rgba(74, 111, 165, 0.1); color: var(--primary-color); border-radius: 50px; font-size: 12px; font-weight: 500; letter-spacing: 0.5px; } .rating-container { position: relative; margin: 20px 0; } .stars-container { display: flex; gap: 6px; } .star { width: 30px; height: 30px; cursor: pointer; position: relative; transition: transform 0.3s ease; } .star:hover { transform: scale(1.15); } .star svg { width: 100%; height: 100%; position: absolute; top: 0; left: 0; } .star-bg { fill: #e0e0e0; } .star-fill { fill: url(#starGradient); transform-origin: center; transform: scale(0); transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1); } .star.active .star-fill { transform: scale(1); } .rating-label { font-size: 20px; font-weight: 600; margin-top: 12px; background: linear-gradient(to right, var(--primary-color), var(--tertiary-color)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; opacity: 0; transform: translateY(10px); transition: all 0.3s ease; } .rating-label.visible { opacity: 1; transform: translateY(0); } .tooltip { position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%) translateY(-8px); padding: 8px 12px; background: #2c3e50; color: white; border-radius: 6px; font-size: 12px; font-weight: 500; opacity: 0; pointer-events: none; transition: all 0.3s ease; box-shadow: 0 4px 12px rgba(0,0,0,0.1); white-space: nowrap; z-index: 10; } .tooltip::after { content: ''; position: absolute; top: 100%; left: 50%; margin-left: -6px; width: 0; height: 0; border-top: 6px solid #2c3e50; border-right: 6px solid transparent; border-left: 6px solid transparent; } .star:hover .tooltip { opacity: 1; transform: translateX(-50%) translateY(-4px); } .review-text { color: var(--text-secondary); font-style: italic; margin-top: 14px; font-size: 15px; } .recent-visit { display: flex; align-items: center; gap: 6px; margin-top: 16px; font-size: 13px; color: var(--text-secondary); } .recent-visit svg { width: 16px; height: 16px; color: var(--tertiary-color); } .submit-review { margin-top: 30px; background: linear-gradient(135deg, var(--primary-color), var(--tertiary-color)); color: white; border: none; padding: 12px 24px; border-radius: var(--radius); font-weight: 600; font-size: 16px; cursor: pointer; transition: all 0.3s ease; box-shadow: 0 4px 12px rgba(0,0,0,0.1); display: flex; align-items: center; justify-content: center; gap: 8px; } .submit-review:hover { transform: translateY(-2px); box-shadow: 0 6px 16px rgba(0,0,0,0.15); } .submit-review:active { transform: translateY(0); } .confetti { position: absolute; width: 8px; height: 8px; background-color: #FFC107; border-radius: 50%; pointer-events: none; } @media (max-width: 600px) { .container { padding: 24px 20px; } h1 { font-size: 24px; } .review-header { flex-direction: column; align-items: flex-start; gap: 8px; } .star { width: 26px; height: 26px; } } /* Animation for content entrance */ @keyframes fadeInUp { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } .review-item { animation: fadeInUp 0.5s ease forwards; opacity: 0; } .review-item:nth-child(1) { animation-delay: 0.1s; } .review-item:nth-child(2) { animation-delay: 0.3s; } .review-item:nth-child(3) { animation-delay: 0.5s; } /* Subtle glow effect on hover */ .review-item:hover { background: linear-gradient(to right, rgba(255,255,255,0), rgba(74, 111, 165, 0.05), rgba(255,255,255,0)); } </style> </head> <body> <div class="container"> <h1>Epicure Dining Ratings</h1> <p>Share your honest culinary experiences with our carefully designed rating system. Each star represents a different aspect of your dining journey.</p> <div class="review-item"> <div class="review-header"> <div class="restaurant-name">Lumière Bistro</div> <div class="cuisine-tag">French Modern</div> </div> <div class="rating-container" id="rating1"> <div class="stars-container"> <div class="star" data-value="1"> <svg viewBox="0 0 24 24"> <defs> <linearGradient id="starGradient" x1="0%" y1="0%" x2="100%" y2="100%"> <stop offset="0%" stop-color="#4a6fa5" /> <stop offset="100%" stop-color="#ff6b6b" /> </linearGradient> </defs> <path class="star-bg" d="M12,17.27L18.18,21l-1.64-7.03L22,9.24l-7.19-0.61L12,2L9.19,8.63L2,9.24l5.46,4.73L5.82,21L12,17.27z"/> <path class="star-fill" d="M12,17.27L18.18,21l-1.64-7.03L22,9.24l-7.19-0.61L12,2L9.19,8.63L2,9.24l5.46,4.73L5.82,21L12,17.27z"/> </svg> <div class="tooltip">Disappointing (1/5)</div> </div> <div class="star" data-value="2"> <svg viewBox="0 0 24 24"> <path class="star-bg" d="M12,17.27L18.18,21l-1.64-7.03L22,9.24l-7.19-0.61L12,2L9.19,8.63L2,9.24l5.46,4.73L5.82,21L12,17.27z"/> <path class="star-fill" d="M12,17.27L18.18,21l-1.64-7.03L22,9.24l-7.19-0.61L12,2L9.19,8.63L2,9.24l5.46,4.73L5.82,21L12,17.27z"/> </svg> <div class="tooltip">Adequate (2/5)</div> </div> <div class="star" data-value="3"> <svg viewBox="0 0 24 24"> <path class="star-bg" d="M12,17.27L18.18,21l-1.64-7.03L22,9.24l-7.19-0.61L12,2L9.19,8.63L2,9.24l5.46,4.73L5.82,21L12,17.27z"/> <path class="star-fill" d="M12,17.27L18.18,21l-1.64-7.03L22,9.24l-7.19-0.61L12,2L9.19,8.63L2,9.24l5.46,4.73L5.82,21L12,17.27z"/> </svg> <div class="tooltip">Good (3/5)</div> </div> <div class="star" data-value="4"> <svg viewBox="0 0 24 24"> <path class="star-bg" d="M12,17.27L18.18,21l-1.64-7.03L22,9.24l-7.19-0.61L12,2L9.19,8.63L2,9.24l5.46,4.73L5.82,21L12,17.27z"/> <path class="star-fill" d="M12,17.27L18.18,21l-1.64-7.03L22,9.24l-7.19-0.61L12,2L9.19,8.63L2,9.24l5.46,4.73L5.82,21L12,17.27z"/> </svg> <div class="tooltip">Excellent (4/5)</div> </div> <div class="star" data-value="5"> <svg viewBox="0 0 24 24"> <path class="star-bg" d="M12,17.27L18.18,21l-1.64-7.03L22,9.24l-7.19-0.61L12,2L9.19,8.63L2,9.24l5.46,4.73L5.82,21L12,17.27z"/> <path class="star-fill" d="M12,17.27L18.18,21l-1.64-7.03L22,9.24l-7.19-0.61L12,2L9.19,8.63L2,9.24l5.46,4.73L5.82,21L12,17.27z"/> </svg> <div class="tooltip">Exceptional (5/5)</div> </div> </div> <div class="rating-label" id="ratingLabel1"></div> </div> </div> <div class="review-item"> <div class="review-header"> <div class="restaurant-name">Sakura Kaiseki</div> <div class="cuisine-tag">Japanese Traditional</div> </div> <div class="rating-container" id="rating2"> <div class="stars-container"> <div class="star" data-value="1"> <svg viewBox="0 0 24 24"> <path class="star-bg" d="M12,17.27L18.18,21l-1.64-7.03L22,9.24l-7.19-0.61L12,2L9.19,8.63L2,9.24l5.46,4.73L5.82,21L12,17.27z"/> <path class="star-fill" d="M12,17.27L18.18,21l-1.64-7.03L22,9.24l-7.19-0.61L12,2L9.19,8.63L2,9.24l5.46,4.73L5.82,21L12,17.27z"/> </svg> <div class="tooltip">Disappointing (1/5)</div> </div> <div class="star" data-value="2"> <svg viewBox="0 0 24 24"> <path class="star-bg" d="M12,17.27L18.18,21l-1.64-7.03L22,9.24l-7.19-0.61L12,2L9.19,8.63L2,9.24l5.46,4.73L5.82,21L12,17.27z"/> <path class="star-fill" d="M12,17.27L18.18,21l-1.64-7.03L22,9.24l-7.19-0.61L12,2L9.19,8.63L2,9.24l5.46,4.73L5.82,21L12,17.27z"/> </svg> <div class="tooltip">Adequate (2/5)</div> </div> <div class="star" data-value="3"> <svg viewBox="0 0 24 24"> <path class="star-bg" d="M12,17.27L18.18,21l-1.64-7.03L22,9.24l-7.19-0.61L12,2L9.19,8.63L2,9.24l5.46,4.73L5.82,21L12,17.27z"/> <path class="star-fill" d="M12,17.27L18.18,21l-1.64-7.03L22,9.24l-7.19-0.61L12,2L9.19,8.63L2,9.24l5.46,4.73L5.82,21L12,17.27z"/> </svg> <div class="tooltip">Good (3/5)</div> </div> <div class="star" data-value="4"> <svg viewBox="0 0 24 24"> <path class="star-bg" d="M12,17.27L18.18,21l-1.64-7.03L22,9.24l-7.19-0.61L12,2L9.19,8.63L2,9.24l5.46,4.73L5.82,21L12,17.27z"/> <path class="star-fill" d="M12,17.27L18.18,21l-1.64-7.03L22,9.24l-7.19-0.61L12,2L9.19,8.63L2,9.24l5.46,4.73L5.82,21L12,17.27z"/> </svg> <div class="tooltip">Excellent (4/5)</div> </div> <div class="star" data-value="5"> <svg viewBox="0 0 24 24"> <path class="star-bg" d="M12,17.27L18.18,21l-1.64-7.03L22,9.24l-7.19-0.61L12,2L9.19,8.63L2,9.24l5.46,4.73L5.82,21L12,17.27z"/> <path class="star-fill" d="M12,17.27L18.18,21l-1.64-7.03L22,9.24l-7.19-0.61L12,2L9.19,8.63L2,9.24l5.46,4.73L5.82,21L12,17.27z"/> </svg> <div class="tooltip">Exceptional (5/5)</div> </div> </div> <div class="rating-label" id="ratingLabel2"></div> <div class="review-text">"Their seasonal omakase exceeded my expectations with meticulous presentation and sublime flavors in each course."</div> <div class="recent-visit"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" /> </svg> Visited 3 days ago </div> </div> </div> <div class="review-item"> <div class="review-header"> <div class="restaurant-name">Verde Tapas</div> <div class="cuisine-tag">Spanish Contemporary</div> </div> <div class="rating-container" id="rating3"> <div class="stars-container"> <div class="star" data-value="1"> <svg viewBox="0 0 24 24"> <path class="star-bg" d="M12,17.27L18.18,21l-1.64-7.03L22,9.24l-7.19-0.61L12,2L9.19,8.63L2,9.24l5.46,4.73L5.82,21L12,17.27z"/> <path class="star-fill" d="M12,17.27L18.18,21l-1.64-7.03L22,9.24l-7.19-0.61L12,2L9.19,8.63L2,9.24l5.46,4.73L5.82,21L12,17.27z"/> </svg> <div class="tooltip">Disappointing (1/5)</div> </div> <div class="star" data-value="2"> <svg viewBox="0 0 24 24"> <path class="star-bg" d="M12,17.27L18.18,21l-1.64-7.03L22,9.24l-7.19-0.61L12,2L9.19,8.63L2,9.24l5.46,4.73L5.82,21L12,17.27z"/> <path class="star-fill" d="M12,17.27L18.18,21l-1.64-7.03L22,9.24l-7.19-0.61L12,2L9.19,8.63L2,9.24l5.46,4.73L5.82,21L12,17.27z"/> </svg> <div class="tooltip">Adequate (2/5)</div> </div> <div class="star" data-value="3"> <svg viewBox="0 0 24 24"> <path class="star-bg" d="M12,17.27L18.18,21l-1.64-7.03L22,9.24l-7.19-0.61L12,2L9.19,8.63L2,9.24l5.46,4.73L5.82,21L12,17.27z"/> <path class="star-fill" d="M12,17.27L18.18,21l-1.64-7.03L22,9.24l-7.19-0.61L12,2L9.19,8.63L2,9.24l5.46,4.73L5.82,21L12,17.27z"/> </svg> <div class="tooltip">Good (3/5)</div> </div> <div class="star" data-value="4"> <svg viewBox="0 0 24 24"> <path class="star-bg" d="M12,17.27L18.18,21l-1.64-7.03L22,9.24l-7.19-0.61L12,2L9.19,8.63L2,9.24l5.46,4.73L5.82,21L12,17.27z"/> <path class="star-fill" d="M12,17.27L18.18,21l-1.64-7.03L22,9.24l-7.19-0.61L12,2L9.19,8.63L2,9.24l5.46,4.73L5.82,21L12,17.27z"/> </svg> <div class="tooltip">Excellent (4/5)</div> </div> <div class="star" data-value="5"> <svg viewBox="0 0 24 24"> <path class="star-bg" d="M12,17.27L18.18,21l-1.64-7.03L22,9.24l-7.19-0.61L12,2L9.19,8.63L2,9.24l5.46,4.73L5.82,21L12,17.27z"/> <path class="star-fill" d="M12,17.27L18.18,21l-1.64-7.03L22,9.24l-7.19-0.61L12,2L9.19,8.63L2,9.24l5.46,4.73L5.82,21L12,17.27z"/> </svg> <div class="tooltip">Exceptional (5/5)</div> </div> </div> <div class="rating-label" id="ratingLabel3"></div> </div> </div> <button class="submit-review"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path> </svg> Submit Ratings </button> </div> <script> document.addEventListener('DOMContentLoaded', function() { initializeRatings('rating1', 'ratingLabel1'); initializeRatings('rating2', 'ratingLabel2'); initializeRatings('rating3', 'ratingLabel3'); // Pre-select rating for Sakura Kaiseki (for demonstration) const sakuraRating = document.querySelector('#rating2'); const sakuraStars = sakuraRating.querySelectorAll('.star'); for (let i = 0; i < 5; i++) { if (i < 5) { // 5 stars sakuraStars[i].classList.add('active'); } } document.getElementById('ratingLabel2').textContent = "Exceptional"; document.getElementById('ratingLabel2').classList.add('visible'); // Add confetti effect to submit button const submitBtn = document.querySelector('.submit-review'); submitBtn.addEventListener('click', function(e) { e.preventDefault(); createConfetti(e); // Visual feedback this.textContent = "Ratings Submitted!"; setTimeout(() => { this.innerHTML = ` <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path> </svg> Submit Ratings`; }, 2000); }); }); function initializeRatings(containerId, labelId) { const container = document.getElementById(containerId); const stars = container.querySelectorAll('.star'); const ratingLabel = document.getElementById(labelId); const ratingDescriptions = [ "Disappointing", "Adequate", "Good", "Excellent", "Exceptional" ]; stars.forEach(star => { star.addEventListener('click', function() { const value = parseInt(this.getAttribute('data-value')); // Reset all stars stars.forEach(s => s.classList.remove('active')); // Activate stars up to selected one for (let i = 0; i < stars.length; i++) { if (i < value) { stars[i].classList.add('active'); } } // Update rating label ratingLabel.textContent = ratingDescriptions[value - 1]; ratingLabel.classList.add('visible'); // Add animation to the selected star this.querySelector('.star-fill').animate([ { transform: 'scale(0.5)', opacity: 0.7 }, { transform: 'scale(1.2)', opacity: 1 }, { transform: 'scale(1)', opacity: 1 } ], { duration: 400, easing: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)' }); }); }); } function createConfetti(e) { const colors = ['#4a6fa5', '#ffb347', '#ff6b6b', '#4CAF50', '#9C27B0']; const buttonRect = e.target.getBoundingClientRect(); for (let i = 0; i < 50; i++) { const confetti = document.createElement('div'); confetti.className = 'confetti'; confetti.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)]; document.body.appendChild(confetti); const size = Math.random() * 10 + 5; confetti.style.width = `${size}px`; confetti.style.height = `${size}px`; const startX = buttonRect.left + buttonRect.width / 2; const startY = buttonRect.top + buttonRect.height / 2; confetti.style.left = `${startX}px`; confetti.style.top = `${startY}px`; const angle = Math.random() * Math.PI * 2; const velocity = Math.random() * 6 + 3; const vx = Math.cos(angle) * velocity; const vy = Math.sin(angle) * velocity; let x = startX; let y = startY; let alpha = 1; const animateConfetti = () => { x += vx; y += vy + 0.1; // Add gravity alpha -= 0.01; if (alpha <= 0) { confetti.remove(); return; } confetti.style.left = `${x}px`; confetti.style.top = `${y}px`; confetti.style.opacity = alpha; requestAnimationFrame(animateConfetti); }; setTimeout(animateConfetti, Math.random() * 500); } } </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Star Rating Module</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { display: flex; justify-content: center; align-items: center; height: 100vh; background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); overflow: hidden; } .app-container { width: 100%; max-width: 320px; background-color: #fff; border-radius: 24px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1); padding: 30px 20px; position: relative; overflow: hidden; } .app-header { text-align: center; margin-bottom: 25px; } .app-header h1 { color: #333; font-size: 22px; font-weight: 600; margin-bottom: 8px; } .app-header p { color: #666; font-size: 14px; line-height: 1.4; } .rating-container { display: flex; flex-direction: column; align-items: center; position: relative; } .stars-container { display: flex; justify-content: center; margin-bottom: 25px; position: relative; z-index: 2; } .star { width: 48px; height: 48px; margin: 0 6px; cursor: pointer; position: relative; transition: transform 0.3s ease; filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.1)); } .star svg { width: 100%; height: 100%; fill: #e0e0e0; transition: fill 0.3s ease, transform 0.3s ease; } .star.active svg { fill: #FFD700; } .star.hover svg { transform: scale(1.1); } .star.pulse svg { animation: pulse 0.4s ease-in-out; } @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.2); } 100% { transform: scale(1); } } .feedback-text { font-size: 18px; font-weight: 500; color: #333; text-align: center; min-height: 27px; margin-bottom: 20px; transition: opacity 0.3s ease; } .submit-btn { background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%); color: white; border: none; padding: 12px 30px; border-radius: 50px; font-size: 16px; font-weight: 500; cursor: pointer; box-shadow: 0 4px 15px rgba(37, 117, 252, 0.2); transition: all 0.3s ease; opacity: 0; transform: translateY(10px); pointer-events: none; } .submit-btn.visible { opacity: 1; transform: translateY(0); pointer-events: all; } .submit-btn:hover { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(37, 117, 252, 0.3); } .submit-btn:active { transform: translateY(1px); } .success-message { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-color: #fff; display: flex; flex-direction: column; justify-content: center; align-items: center; opacity: 0; pointer-events: none; transition: opacity 0.4s ease; z-index: 10; } .success-message.visible { opacity: 1; pointer-events: all; } .success-icon { width: 80px; height: 80px; margin-bottom: 20px; animation: bounce 1s ease; } @keyframes bounce { 0%, 20%, 50%, 80%, 100% { transform: translateY(0); } 40% { transform: translateY(-30px); } 60% { transform: translateY(-15px); } } .success-text { font-size: 18px; font-weight: 600; color: #333; text-align: center; margin-bottom: 10px; } .success-subtext { font-size: 14px; color: #666; text-align: center; max-width: 240px; line-height: 1.4; } .particles { position: absolute; width: 100%; height: 100%; top: 0; left: 0; pointer-events: none; z-index: 1; } .particle { position: absolute; border-radius: 50%; opacity: 0; } @keyframes particle-animation { 0% { transform: translate(0, 0) scale(1); opacity: 0; } 10% { opacity: 1; } 90% { opacity: 1; } 100% { transform: translate(var(--x), var(--y)) scale(0); opacity: 0; } } @media (max-width: 360px) { .app-container { max-width: 280px; padding: 20px 15px; } .star { width: 40px; height: 40px; margin: 0 4px; } .app-header h1 { font-size: 20px; } .feedback-text { font-size: 16px; } } .reset-btn { background: none; border: none; color: #2575fc; text-decoration: underline; font-size: 14px; cursor: pointer; margin-top: 15px; opacity: 0; transform: translateY(10px); transition: all 0.3s ease; } .reset-btn.visible { opacity: 1; transform: translateY(0); } .swipe-hint { position: absolute; top: 20px; left: 0; width: 100%; text-align: center; font-size: 12px; color: #999; opacity: 0.8; display: flex; align-items: center; justify-content: center; } .swipe-hint svg { width: 18px; height: 18px; margin-right: 5px; animation: swipe-animation 2s infinite; } @keyframes swipe-animation { 0% { transform: translateX(0); } 50% { transform: translateX(5px); } 100% { transform: translateX(0); } } </style> </head> <body> <div class="app-container"> <div class="app-header"> <h1>How was your experience?</h1> <p>Swipe across the stars to rate your recent session with our fitness app</p> </div> <div class="swipe-hint"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="5" y1="12" x2="19" y2="12"></line> <polyline points="12 5 19 12 12 19"></polyline> </svg> <span>Swipe or tap to rate</span> </div> <div class="rating-container"> <div class="particles"></div> <div class="stars-container"> <div class="star" data-value="1"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/> </svg> </div> <div class="star" data-value="2"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/> </svg> </div> <div class="star" data-value="3"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/> </svg> </div> <div class="star" data-value="4"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/> </svg> </div> <div class="star" data-value="5"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/> </svg> </div> </div> <div class="feedback-text"></div> <button class="submit-btn">Submit Feedback</button> <button class="reset-btn">Rate Again</button> </div> <div class="success-message"> <svg class="success-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <circle cx="12" cy="12" r="10" fill="#4CAF50"/> <path fill="#FFFFFF" d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z"/> </svg> <div class="success-text">Thanks for your feedback!</div> <div class="success-subtext">Your input helps us improve our fitness app experience for everyone.</div> <button class="reset-btn visible">Rate Another Feature</button> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { const stars = document.querySelectorAll('.star'); const feedbackText = document.querySelector('.feedback-text'); const submitBtn = document.querySelector('.submit-btn'); const successMessage = document.querySelector('.success-message'); const resetBtns = document.querySelectorAll('.reset-btn'); const particlesContainer = document.querySelector('.particles'); const swipeHint = document.querySelector('.swipe-hint'); let currentRating = 0; let isSwiping = false; let startX, startY; const feedbackMessages = [ '', 'Needs improvement', 'Could be better', 'Pretty good', 'Great experience!', 'Absolutely loved it!' ]; // Touch event handling for swipe rating const starsContainer = document.querySelector('.stars-container'); starsContainer.addEventListener('touchstart', function(e) { isSwiping = true; startX = e.touches[0].clientX; startY = e.touches[0].clientY; }, { passive: true }); starsContainer.addEventListener('touchmove', function(e) { if (!isSwiping) return; const touchX = e.touches[0].clientX; const touchY = e.touches[0].clientY; // If vertical movement is greater than horizontal, don't process as swipe if (Math.abs(touchY - startY) > Math.abs(touchX - startX)) return; e.preventDefault(); // Get the star that was touched const containerRect = starsContainer.getBoundingClientRect(); const offsetX = touchX - containerRect.left; const containerWidth = containerRect.width; // Calculate which star based on position const starWidth = containerWidth / 5; let rating = Math.ceil(offsetX / starWidth); // Ensure rating is between 1 and 5 rating = Math.max(1, Math.min(5, rating)); setRating(rating); }); document.addEventListener('touchend', function() { isSwiping = false; }, { passive: true }); // Click handling for individual star selection stars.forEach(star => { star.addEventListener('click', function() { const rating = parseInt(star.getAttribute('data-value')); setRating(rating); // Add pulse animation to the clicked star star.classList.add('pulse'); setTimeout(() => { star.classList.remove('pulse'); }, 400); createParticles(star); }); star.addEventListener('mouseenter', function() { star.classList.add('hover'); }); star.addEventListener('mouseleave', function() { star.classList.remove('hover'); }); }); function setRating(rating) { currentRating = rating; // Update visual state of stars stars.forEach(star => { const starValue = parseInt(star.getAttribute('data-value')); if (starValue <= rating) { star.classList.add('active'); } else { star.classList.remove('active'); } }); // Update feedback text feedbackText.textContent = feedbackMessages[rating]; feedbackText.style.opacity = 1; // Show submit button submitBtn.classList.add('visible'); // Hide swipe hint swipeHint.style.opacity = 0; } function createParticles(element) { const rect = element.getBoundingClientRect(); const centerX = rect.left + rect.width / 2; const centerY = rect.top + rect.height / 2; // Create particles for (let i = 0; i < 8; i++) { const particle = document.createElement('div'); particle.className = 'particle'; // Random size between 4 and 8px const size = Math.random() * 4 + 4; particle.style.width = `${size}px`; particle.style.height = `${size}px`; // Position at the center of the clicked star particle.style.left = `${centerX}px`; particle.style.top = `${centerY}px`; // Random ending position const angle = Math.random() * Math.PI * 2; const distance = Math.random() * 60 + 20; const x = Math.cos(angle) * distance; const y = Math.sin(angle) * distance; // Random color related to gold const colors = ['#FFD700', '#FFC107', '#FFB300', '#FFA000']; const randomColor = colors[Math.floor(Math.random() * colors.length)]; particle.style.backgroundColor = randomColor; // Set animation variables particle.style.setProperty('--x', `${x}px`); particle.style.setProperty('--y', `${y}px`); // Animation particle.style.animation = `particle-animation ${Math.random() * 0.5 + 0.5}s ease-out forwards`; // Add to container particlesContainer.appendChild(particle); // Remove after animation setTimeout(() => { particlesContainer.removeChild(particle); }, 1000); } } submitBtn.addEventListener('click', function() { successMessage.classList.add('visible'); document.querySelector('.reset-btn').classList.add('visible'); }); resetBtns.forEach(btn => { btn.addEventListener('click', function() { // Reset stars stars.forEach(star => { star.classList.remove('active'); }); // Reset text and buttons feedbackText.textContent = ''; submitBtn.classList.remove('visible'); successMessage.classList.remove('visible'); document.querySelector('.reset-btn').classList.remove('visible'); // Show swipe hint again swipeHint.style.opacity = 0.8; currentRating = 0; }); }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Academic Course Evaluation</title> <style> @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&family=Playfair+Display:wght@400;700&display=swap'); :root { --primary-color: #3a4f6a; --secondary-color: #e9b44c; --accent-color: #9dc88d; --light-color: #f4f6f9; --dark-color: #1d2c3f; --error-color: #e45858; --success-color: #5cb85c; --transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1); } * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Roboto', sans-serif; background-color: var(--light-color); color: var(--dark-color); display: flex; justify-content: center; align-items: center; min-height: 100vh; padding: 20px; } .evaluation-container { background-color: white; border-radius: 8px; box-shadow: 0 8px 24px rgba(29, 44, 63, 0.12); width: 100%; max-width: 660px; padding: 30px; overflow: hidden; position: relative; } .evaluation-container::before { content: ""; position: absolute; top: 0; left: 0; width: 100%; height: 8px; background: linear-gradient(90deg, var(--primary-color), var(--secondary-color)); } .evaluation-header { margin-bottom: 25px; text-align: center; } .evaluation-header h1 { font-family: 'Playfair Display', serif; font-size: 28px; color: var(--primary-color); margin-bottom: 10px; letter-spacing: -0.5px; } .evaluation-header p { font-size: 16px; color: #666; line-height: 1.4; } .course-info { background-color: var(--light-color); border-radius: 6px; padding: 15px; margin-bottom: 25px; border-left: 4px solid var(--primary-color); } .course-info h2 { font-size: 18px; margin-bottom: 8px; color: var(--primary-color); } .course-details { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } .course-detail { display: flex; align-items: center; } .course-detail svg { margin-right: 8px; fill: var(--primary-color); opacity: 0.7; } .evaluation-section { margin-bottom: 25px; } .evaluation-section h3 { font-size: 16px; font-weight: 500; margin-bottom: 12px; padding-bottom: 6px; border-bottom: 1px solid #eee; color: var(--primary-color); } .rating-category { margin-bottom: 20px; } .rating-label { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; } .rating-title { font-weight: 500; font-size: 15px; } .rating-value { font-weight: 700; font-size: 16px; color: var(--secondary-color); min-width: 40px; text-align: right; } .stars-container { position: relative; display: inline-flex; cursor: pointer; } .stars-bg, .stars-fg { display: flex; } .stars-bg { color: #e0e0e0; } .stars-fg { position: absolute; top: 0; left: 0; overflow: hidden; width: 0%; color: var(--secondary-color); white-space: nowrap; transition: var(--transition); } .star { position: relative; width: 32px; height: 32px; display: flex; justify-content: center; align-items: center; transition: transform 0.2s ease; } .stars-container:hover .star, .stars-container.active .star { transform: scale(1.05); } .star-tooltip { position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%) translateY(-5px); background-color: var(--dark-color); color: white; padding: 5px 8px; border-radius: 4px; font-size: 12px; white-space: nowrap; opacity: 0; visibility: hidden; transition: var(--transition); pointer-events: none; } .star-tooltip::after { content: ''; position: absolute; top: 100%; left: 50%; margin-left: -5px; border-width: 5px; border-style: solid; border-color: var(--dark-color) transparent transparent transparent; } .star:hover .star-tooltip { opacity: 1; visibility: visible; transform: translateX(-50%) translateY(-10px); } .comments-section { margin-top: 25px; } .form-group { margin-bottom: 20px; } .form-group label { display: block; font-weight: 500; margin-bottom: 8px; font-size: 15px; } .form-control { width: 100%; padding: 12px 15px; border: 1px solid #ddd; border-radius: 4px; font-family: 'Roboto', sans-serif; font-size: 15px; transition: border-color 0.3s ease; background-color: #f9fbfd; } .form-control:focus { outline: none; border-color: var(--primary-color); box-shadow: 0 0 0 3px rgba(58, 79, 106, 0.1); } textarea.form-control { min-height: 120px; resize: vertical; } .button { display: inline-block; padding: 12px 24px; background-color: var(--primary-color); color: white; border: none; border-radius: 4px; font-size: 16px; font-weight: 500; cursor: pointer; transition: var(--transition); text-align: center; } .button:hover { background-color: var(--dark-color); transform: translateY(-2px); box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); } .button:active { transform: translateY(0); } .button-container { display: flex; justify-content: space-between; align-items: center; margin-top: 30px; } .reset-button { background-color: transparent; color: var(--primary-color); border: 1px solid #ddd; } .reset-button:hover { background-color: #f5f5f5; box-shadow: none; } .note { font-size: 13px; color: #777; margin-top: 10px; font-style: italic; } .submit-feedback { position: fixed; top: 20px; right: 20px; padding: 15px 20px; border-radius: 4px; color: white; font-weight: 500; opacity: 0; transform: translateY(-20px); transition: var(--transition); z-index: 1000; pointer-events: none; } .submit-feedback.success { background-color: var(--success-color); } .submit-feedback.error { background-color: var(--error-color); } .submit-feedback.show { opacity: 1; transform: translateY(0); } .progress-bar { position: absolute; bottom: 0; left: 0; height: 4px; width: 100%; background-color: #eee; overflow: hidden; } .progress-fill { height: 100%; width: 0; background-color: var(--accent-color); transition: width 0.3s ease; } @media (max-width: 600px) { .evaluation-container { padding: 20px; } .evaluation-header h1 { font-size: 22px; } .course-details { grid-template-columns: 1fr; } .star { width: 24px; height: 24px; } .button-container { flex-direction: column; gap: 15px; } .button { width: 100%; } } /* Animation classes */ @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.15); } 100% { transform: scale(1); } } @keyframes shimmer { 0% { box-shadow: 0 0 0 0 rgba(233, 180, 76, 0.7); } 70% { box-shadow: 0 0 0 10px rgba(233, 180, 76, 0); } 100% { box-shadow: 0 0 0 0 rgba(233, 180, 76, 0); } } .star.selected { animation: pulse 0.4s ease-in-out; } .stars-container.all-rated { animation: shimmer 1.5s infinite; } </style> </head> <body> <div class="evaluation-container"> <div class="evaluation-header"> <h1>Academic Course Evaluation</h1> <p>Your feedback is crucial for continuous improvement of our educational offerings. Please evaluate your experience with precision.</p> </div> <div class="course-info"> <h2>Course Information</h2> <div class="course-details"> <div class="course-detail"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24"> <path d="M12 2L0 9l4 2.18v6L12 22l8-4.82v-6L24 9L12 2zm6.82 9.76l-6.82 3.9-6.82-3.9L12 7.4l6.82 4.36zM12 4.2L5 8.6v4.96l7 4v-8.76l7-4v8.76l-7 4v-8.76z"/> </svg> <span>COMP 3750: Advanced Data Structures</span> </div> <div class="course-detail"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24"> <path d="M17 1c0-.552-.447-1-1-1s-1 .448-1 1v2c0 .552.447 1 1 1s1-.448 1-1v-2zm-12 2c0 .552-.447 1-1 1s-1-.448-1-1v-2c0-.552.447-1 1-1s1 .448 1 1v2zm13 5v10h-16v-10h16zm2-6h-2v1c0 1.103-.897 2-2 2s-2-.897-2-2v-1h-8v1c0 1.103-.897 2-2 2s-2-.897-2-2v-1h-2v18h20v-18zm-11.646 14c-1.318 0-2.397-1.078-2.397-2.398 0-1.318 1.079-2.397 2.397-2.397 1.32 0 2.398 1.079 2.398 2.397 0 1.32-1.078 2.398-2.398 2.398z"/> </svg> <span>Fall Semester 2023</span> </div> <div class="course-detail"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24"> <path d="M12 0c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm0 22c-5.514 0-10-4.486-10-10s4.486-10 10-10 10 4.486 10 10-4.486 10-10 10zm.5-18h-1v8.5l6.5 3.25.75-1.23-6.25-3.02v-7.5z"/> </svg> <span>75 Total Contact Hours</span> </div> <div class="course-detail"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24"> <path d="M20 13.44v-3.44c0-1.32.04-2.46 0-3.06-.05-.84-.66-1.45-1.3-1.7-.89-.35-1.92-.14-2.57.36l-5.13 4.04-5.13-4.04c-.65-.5-1.68-.71-2.57-.36-.64.25-1.25.86-1.3 1.7-.04.6 0 1.74 0 3.06v3.44s0 2.56 0 3.06c.05.84.66 1.45 1.3 1.7.89.35 1.92.14 2.57-.36l5.13-4.04 5.13 4.04c.65.5 1.68.71 2.57.36.64-.25 1.25-.86 1.3-1.7 0-.5 0-3.06 0-3.06zm-14 1.56v-6c0-.22.18-.39.4-.4l4.6 3.59-4.6 3.61c-.22-.01-.4-.18-.4-.4v-.4zm12 0c0 .22-.18.39-.4.4l-4.6-3.61 4.6-3.59c.22.01.4.18.4.4v6.4z"/> </svg> <span>Prof. Elena Rodriguez</span> </div> </div> </div> <div class="evaluation-section"> <h3>Course Content Evaluation</h3> <div class="rating-category"> <div class="rating-label"> <span class="rating-title">Curriculum Relevance</span> <span class="rating-value" id="relevance-value">0.0</span> </div> <div class="stars-container" data-category="relevance"> <div class="stars-bg"> <div class="star" data-value="1"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z"/> </svg> <span class="star-tooltip">Outdated</span> </div> <div class="star" data-value="2"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z"/> </svg> <span class="star-tooltip">Somewhat Relevant</span> </div> <div class="star" data-value="3"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z"/> </svg> <span class="star-tooltip">Adequate</span> </div> <div class="star" data-value="4"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z"/> </svg> <span class="star-tooltip">Relevant</span> </div> <div class="star" data-value="5"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z"/> </svg> <span class="star-tooltip">Cutting-Edge</span> </div> </div> <div class="stars-fg" id="relevance-fg"> <div class="star"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z"/> </svg> </div> <div class="star"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z"/> </svg> </div> <div class="star"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z"/> </svg> </div> <div class="star"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z"/> </svg> </div> <div class="star"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z"/> </svg> </div> </div> </div> </div> <div class="rating-category"> <div class="rating-label"> <span class="rating-title">Academic Depth</span> <span class="rating-value" id="depth-value">0.0</span> </div> <div class="stars-container" data-category="depth"> <div class="stars-bg"> <div class="star" data-value="1"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z"/> </svg> <span class="star-tooltip">Superficial</span> </div> <div class="star" data-value="2"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z"/> </svg> <span class="star-tooltip">Basic</span> </div> <div class="star" data-value="3"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z"/> </svg> <span class="star-tooltip">Moderate</span> </div> <div class="star" data-value="4"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z"/> </svg> <span class="star-tooltip">Substantial</span> </div> <div class="star" data-value="5"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z"/> </svg> <span class="star-tooltip">Profound</span> </div> </div> <div class="stars-fg" id="depth-fg"> <div class="star"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z"/> </svg> </div> <div class="star"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z"/> </svg> </div> <div class="star"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z"/> </svg> </div> <div class="star"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z"/> </svg> </div> <div class="star"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z"/> </svg> </div> </div> </div> </div> </div> <div class="evaluation-section"> <h3>Instructional Quality Assessment</h3> <div class="rating-category"> <div class="rating-label"> <span class="rating-title">Pedagogical Effectiveness</span> <span class="rating-value" id="pedagogy-value">0.0</span> </div> <div class="stars-container" data-category="pedagogy"> <div class="stars-bg"> <div class="star" data-value="1"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z"/> </svg> <span class="star-tooltip">Ineffective</span> </div> <div class="star" data-value="2"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z"/> </svg> <span class="star-tooltip">Minimal</span> </div> <div class="star" data-value="3"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z"/> </svg> <span class="star-tooltip">Satisfactory</span> </div> <div class="star" data-value="4"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z"/> </svg> <span class="star-tooltip">Effective</span> </div> <div class="star" data-value="5"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z"/> </svg> <span class="star-tooltip">Exceptional</span> </div> </div> <div class="stars-fg" id="pedagogy-fg"> <div class="star"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z"/> </svg> </div> <div class="star"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z"/> </svg> </div> <div class="star"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z"/> </svg> </div> <div class="star"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z"/> </svg> </div> <div class="star"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z"/> </svg> </div> </div> </div> </div> <div class="rating-category"> <div class="rating-label"> <span class="rating-title">Assessment Quality</span> <span class="rating-value" id="assessment-value">0.0</span> </div> <div class="stars-container" data-category="assessment"> <div class="stars-bg"> <div class="star" data-value="1"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z"/> </svg> <span class="star-tooltip">Misaligned</span> </div> <div class="star" data-value="2"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 .587l3.668 7.568 8
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; } body { background-color: #0f0f17; color: #f5f5f7; display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 100vh; padding: 20px; transition: background-color 0.3s ease; overflow-x: hidden; width: 100%; height: 100%; } .container { width: 100%; max-width: 600px; position: relative; z-index: 1; } .bg-glow { position: absolute; width: 350px; height: 350px; background: radial-gradient(circle, rgba(153, 0, 255, 0.2) 0%, rgba(0, 0, 0, 0) 70%); top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 0; pointer-events: none; filter: blur(30px); transition: all 0.5s ease; } h1 { font-size: 2.4rem; margin-bottom: 20px; font-weight: 700; letter-spacing: -0.5px; background: linear-gradient(90deg, #ff6b6b, #cc66ff); -webkit-background-clip: text; background-clip: text; color: transparent; text-align: center; } .content-card { background: rgba(20, 20, 35, 0.7); border-radius: 16px; padding: 30px; backdrop-filter: blur(10px); box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3); margin-bottom: 30px; border: 1px solid rgba(255, 255, 255, 0.05); transition: transform 0.3s ease, box-shadow 0.3s ease; overflow: hidden; position: relative; } .content-card:hover { transform: translateY(-5px); box-shadow: 0 15px 40px rgba(121, 40, 202, 0.2); } .card-info { display: flex; align-items: flex-start; margin-bottom: 25px; } .thumbnail { width: 100px; height: 150px; border-radius: 8px; object-fit: cover; border: 2px solid rgba(255, 255, 255, 0.1); transition: transform 0.3s ease, border 0.3s ease; overflow: hidden; position: relative; } .thumbnail:hover { transform: scale(1.05); border: 2px solid rgba(153, 0, 255, 0.5); } .info { margin-left: 20px; flex: 1; } .title { font-size: 1.8rem; font-weight: 700; margin-bottom: 5px; color: #fff; } .meta { color: #a0a0a0; font-size: 0.95rem; margin-bottom: 10px; } .meta span { margin-right: 15px; } .description { color: #cccccc; font-size: 0.95rem; line-height: 1.5; margin-bottom: 15px; } .genre { display: inline-block; background: rgba(153, 0, 255, 0.15); color: #cc66ff; padding: 4px 10px; border-radius: 20px; font-size: 0.85rem; margin-right: 8px; margin-bottom: 8px; border: 1px solid rgba(153, 0, 255, 0.3); } .rating-system { margin: 25px 0 15px; } .rating-title { font-size: 1.2rem; margin-bottom: 15px; color: #fff; font-weight: 600; letter-spacing: 0.5px; display: flex; align-items: center; } .rating-title svg { margin-right: 8px; color: #cc66ff; } .stars-container { display: flex; gap: 10px; margin-bottom: 20px; } .star { width: 50px; height: 50px; position: relative; cursor: pointer; transition: transform 0.2s ease; } .star:hover { transform: scale(1.1); } .star svg { width: 100%; height: 100%; position: absolute; top: 0; left: 0; fill: none; stroke: rgba(255, 255, 255, 0.3); stroke-width: 1; transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); } .star:hover svg { stroke: rgba(255, 255, 255, 0.8); filter: drop-shadow(0 0 5px rgba(153, 0, 255, 0.7)); } .star.active svg { fill: #cc66ff; stroke: #cc66ff; filter: drop-shadow(0 0 8px rgba(153, 0, 255, 0.8)); } .rating-feedback { min-height: 24px; margin-top: 5px; color: #a0a0a0; font-size: 1rem; transition: all 0.3s ease; opacity: 0; transform: translateY(10px); } .rating-feedback.visible { opacity: 1; transform: translateY(0); } .submit-btn { margin-top: 20px; background: linear-gradient(90deg, #ff6b6b, #cc66ff); border: none; color: white; padding: 12px 30px; border-radius: 30px; font-size: 1rem; font-weight: 600; cursor: pointer; transition: all 0.3s ease; box-shadow: 0 5px 15px rgba(153, 0, 255, 0.3); position: relative; overflow: hidden; } .submit-btn:hover { transform: translateY(-2px); box-shadow: 0 8px 20px rgba(153, 0, 255, 0.4); } .submit-btn:active { transform: translateY(1px); } .submit-btn::before { content: ""; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent); transition: all 0.6s ease; } .submit-btn:hover::before { left: 100%; } .success-message { margin-top: 20px; padding: 15px; background: rgba(0, 255, 128, 0.1); border-radius: 8px; border-left: 4px solid #00cc66; color: #00cc66; display: none; animation: fadeIn 0.5s ease; } .rating-display { margin-top: 30px; text-align: center; } .rating-avg { font-size: 1.8rem; color: #cc66ff; font-weight: 700; margin-bottom: 5px; display: flex; align-items: center; justify-content: center; } .rating-avg svg { margin-left: 5px; fill: #cc66ff; } .rating-count { color: #a0a0a0; font-size: 0.9rem; } @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } @keyframes pulse { 0% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.1); opacity: 0.8; } 100% { transform: scale(1); opacity: 1; } } @keyframes glow { 0% { box-shadow: 0 0 5px #cc66ff, 0 0 10px #cc66ff; } 100% { box-shadow: 0 0 20px #cc66ff, 0 0 30px #cc66ff; } } @media (max-width: 600px) { .card-info { flex-direction: column; } .thumbnail { width: 100%; height: 200px; margin-bottom: 20px; } .info { margin-left: 0; } .stars-container { justify-content: center; } .star { width: 45px; height: 45px; } h1 { font-size: 2rem; } .title { font-size: 1.5rem; } } /* Star animation effects */ @keyframes starPop { 0% { transform: scale(1); } 50% { transform: scale(1.2); } 100% { transform: scale(1); } } .star.active { animation: starPop 0.4s ease; } .star-hover-glow { position: absolute; width: 100%; height: 100%; background: radial-gradient(circle, rgba(204, 102, 255, 0.6) 0%, rgba(0, 0, 0, 0) 70%); filter: blur(8px); z-index: -1; opacity: 0; transition: opacity 0.3s ease; pointer-events: none; } .star:hover .star-hover-glow { opacity: 1; } .submission-complete { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: rgba(15, 15, 23, 0.9); display: flex; flex-direction: column; align-items: center; justify-content: center; z-index: 10; opacity: 0; visibility: hidden; transition: all 0.5s ease; border-radius: 16px; } .submission-complete.visible { opacity: 1; visibility: visible; } .checkmark { width: 80px; height: 80px; border-radius: 50%; display: flex; align-items: center; justify-content: center; background: linear-gradient(45deg, #cc66ff, #ff6b6b); margin-bottom: 20px; position: relative; animation: pulse 2s infinite; } .checkmark svg { width: 40px; height: 40px; stroke: white; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; } .completion-message { font-size: 1.5rem; color: white; margin-bottom: 10px; text-align: center; } .completion-subtitle { color: #a0a0a0; text-align: center; max-width: 80%; margin-bottom: 30px; } .completion-continue { background: rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.2); color: white; padding: 10px 25px; border-radius: 30px; cursor: pointer; transition: all 0.3s ease; } .completion-continue:hover { background: rgba(255, 255, 255, 0.2); } /* Pulse animation for the background glow */ @keyframes backgroundPulse { 0% { transform: translate(-50%, -50%) scale(1); opacity: 0.2; } 50% { transform: translate(-50%, -50%) scale(1.1); opacity: 0.3; } 100% { transform: translate(-50%, -50%) scale(1); opacity: 0.2; } } .bg-glow { animation: backgroundPulse 10s ease infinite; } </style> </head> <body> <div class="bg-glow"></div> <div class="container"> <h1>NetfluxRate</h1> <div class="content-card"> <div class="card-info"> <img src="https://images.unsplash.com/photo-1535016120720-40c646be5580?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1287&q=80" alt="Film thumbnail" class="thumbnail"> <div class="info"> <h2 class="title">Neon Horizon</h2> <div class="meta"> <span>2023</span> <span>2h 18m</span> <span>4K Ultra HD</span> </div> <p class="description">A cyberpunk thriller where digital consciousness and reality blur. When a rogue AI begins manipulating a virtual playground for the wealthy, a hacker must confront her own identity to save both worlds.</p> <div> <span class="genre">Sci-Fi</span> <span class="genre">Thriller</span> <span class="genre">Cyberpunk</span> </div> </div> </div> <div class="rating-system"> <h3 class="rating-title"> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path> </svg> Rate This Title </h3> <div class="stars-container"> <div class="star" data-value="1"> <div class="star-hover-glow"></div> <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z"></path> </svg> </div> <div class="star" data-value="2"> <div class="star-hover-glow"></div> <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z"></path> </svg> </div> <div class="star" data-value="3"> <div class="star-hover-glow"></div> <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z"></path> </svg> </div> <div class="star" data-value="4"> <div class="star-hover-glow"></div> <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z"></path> </svg> </div> <div class="star" data-value="5"> <div class="star-hover-glow"></div> <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z"></path> </svg> </div> </div> <div class="rating-feedback"></div> <button class="submit-btn" disabled>Submit Rating</button> <div class="success-message">Your rating has been successfully submitted!</div> <div class="rating-display"> <div class="rating-avg"> 4.7 <svg width="20" height="20" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z"></path> </svg> </div> <div class="rating-count">Based on 1,482 ratings</div> </div> </div> <div class="submission-complete"> <div class="checkmark"> <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M20 6L9 17L4 12" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </div> <h3 class="completion-message">Rating Submitted!</h3> <p class="completion-subtitle">Your feedback helps improve recommendations for your profile.</p> <button class="completion-continue">Continue Watching</button> </div> </div> </div> <script> const stars = document.querySelectorAll('.star'); const submitBtn = document.querySelector('.submit-btn'); const feedbackEl = document.querySelector('.rating-feedback'); const successMessage = document.querySelector('.success-message'); const submissionComplete = document.querySelector('.submission-complete'); const continueBtn = document.querySelector('.completion-continue'); const bgGlow = document.querySelector('.bg-glow'); const feedbackMessages = [ "Not worth my time", "Disappointing, had potential", "Average, nothing special", "Really enjoyed it, would recommend", "Absolute masterpiece, must-watch!" ]; let currentRating = 0; // Function to update star states based on selected rating function updateStars(rating) { stars.forEach(star => { const starValue = parseInt(star.getAttribute('data-value')); if (starValue <= rating) { star.classList.add('active'); } else { star.classList.remove('active'); } }); } // Handle star hover stars.forEach(star => { star.addEventListener('mouseover', () => { const hoverValue = parseInt(star.getAttribute('data-value')); updateStars(hoverValue); }); }); // Handle star click stars.forEach(star => { star.addEventListener('click', () => { const clickedValue = parseInt(star.getAttribute('data-value')); if (currentRating === clickedValue) { // Toggle off the star if it's already selected currentRating = 0; updateStars(0); feedbackEl.textContent = ''; feedbackEl.classList.remove('visible'); submitBtn.disabled = true; } else { // Set new rating currentRating = clickedValue; updateStars(currentRating); // Show feedback message feedbackEl.textContent = feedbackMessages[currentRating - 1]; feedbackEl.classList.add('visible'); // Enable submit button submitBtn.disabled = false; } // Update background glow position based on rating const glowColor = currentRating > 3 ? 'rgba(153, 0, 255, 0.3)' : currentRating > 1 ? 'rgba(255, 107, 107, 0.3)' : 'rgba(255, 0, 0, 0.2)'; bgGlow.style.background = `radial-gradient(circle, ${glowColor} 0%, rgba(0, 0, 0, 0) 70%)`; }); }); // Reset stars when mouse leaves the container document.querySelector('.stars-container').addEventListener('mouseleave', () => { updateStars(currentRating); }); // Handle submit button click submitBtn.addEventListener('click', () => { if (currentRating > 0) { submissionComplete.classList.add('visible'); // Simulate rating count update const countEl = document.querySelector('.rating-count'); let currentCount = parseInt(countEl.textContent.match(/\d+,\d+/)[0].replace(',', '')); currentCount++; countEl.textContent = `Based on ${currentCount.toLocaleString()} ratings`; // Simulate rating average update const avgEl = document.querySelector('.rating-avg'); let currentAvg = parseFloat(avgEl.textContent); let newAvg = (currentAvg * (currentCount - 1) + currentRating) / currentCount; avgEl.textContent = newAvg.toFixed(1); // Add SVG back after text content change avgEl.innerHTML = `${newAvg.toFixed(1)} <svg width="20" height="20" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z"></path> </svg>`; } }); // Handle continue button click continueBtn.addEventListener('click', () => { submissionComplete.classList.remove('visible'); // Reset rating currentRating = 0; updateStars(0); feedbackEl.textContent = ''; feedbackEl.classList.remove('visible'); submitBtn.disabled = true; // Reset background glow bgGlow.style.background = 'radial-gradient(circle, rgba(153, 0, 255, 0.2) 0%, rgba(0, 0, 0, 0) 70%)'; }); // On initial load, create a slight pulsing effect document.addEventListener('DOMContentLoaded', () => { setTimeout(() => { stars.forEach(star => { star.style.transition = 'transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275)'; }); }, 500); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Neighborhood Gems Rating Widget</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { display: flex; justify-content: center; align-items: center; min-height: 700px; width: 100%; max-width: 700px; margin: 0 auto; background-color: #f9f7f5; padding: 20px; } .rating-container { background: linear-gradient(145deg, #ffffff, #f5f0e8); border-radius: 20px; box-shadow: 0 10px 30px rgba(200, 145, 90, 0.15); padding: 30px; width: 100%; max-width: 600px; transition: transform 0.3s ease, box-shadow 0.3s ease; position: relative; overflow: hidden; } .rating-container:hover { transform: translateY(-5px); box-shadow: 0 15px 35px rgba(200, 145, 90, 0.2); } h1 { color: #2e384d; font-size: 2rem; margin-bottom: 10px; position: relative; display: inline-block; } h1::after { content: ''; position: absolute; bottom: -5px; left: 0; width: 60px; height: 3px; background: linear-gradient(90deg, #f8b64c, #e67e22); border-radius: 3px; } .subtitle { color: #5d6778; margin-bottom: 30px; font-size: 1rem; line-height: 1.5; } .business-card { display: flex; align-items: center; background-color: #fff; border-radius: 15px; padding: 15px; margin-bottom: 25px; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05); transition: transform 0.2s ease; } .business-card:hover { transform: scale(1.02); } .business-img { width: 80px; height: 80px; border-radius: 50%; object-fit: cover; margin-right: 15px; border: 3px solid #fcf0e3; } .business-info h2 { color: #2e384d; font-size: 1.3rem; margin-bottom: 5px; } .business-type { color: #e67e22; font-size: 0.9rem; margin-bottom: 8px; font-weight: 500; } .business-address { color: #6c757d; font-size: 0.85rem; } .rating-title { font-weight: 600; color: #2e384d; margin-bottom: 15px; font-size: 1.1rem; } .stars-outer { display: inline-block; position: relative; font-size: 2.5rem; cursor: pointer; } .stars-inner { position: absolute; top: 0; left: 0; white-space: nowrap; overflow: hidden; width: 0; color: #f8b64c; transition: width 0.3s cubic-bezier(0.34, 1.56, 0.64, 1); } .stars-outer::before { content: "☆☆☆☆☆"; color: #ddd; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); } .stars-inner::before { content: "★★★★★"; text-shadow: 0 1px 3px rgba(250, 170, 20, 0.3); } .rating-value { margin-top: 15px; color: #e67e22; font-weight: 700; font-size: 2rem; opacity: 0; transform: translateY(10px); transition: opacity 0.3s ease, transform 0.3s ease; } .rating-value.show { opacity: 1; transform: translateY(0); } .feedback-form { margin-top: 30px; } textarea { width: 100%; padding: 15px; border-radius: 10px; border: 1px solid #e1e5ea; resize: none; height: 120px; margin-bottom: 15px; font-size: 0.95rem; color: #495057; transition: border-color 0.2s ease, box-shadow 0.2s ease; background-color: #fff; } textarea:focus { outline: none; border-color: #f8b64c; box-shadow: 0 0 0 3px rgba(248, 182, 76, 0.2); } .submit-btn { background: linear-gradient(90deg, #f8b64c, #e67e22); color: white; border: none; padding: 12px 25px; border-radius: 50px; font-weight: 600; cursor: pointer; transition: transform 0.2s ease, box-shadow 0.2s ease; font-size: 1rem; display: inline-block; box-shadow: 0 4px 10px rgba(230, 126, 34, 0.2); } .submit-btn:hover { transform: translateY(-2px); box-shadow: 0 6px 15px rgba(230, 126, 34, 0.3); } .submit-btn:active { transform: translateY(0); box-shadow: 0 2px 5px rgba(230, 126, 34, 0.3); } .success-message { background-color: rgba(52, 199, 89, 0.1); color: #28a745; padding: 15px; border-radius: 10px; font-weight: 500; margin-top: 20px; display: none; align-items: center; animation: fadeSlideUp 0.5s ease forwards; } @keyframes fadeSlideUp { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .success-icon { font-size: 1.5rem; margin-right: 10px; } .pattern { position: absolute; top: 0; right: 0; width: 150px; height: 150px; opacity: 0.05; background-image: radial-gradient(#e67e22 1px, transparent 1px), radial-gradient(#e67e22 1px, transparent 1px); background-size: 15px 15px; background-position: 0 0, 7.5px 7.5px; border-radius: 0 20px 0 0; pointer-events: none; } .star-hint { background-color: rgba(52, 152, 219, 0.9); color: white; padding: 5px 10px; border-radius: 5px; position: absolute; top: -40px; white-space: nowrap; font-size: 0.85rem; opacity: 0; transition: opacity 0.3s ease, transform 0.3s ease; transform: translateY(5px); box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1); pointer-events: none; } .star-hint::after { content: ''; position: absolute; bottom: -5px; left: 50%; transform: translateX(-50%); border-left: 6px solid transparent; border-right: 6px solid transparent; border-top: 6px solid rgba(52, 152, 219, 0.9); } .stars-container { position: relative; display: inline-block; } .rating-label { font-size: 0.9rem; color: #6c757d; margin-top: 10px; font-style: italic; } @media (max-width: 500px) { .rating-container { padding: 20px; } h1 { font-size: 1.5rem; } .business-img { width: 60px; height: 60px; } .business-info h2 { font-size: 1.1rem; } .stars-outer { font-size: 2rem; } .rating-value { font-size: 1.5rem; } } @media (max-width: 350px) { .business-card { flex-direction: column; text-align: center; } .business-img { margin-right: 0; margin-bottom: 10px; } } .star-pulse { animation: starPulse 0.5s ease; } @keyframes starPulse { 0% { transform: scale(1); } 50% { transform: scale(1.2); } 100% { transform: scale(1); } } .confetti { position: absolute; width: 10px; height: 10px; opacity: 0; pointer-events: none; } .thank-you { font-weight: 700; color: #2e384d; margin-bottom: 5px; } </style> </head> <body> <div class="rating-container"> <div class="pattern"></div> <h1>Neighborhood Gems</h1> <p class="subtitle">Support local businesses by sharing your experiences. Your feedback helps our community thrive!</p> <div class="business-card"> <img src="https://images.unsplash.com/photo-1414235077428-338989a2e8c0?ixlib=rb-1.2.1&auto=format&fit=crop&w=200&q=80" alt="Rustic Spoon Café" class="business-img"> <div class="business-info"> <h2>Rustic Spoon Café</h2> <p class="business-type">Farm-to-Table Restaurant</p> <p class="business-address">342 Maple Street, Downtown</p> </div> </div> <div class="rating-section"> <p class="rating-title">How was your experience?</p> <div class="stars-container"> <div class="stars-outer"> <div class="stars-inner"></div> </div> <div class="star-hint">Select your rating</div> </div> <p class="rating-value">0.0</p> <p class="rating-label"></p> </div> <div class="feedback-form"> <textarea placeholder="Share what you loved or how they could improve (optional)"></textarea> <button class="submit-btn">Submit Review</button> </div> <div class="success-message"> <span class="success-icon">✓</span> <div> <p class="thank-you">Thank you for your review!</p> <p>Your feedback helps Rustic Spoon Café and our community.</p> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { const starsOuter = document.querySelector('.stars-outer'); const starsInner = document.querySelector('.stars-inner'); const ratingValue = document.querySelector('.rating-value'); const ratingLabel = document.querySelector('.rating-label'); const starHint = document.querySelector('.star-hint'); const submitBtn = document.querySelector('.submit-btn'); const successMessage = document.querySelector('.success-message'); const starsContainer = document.querySelector('.stars-container'); let rating = 0; let mouseOverRating = 0; const labels = [ "", "Needs improvement", "Fair", "Good", "Very good", "Excellent!" ]; // Create star positions for better touch/click precision const starPositions = [0, 0.2, 0.4, 0.6, 0.8]; // Function to set rating function setRating(newRating) { rating = newRating; starsInner.style.width = `${rating * 20}%`; ratingValue.textContent = rating.toFixed(1); ratingLabel.textContent = labels[Math.ceil(rating)]; if (!ratingValue.classList.contains('show')) { ratingValue.classList.add('show'); } // Add pulse animation starsInner.classList.add('star-pulse'); setTimeout(() => { starsInner.classList.remove('star-pulse'); }, 500); if (rating >= 4) { createConfetti(); } } // Create confetti effect for high ratings function createConfetti() { const colors = ['#f8b64c', '#e67e22', '#3498db', '#2ecc71', '#e74c3c', '#9b59b6']; const confettiContainer = document.querySelector('.rating-container'); for (let i = 0; i < 50; i++) { const confetti = document.createElement('div'); confetti.className = 'confetti'; confetti.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)]; confetti.style.left = `${Math.random() * 100}%`; confetti.style.top = `${30 + Math.random() * 20}%`; confetti.style.transform = `rotate(${Math.random() * 360}deg)`; confettiContainer.appendChild(confetti); // Animate confetti const animationDuration = 1 + Math.random() * 2; const animationDelay = Math.random() * 0.5; confetti.style.animation = ` confettiDrop ${animationDuration}s ease ${animationDelay}s forwards `; setTimeout(() => { confetti.remove(); }, (animationDuration + animationDelay) * 1000); } } // Add animation keyframes dynamically const style = document.createElement('style'); style.textContent = ` @keyframes confettiDrop { 0% { transform: translateY(0) rotate(0deg); opacity: 1; } 100% { transform: translateY(200px) rotate(720deg); opacity: 0; } } `; document.head.appendChild(style); // Handle mousemove starsOuter.addEventListener('mousemove', function(e) { const rect = starsOuter.getBoundingClientRect(); const position = (e.clientX - rect.left) / rect.width; if (position < 0) return; // Convert position to star rating (0.1 to 5.0) const rawRating = position * 5; mouseOverRating = Math.round(rawRating * 10) / 10; // Clamp to valid range mouseOverRating = Math.max(0.1, Math.min(5, mouseOverRating)); // Preview the rating starsInner.style.width = `${mouseOverRating * 20}%`; // Show hint with current rating value starHint.textContent = mouseOverRating.toFixed(1); starHint.style.opacity = '1'; starHint.style.transform = 'translateY(0)'; // Position the hint const hintPosition = (mouseOverRating / 5) * rect.width; starHint.style.left = `${Math.min(Math.max(hintPosition, 20), rect.width - 40)}px`; }); // Handle mouseout starsOuter.addEventListener('mouseout', function() { // Restore actual rating when mouse leaves starsInner.style.width = `${rating * 20}%`; starHint.style.opacity = '0'; starHint.style.transform = 'translateY(5px)'; }); // Handle click starsOuter.addEventListener('click', function(e) { const rect = starsOuter.getBoundingClientRect(); const position = (e.clientX - rect.left) / rect.width; // Convert position to star rating (0.1 to 5.0) const rawRating = position * 5; let clickedRating = Math.round(rawRating * 10) / 10; // Clamp to valid range clickedRating = Math.max(0.1, Math.min(5, clickedRating)); setRating(clickedRating); }); // Handle touch for mobile starsOuter.addEventListener('touchmove', function(e) { e.preventDefault(); const touch = e.touches[0]; const rect = starsOuter.getBoundingClientRect(); const position = (touch.clientX - rect.left) / rect.width; if (position < 0 || position > 1) return; // Convert position to star rating (0.1 to 5.0) const rawRating = position * 5; mouseOverRating = Math.round(rawRating * 10) / 10; // Clamp to valid range mouseOverRating = Math.max(0.1, Math.min(5, mouseOverRating)); // Preview the rating starsInner.style.width = `${mouseOverRating * 20}%`; // Show hint with current rating value starHint.textContent = mouseOverRating.toFixed(1); starHint.style.opacity = '1'; starHint.style.transform = 'translateY(0)'; // Position the hint const hintPosition = (mouseOverRating / 5) * rect.width; starHint.style.left = `${Math.min(Math.max(hintPosition, 20), rect.width - 40)}px`; }); starsOuter.addEventListener('touchend', function(e) { if (mouseOverRating > 0) { setRating(mouseOverRating); } starHint.style.opacity = '0'; starHint.style.transform = 'translateY(5px)'; }); // Handle form submission submitBtn.addEventListener('click', function() { if (rating === 0) { starHint.textContent = "Please select a rating"; starHint.style.opacity = '1'; starHint.style.transform = 'translateY(0)'; starHint.style.left = '50%'; starHint.style.transform = 'translateX(-50%)'; setTimeout(() => { starHint.style.opacity = '0'; }, 2000); return; } // Hide the form elements with animation document.querySelector('.feedback-form').style.opacity = '0.5'; document.querySelector('.feedback-form').style.pointerEvents = 'none'; // Show success message successMessage.style.display = 'flex'; // Reset form fields (optional) document.querySelector('textarea').value = ''; }); }); </script> </body> </html>
<html> <head> <style> :root { --primary: #4C5EFD; --secondary: #FF6B6B; --dark: #2D3250; --light: #F8F9FA; --gray: #AAB2BD; --success: #26DE81; --warning: #FFC107; --font-primary: 'Poppins', sans-serif; } * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: var(--font-primary); background: var(--light); color: var(--dark); display: flex; flex-direction: column; justify-content: center; align-items: center; height: 100vh; background: linear-gradient(135deg, #f5f7fa 0%, #e4e8f0 100%); overflow: hidden; } .container { max-width: 650px; margin: 0 auto; background: white; border-radius: 20px; padding: 40px; box-shadow: 0 15px 35px rgba(45, 50, 80, 0.1); transform: translateY(0); transition: transform 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275); } .container:hover { transform: translateY(-5px); } h1 { font-size: 32px; font-weight: 700; margin-bottom: 10px; color: var(--dark); text-align: center; } h2 { font-size: 18px; font-weight: 500; color: var(--gray); margin-bottom: 30px; text-align: center; } .rating-section { margin-bottom: 30px; position: relative; transition: all 0.3s ease; } .restaurant-card { display: flex; align-items: center; margin-bottom: 30px; padding-bottom: 20px; border-bottom: 1px solid #f0f0f0; } .restaurant-image { width: 80px; height: 80px; border-radius: 12px; object-fit: cover; margin-right: 20px; box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1); } .restaurant-details h3 { font-size: 22px; font-weight: 600; margin-bottom: 5px; } .restaurant-details p { font-size: 14px; color: var(--gray); margin-bottom: 8px; } .restaurant-tags { display: flex; flex-wrap: wrap; gap: 8px; } .tag { background: #f0f2f5; border-radius: 15px; padding: 4px 12px; font-size: 12px; color: var(--dark); } .rating-container { text-align: center; margin-bottom: 25px; } .stars-container { display: inline-flex; position: relative; font-size: 0; } .stars-display { display: inline-flex; font-size: 0; } .stars-fillable { position: absolute; top: 0; left: 0; font-size: 0; pointer-events: none; overflow: hidden; width: 0; transition: width 0.3s ease; } .star { display: inline-block; width: 42px; height: 42px; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23AAB2BD'%3E%3Cpath d='M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21 12 17.27z'/%3E%3C/svg%3E"); background-size: contain; background-repeat: no-repeat; cursor: pointer; transition: transform 0.2s ease; position: relative; } .star:hover { transform: scale(1.1); } .stars-fillable .star { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23FF6B6B'%3E%3Cpath d='M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21 12 17.27z'/%3E%3C/svg%3E"); } .rating-value { font-size: 24px; font-weight: 700; margin-top: 10px; color: var(--secondary); transition: all 0.3s ease; display: flex; align-items: center; justify-content: center; gap: 8px; } .rating-hint { font-size: 14px; color: var(--gray); } textarea { width: 100%; height: 120px; border: 2px solid #e4e8f0; border-radius: 12px; padding: 15px; font-family: var(--font-primary); resize: none; margin-bottom: 20px; font-size: 15px; transition: all 0.3s ease; } textarea:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px rgba(76, 94, 253, 0.1); } .button { background: var(--primary); color: white; border: none; border-radius: 12px; padding: 14px 28px; font-size: 16px; font-weight: 600; cursor: pointer; transition: all 0.3s ease; display: block; width: 100%; box-shadow: 0 5px 15px rgba(76, 94, 253, 0.3); } .button:hover { background: #3d4ff0; transform: translateY(-2px); box-shadow: 0 8px 20px rgba(76, 94, 253, 0.4); } .button:active { transform: translateY(1px); } .community-stats { display: flex; justify-content: space-between; margin-top: 35px; padding-top: 25px; border-top: 1px solid #f0f0f0; } .stat-item { text-align: center; flex: 1; padding: 0 10px; position: relative; } .stat-item:not(:last-child)::after { content: ''; position: absolute; right: 0; top: 50%; transform: translateY(-50%); height: 70%; width: 1px; background-color: #f0f0f0; } .stat-value { font-size: 28px; font-weight: 700; color: var(--primary); margin-bottom: 5px; animation: countUp 1.5s ease-out forwards; } .stat-label { font-size: 13px; color: var(--gray); font-weight: 500; } .rating-feedback { height: 20px; margin-top: 10px; font-size: 14px; font-weight: 500; transition: all 0.3s ease; opacity: 0; transform: translateY(10px); } .rating-feedback.show { opacity: 1; transform: translateY(0); } .emoji { font-size: 22px; margin-right: 5px; } .confetti { position: absolute; width: 10px; height: 10px; background-color: var(--primary); border-radius: 0; pointer-events: none; opacity: 0; } @keyframes countUp { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } } @media (max-width: 600px) { .container { padding: 25px; border-radius: 15px; } h1 { font-size: 26px; } h2 { font-size: 16px; } .star { width: 36px; height: 36px; } .community-stats { flex-direction: column; gap: 20px; } .stat-item:not(:last-child)::after { display: none; } .restaurant-card { flex-direction: column; text-align: center; } .restaurant-image { margin-right: 0; margin-bottom: 15px; } .restaurant-tags { justify-content: center; } } </style> </head> <body> <div class="container"> <div class="restaurant-card"> <img src="https://images.unsplash.com/photo-1555396273-367ea4eb4db5?q=80&w=1974&auto=format&fit=crop" alt="Noma Restaurant" class="restaurant-image"> <div class="restaurant-details"> <h3>Noma Restaurant</h3> <p>Copenhagen, Denmark</p> <div class="restaurant-tags"> <span class="tag">Fine Dining</span> <span class="tag">Nordic</span> <span class="tag">Michelin ★★★</span> </div> </div> </div> <h1>How was your dining experience?</h1> <h2>Your honest review helps our community discover extraordinary places</h2> <div class="rating-section"> <div class="rating-container"> <div class="stars-container"> <div class="stars-display"> <span class="star" data-value="0.5"></span> <span class="star" data-value="1"></span> <span class="star" data-value="1.5"></span> <span class="star" data-value="2"></span> <span class="star" data-value="2.5"></span> <span class="star" data-value="3"></span> <span class="star" data-value="3.5"></span> <span class="star" data-value="4"></span> <span class="star" data-value="4.5"></span> <span class="star" data-value="5"></span> </div> <div class="stars-fillable" id="fillable-stars"></div> </div> <div class="rating-value"> <span id="rating-number">0</span> <span id="rating-hint" class="rating-hint">Tap to rate</span> </div> <div id="rating-feedback" class="rating-feedback"></div> </div> <textarea placeholder="Share what made this experience special. What dishes stood out? How was the service and ambiance?"></textarea> <button class="button" id="submit-button">Submit Review</button> </div> <div class="community-stats"> <div class="stat-item"> <div class="stat-value">3,724</div> <div class="stat-label">Community Reviews</div> </div> <div class="stat-item"> <div class="stat-value">4.7</div> <div class="stat-label">Average Rating</div> </div> <div class="stat-item"> <div class="stat-value">92%</div> <div class="stat-label">Would Recommend</div> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { const starsContainer = document.querySelector('.stars-container'); const stars = document.querySelectorAll('.star'); const fillableStars = document.getElementById('fillable-stars'); const ratingNumber = document.getElementById('rating-number'); const ratingHint = document.getElementById('rating-hint'); const ratingFeedback = document.getElementById('rating-feedback'); const submitButton = document.getElementById('submit-button'); let rating = 0; let starWidth = stars[0].offsetWidth; const feedbackMessages = [ { threshold: 1, message: '<span class="emoji">😞</span> Disappointed', color: '#FF6B6B' }, { threshold: 2, message: '<span class="emoji">😐</span> Just OK', color: '#FFC107' }, { threshold: 3, message: '<span class="emoji">🙂</span> Decent experience', color: '#4C5EFD' }, { threshold: 4, message: '<span class="emoji">😊</span> Very good!', color: '#26DE81' }, { threshold: 5, message: '<span class="emoji">🤩</span> Absolutely amazing!', color: '#26DE81' } ]; function updateStarDisplay(current = null) { if (current !== null) { const hoverValue = parseFloat(current.dataset.value); fillableStars.style.width = (hoverValue / 5 * 100) + '%'; if (!rating) { ratingNumber.textContent = hoverValue.toFixed(1); updateFeedbackText(hoverValue, true); } } else if (rating) { fillableStars.style.width = (rating / 5 * 100) + '%'; ratingNumber.textContent = rating.toFixed(1); updateFeedbackText(rating); } else { fillableStars.style.width = '0%'; ratingNumber.textContent = '0'; ratingHint.textContent = 'Tap to rate'; ratingFeedback.classList.remove('show'); } } function updateFeedbackText(value, isHover = false) { const feedbackItem = feedbackMessages.find(item => value <= item.threshold); if (feedbackItem) { if (!isHover) { ratingFeedback.innerHTML = feedbackItem.message; ratingFeedback.style.color = feedbackItem.color; ratingFeedback.classList.add('show'); ratingHint.textContent = 'Your rating'; } else { ratingHint.textContent = feedbackItem.message.replace(/<[^>]*>?/gm, ''); } } } function createConfetti(x, y) { const colors = ['#FF6B6B', '#4C5EFD', '#26DE81', '#FFC107']; const shapes = ['circle', 'square', 'triangle']; for (let i = 0; i < 30; i++) { const confetti = document.createElement('div'); confetti.className = 'confetti'; // Random properties const color = colors[Math.floor(Math.random() * colors.length)]; const shape = shapes[Math.floor(Math.random() * shapes.length)]; const size = Math.random() * 10 + 5; confetti.style.backgroundColor = color; confetti.style.width = `${size}px`; confetti.style.height = `${size}px`; if (shape === 'circle') { confetti.style.borderRadius = '50%'; } else if (shape === 'triangle') { confetti.style.width = '0'; confetti.style.height = '0'; confetti.style.backgroundColor = 'transparent'; confetti.style.borderLeft = `${size/2}px solid transparent`; confetti.style.borderRight = `${size/2}px solid transparent`; confetti.style.borderBottom = `${size}px solid ${color}`; } // Position at click/tap location confetti.style.left = `${x}px`; confetti.style.top = `${y}px`; document.body.appendChild(confetti); // Animation const angle = Math.random() * Math.PI * 2; const distance = Math.random() * 100 + 50; const destinationX = x + Math.cos(angle) * distance; const destinationY = y + Math.sin(angle) * distance; confetti.animate([ { transform: `translate(0, 0) rotate(0deg)`, opacity: 1 }, { transform: `translate(${destinationX - x}px, ${destinationY - y}px) rotate(${Math.random() * 720}deg)`, opacity: 0 } ], { duration: Math.random() * 1000 + 1000, easing: 'cubic-bezier(.37,.74,.15,1)', fill: 'forwards' }); setTimeout(() => { confetti.remove(); }, 2000); } } // Mouse/touch events for stars stars.forEach(star => { star.addEventListener('mouseover', function() { updateStarDisplay(this); }); star.addEventListener('click', function(e) { rating = parseFloat(this.dataset.value); updateStarDisplay(); // Get the position for confetti const rect = star.getBoundingClientRect(); createConfetti(rect.left + rect.width/2, rect.top + rect.height/2); // Animate rating change ratingNumber.style.animation = 'pulse 0.3s ease-in-out'; setTimeout(() => { ratingNumber.style.animation = ''; }, 300); }); }); starsContainer.addEventListener('mouseout', function() { updateStarDisplay(); }); // Submit button submitButton.addEventListener('click', function() { if (rating > 0) { submitButton.textContent = "Thanks for your review!"; submitButton.style.backgroundColor = "#26DE81"; setTimeout(() => { submitButton.textContent = "Submit Review"; submitButton.style.backgroundColor = "#4C5EFD"; rating = 0; updateStarDisplay(); document.querySelector('textarea').value = ''; }, 2000); } else { submitButton.textContent = "Please add a rating first"; submitButton.style.backgroundColor = "#FF6B6B"; submitButton.animate([ { transform: 'translateX(-5px)' }, { transform: 'translateX(5px)' }, { transform: 'translateX(-5px)' }, { transform: 'translateX(5px)' }, { transform: 'translateX(0)' } ], { duration: 300, easing: 'ease-in-out' }); setTimeout(() => { submitButton.textContent = "Submit Review"; submitButton.style.backgroundColor = "#4C5EFD"; }, 2000); } }); // Make the stars responsive window.addEventListener('resize', function() { starWidth = stars[0].offsetWidth; updateStarDisplay(); }); // Enable half-star ratings with mousemove stars.forEach(star => { star.addEventListener('mousemove', function(e) { const starValue = parseFloat(this.dataset.value); const rect = this.getBoundingClientRect(); const percentage = (e.clientX - rect.left) / rect.width; // If mouse is on the left half of the star if (percentage <= 0.5 && starValue % 1 === 0) { fillableStars.style.width = ((Math.floor(starValue) - 0.5) / 5 * 100) + '%'; ratingNumber.textContent = (Math.floor(starValue) - 0.5).toFixed(1); updateFeedbackText(Math.floor(starValue) - 0.5, true); } else { fillableStars.style.width = (starValue / 5 * 100) + '%'; ratingNumber.textContent = starValue.toFixed(1); updateFeedbackText(starValue, true); } }); }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>NEXUS RATINGS</title> <style> :root { --primary-color: #ff3a5e; --secondary-color: #3affde; --background-dark: #121219; --background-darker: #0a0a10; --text-primary: #e0e0ff; --text-secondary: #8d8db7; --metallic-light: #e0e5ff; --metallic-dark: #70748c; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Rajdhani', 'Orbitron', sans-serif; } @keyframes backgroundPulse { 0% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } 100% { background-position: 0% 50%; } } @keyframes glitch { 0% { text-shadow: 0.05em 0 0 var(--primary-color), -0.05em -0.025em 0 var(--secondary-color); } 14% { text-shadow: 0.05em 0 0 var(--primary-color), -0.05em -0.025em 0 var(--secondary-color); } 15% { text-shadow: -0.05em -0.025em 0 var(--primary-color), 0.025em 0.025em 0 var(--secondary-color); } 49% { text-shadow: -0.05em -0.025em 0 var(--primary-color), 0.025em 0.025em 0 var(--secondary-color); } 50% { text-shadow: 0.025em 0.05em 0 var(--primary-color), 0.05em 0 0 var(--secondary-color); } 99% { text-shadow: 0.025em 0.05em 0 var(--primary-color), 0.05em 0 0 var(--secondary-color); } 100% { text-shadow: 0.05em 0 0 var(--primary-color), -0.05em -0.025em 0 var(--secondary-color); } } @keyframes flicker { 0%, 19.999%, 22%, 62.999%, 64%, 64.999%, 70%, 100% { opacity: 0.99; filter: drop-shadow(0 0 1px rgba(252, 252, 252, 0.5)) drop-shadow(0 0 5px rgba(255, 58, 94, 0.5)); } 20%, 21.999%, 63%, 63.999%, 65%, 69.999% { opacity: 0.4; filter: none; } } @keyframes scanline { 0% { transform: translateY(-100%); } 100% { transform: translateY(100%); } } @keyframes shimmer { 0% { background-position: -100% 0; } 100% { background-position: 100% 0; } } body { background: var(--background-dark); background-image: radial-gradient(circle at 10% 20%, rgba(58, 255, 222, 0.1) 0%, transparent 20%), radial-gradient(circle at 90% 80%, rgba(255, 58, 94, 0.1) 0%, transparent 20%), linear-gradient(45deg, var(--background-dark) 0%, var(--background-darker) 100%); color: var(--text-primary); display: flex; justify-content: center; align-items: center; min-height: 100vh; overflow: hidden; padding: 20px; } .container { width: 100%; max-width: 680px; height: 660px; background: linear-gradient(140deg, rgba(30, 30, 45, 0.9), rgba(15, 15, 25, 0.95)); border-radius: 12px; box-shadow: 0 20px 40px rgba(0, 0, 0, 0.6), inset 0 0 0 1px rgba(255, 255, 255, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.1); padding: 30px; backdrop-filter: blur(10px); position: relative; overflow: hidden; } .container::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px; background: linear-gradient(90deg, var(--primary-color), var(--secondary-color)); z-index: 10; } .scanline { position: absolute; top: 0; left: 0; width: 100%; height: 10px; background: linear-gradient(to bottom, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.05), transparent); opacity: 0.3; animation: scanline 6s linear infinite; pointer-events: none; } .noise { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E"); opacity: 0.05; pointer-events: none; } h1 { font-size: 2.5rem; margin-bottom: 5px; background: linear-gradient(90deg, var(--metallic-light), var(--metallic-dark)); -webkit-background-clip: text; background-clip: text; color: transparent; font-weight: 700; text-transform: uppercase; letter-spacing: 2px; position: relative; display: inline-block; text-shadow: 0 2px 10px rgba(0, 0, 0, 0.2); animation: glitch 3s infinite alternate-reverse; } .subtitle { color: var(--text-secondary); font-size: 1rem; margin-bottom: 30px; opacity: 0.8; font-weight: 400; letter-spacing: 1px; } .game-card { background: linear-gradient(135deg, rgba(40, 40, 55, 0.8), rgba(25, 25, 35, 0.9)); border-radius: 10px; margin-bottom: 25px; padding: 20px; position: relative; overflow: hidden; transition: transform 0.3s, box-shadow 0.3s; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3), inset 0 0 0 1px rgba(255, 255, 255, 0.1); } .game-card:hover { transform: translateY(-5px); box-shadow: 0 12px 25px rgba(0, 0, 0, 0.4), inset 0 0 0 1px rgba(255, 255, 255, 0.15); } .game-card::after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent); transform: translateX(-100%); animation: shimmer 3s infinite; pointer-events: none; } .game-info { display: flex; align-items: center; margin-bottom: 15px; } .game-thumb { width: 80px; height: 80px; border-radius: 8px; overflow: hidden; margin-right: 15px; flex-shrink: 0; box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3); position: relative; } .game-thumb img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.3s; } .game-card:hover .game-thumb img { transform: scale(1.1); } .game-details { flex-grow: 1; } .game-title { font-size: 1.3rem; font-weight: 600; margin-bottom: 5px; color: var(--text-primary); } .game-meta { font-size: 0.85rem; color: var(--text-secondary); display: flex; flex-wrap: wrap; gap: 10px; } .game-tag { background: rgba(255, 58, 94, 0.15); color: var(--primary-color); padding: 2px 8px; border-radius: 4px; font-size: 0.75rem; } .rating-container { margin-top: 15px; } .rating-label { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; } .rating-label span { font-size: 0.9rem; color: var(--text-secondary); } .rating-value { font-weight: 600; color: var(--primary-color); } .stars-container { display: flex; position: relative; user-select: none; } .stars-bg { display: flex; } .star { width: 40px; height: 40px; margin-right: 10px; position: relative; cursor: pointer; transition: transform 0.2s; } .star:hover { transform: translateY(-3px) scale(1.1); } .star svg { position: absolute; width: 100%; height: 100%; } .star-bg { fill: rgba(255, 255, 255, 0.1); stroke: rgba(255, 255, 255, 0.3); stroke-width: 1; filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.3)); } .star-fill { fill: url(#starGradient); opacity: 0; filter: drop-shadow(0 0 5px rgba(255, 58, 94, 0.7)); transition: opacity 0.3s; } .star.active .star-fill { opacity: 1; } .star.pulse .star-fill { animation: flicker 2s infinite; } .star.half .star-fill { clip-path: polygon(0 0, 50% 0, 50% 100%, 0 100%); opacity: 1; } .submit-rating { width: 100%; padding: 12px; margin-top: 20px; background: linear-gradient(90deg, var(--primary-color), #ff6b8b); border: none; border-radius: 6px; color: white; font-weight: 600; font-size: 1rem; cursor: pointer; transition: all 0.3s; box-shadow: 0 5px 15px rgba(255, 58, 94, 0.3); position: relative; overflow: hidden; letter-spacing: 1px; text-transform: uppercase; } .submit-rating:hover { transform: translateY(-2px); box-shadow: 0 8px 20px rgba(255, 58, 94, 0.4); } .submit-rating:active { transform: translateY(1px); } .submit-rating::after { content: ''; position: absolute; top: -50%; left: -50%; width: 200%; height: 200%; background: linear-gradient( rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0) ); transform: rotate(30deg); transition: transform 0.3s; } .submit-rating:hover::after { transform: rotate(30deg) translate(10%, 10%); } .latest-reviews { margin-top: 30px; } .latest-reviews h2 { font-size: 1.2rem; margin-bottom: 15px; color: var(--text-primary); border-bottom: 1px solid rgba(255, 255, 255, 0.1); padding-bottom: 10px; } .review { background: rgba(20, 20, 30, 0.5); border-radius: 8px; padding: 15px; margin-bottom: 15px; display: flex; align-items: center; } .review-rating { display: flex; margin-right: 15px; } .review-star { color: var(--primary-color); font-size: 0.9rem; margin-right: 2px; } .review-content { flex-grow: 1; font-size: 0.9rem; } .review-author { font-weight: 600; margin-bottom: 5px; display: flex; justify-content: space-between; } .review-date { font-size: 0.8rem; color: var(--text-secondary); } .review-text { color: var(--text-secondary); line-height: 1.4; } /* Responsive styles */ @media (max-width: 600px) { .container { padding: 20px; } h1 { font-size: 1.8rem; } .game-info { flex-direction: column; align-items: flex-start; } .game-thumb { margin-bottom: 10px; margin-right: 0; width: 100%; height: 120px; } .star { width: 35px; height: 35px; margin-right: 5px; } } /* For smaller height screens */ @media (max-height: 700px) { .container { height: 600px; overflow-y: auto; } .latest-reviews { margin-top: 20px; } .game-card { padding: 15px; margin-bottom: 15px; } } </style> </head> <body> <div class="container"> <div class="scanline"></div> <div class="noise"></div> <h1>NEXUS RATINGS</h1> <p class="subtitle">RATE YOUR GAMING EXPERIENCE WITH NEXT-GEN PRECISION</p> <div class="game-card"> <div class="game-info"> <div class="game-thumb"> <img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3ClinearGradient id='bg' x1='0%25' y1='0%25' x2='100%25' y2='100%25'%3E%3Cstop offset='0%25' stop-color='%23370031'/%3E%3Cstop offset='100%25' stop-color='%23090979'/%3E%3C/linearGradient%3E%3Crect width='100' height='100' fill='url(%23bg)'/%3E%3Cpath d='M70 30L50 50 30 30 50 70z' fill='%23ff3a5e' opacity='.9'/%3E%3Cpath d='M50 20L65 65 50 50 35 65z' fill='%233affde' opacity='.8'/%3E%3C/svg%3E" alt="Quantum Nexus"> </div> <div class="game-details"> <div class="game-title">Quantum Nexus: Void Shift</div> <div class="game-meta"> <span>DEVELOPER: NightFall Studios</span> <span>RELEASE: 2023</span> </div> <div class="game-meta" style="margin-top: 5px;"> <span class="game-tag">Action RPG</span> <span class="game-tag">Sci-Fi</span> </div> </div> </div> <div class="rating-container"> <div class="rating-label"> <span>YOUR RATING</span> <span class="rating-value">0/5</span> </div> <div class="stars-container"> <svg style="width:0;height:0;position:absolute;" aria-hidden="true" focusable="false"> <linearGradient id="starGradient" x1="0%" y1="0%" x2="100%" y2="100%"> <stop offset="0%" stop-color="#ff3a5e" /> <stop offset="100%" stop-color="#ff6b8b" /> </linearGradient> </svg> <div class="stars-bg"> <div class="star" data-value="1"> <svg viewBox="0 0 24 24" class="star-bg"> <path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"></path> </svg> <svg viewBox="0 0 24 24" class="star-fill"> <path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"></path> </svg> </div> <div class="star" data-value="2"> <svg viewBox="0 0 24 24" class="star-bg"> <path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"></path> </svg> <svg viewBox="0 0 24 24" class="star-fill"> <path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"></path> </svg> </div> <div class="star" data-value="3"> <svg viewBox="0 0 24 24" class="star-bg"> <path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"></path> </svg> <svg viewBox="0 0 24 24" class="star-fill"> <path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"></path> </svg> </div> <div class="star" data-value="4"> <svg viewBox="0 0 24 24" class="star-bg"> <path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"></path> </svg> <svg viewBox="0 0 24 24" class="star-fill"> <path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"></path> </svg> </div> <div class="star" data-value="5"> <svg viewBox="0 0 24 24" class="star-bg"> <path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"></path> </svg> <svg viewBox="0 0 24 24" class="star-fill"> <path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"></path> </svg> </div> </div> </div> <button class="submit-rating" id="submit-rating">SUBMIT RATING</button> </div> </div> <div class="latest-reviews"> <h2>LATEST PLAYER REVIEWS</h2> <div class="review"> <div class="review-rating"> <div class="review-star">★</div> <div class="review-star">★</div> <div class="review-star">★</div> <div class="review-star">★</div> <div class="review-star">★</div> </div> <div class="review-content"> <div class="review-author"> <span>CyberWanderer</span> <span class="review-date">3 days ago</span> </div> <div class="review-text">The dimension-shifting mechanics are mind-blowing. Combat feels satisfying with the dual-phase weapons system. Best atmosphere since Dead Space.</div> </div> </div> <div class="review"> <div class="review-rating"> <div class="review-star">★</div> <div class="review-star">★</div> <div class="review-star">★</div> <div class="review-star">★</div> <div class="review-star" style="color:#333">★</div> </div> <div class="review-content"> <div class="review-author"> <span>VortexQueen</span> <span class="review-date">1 week ago</span> </div> <div class="review-text">Great level design and immersive world-building. The neo-synthwave soundtrack is epic! Loses a star for the repetitive side missions.</div> </div> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { const stars = document.querySelectorAll('.star'); const ratingValue = document.querySelector('.rating-value'); const submitButton = document.getElementById('submit-rating'); let currentRating = 0; let isHalf = false; // Event listeners for stars stars.forEach(star => { star.addEventListener('mousemove', handleStarHover); star.addEventListener('mouseleave', handleStarLeave); star.addEventListener('click', handleStarClick); }); // Submit button event submitButton.addEventListener('click', handleSubmit); function handleStarHover(e) { const star = e.currentTarget; const rect = star.getBoundingClientRect(); const value = parseInt(star.getAttribute('data-value')); const starCenter = rect.left + rect.width / 2; // Reset all stars stars.forEach(s => { s.classList.remove('active', 'half', 'pulse'); }); // Detect if hovering on left or right half of star if (e.clientX < starCenter) { isHalf = true; star.classList.add('half'); // Fill all previous stars completely for (let i = 0; i < value - 1; i++) { stars[i].classList.add('active'); } updateRatingDisplay(value - 0.5); } else { isHalf = false; // Fill this star and all previous stars for (let i = 0; i < value; i++) { stars[i].classList.add('active'); } updateRatingDisplay(value); } } function handleStarLeave() { stars.forEach((star, index) => { star.classList.remove('active', 'half'); // If we have a current rating, restore it if (index < Math.floor(currentRating)) { star.classList.add('active'); } else if (index === Math.floor(currentRating) && currentRating % 1 !== 0) { star.classList.add('half'); } }); updateRatingDisplay(currentRating); } function handleStarClick() { currentRating = isHalf ? parseFloat(this.getAttribute('data-value')) - 0.5 : parseFloat(this.getAttribute('data-value')); // Apply pulse effect to the selected stars stars.forEach((star, index) => { star.classList.remove('pulse'); if (index < Math.floor(currentRating)) { star.classList.add('pulse'); } if (index === Math.floor(currentRating) && currentRating % 1 !== 0) { star.classList.add('pulse'); } }); updateRatingDisplay(currentRating); } function updateRatingDisplay(rating) { ratingValue.textContent = rating + '/5'; } function handleSubmit() { if (currentRating === 0) { // Gently remind the user to select a rating with a visual cue stars.forEach(star => { star.style.animation = 'none'; setTimeout(() => { star.style.animation = 'flicker 0.5s'; }, 10); }); return; } // Visual feedback for submission submitButton.textContent = 'THANKS FOR RATING!'; submitButton.style.background = 'linear-gradient(90deg, #3affde, #2ed8b2)'; submitButton.disabled = true; // Add the new review to the top const reviewsContainer = document.querySelector('.latest-reviews'); const newReview = document.createElement('div'); newReview.className = 'review'; newReview.innerHTML = ` <div class="review-rating"> ${getStarsHTML(currentRating)} </div> <div class="review-content"> <div class="review-author"> <span>You</span> <span class="review-date">Just now</span> </div> <div class="review-text">Thanks for your rating! Write a longer review to help other players.</div> </div> `; // Insert after the heading const heading = reviewsContainer.querySelector('h2'); heading.insertAdjacentElement('afterend', newReview); // Apply an entrance animation newReview.style.opacity = '0'; newReview.style.transform = 'translateY(-10px)'; newReview.style.transition = 'opacity 0.5s, transform 0.5s'; setTimeout(() => { newReview.style.opacity = '1'; newReview.style.transform = 'translateY(0)'; }, 50); // Reset after delay setTimeout(() => { submitButton.textContent = 'SUBMIT RATING'; submitButton.style.background = 'linear-gradient(90deg, var(--primary-color), #ff6b8b)'; submitButton.disabled = false; }, 3000); } function getStarsHTML(rating) { let html = ''; const fullStars = Math.floor(rating); const hasHalfStar = rating % 1 !== 0; for (let i = 1; i <= 5; i++) { if (i <= fullStars) { html += '<div class="review-star">★</div>'; } else if (i === fullStars + 1 && hasHalfStar) { html += '<div class="review-star" style="position:relative;"><span style="position:absolute;width:50%;overflow:hidden;">★</span><span style="color:#333;position:absolute;left:50%;">★</span></div>'; } else { html += '<div class="review-star" style="color:#333">★</div>'; } } return html; } // Add initial pulse animation to stars function initializeStarAnimations() { stars.forEach((star, index) => { setTimeout(() => { star.classList.add('pulse'); setTimeout(() => { star.classList.remove('pulse'); }, 2000); }, index * 200); }); } initializeStarAnimations(); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Organic Restaurant Feedback</title> <style> :root { --primary: #ff7e5f; --primary-hover: #ff6347; --secondary: #feb47b; --text-dark: #4a4a4a; --text-light: #7a7a7a; --background: #fffaf5; --card-bg: #ffffff; --shadow: rgba(255, 126, 95, 0.15); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { background-color: var(--background); display: flex; justify-content: center; align-items: center; min-height: 700px; padding: 20px; overflow-x: hidden; } .container { width: 100%; max-width: 650px; background-color: var(--card-bg); border-radius: 24px; box-shadow: 0 12px 28px var(--shadow); padding: 30px; transition: transform 0.3s ease; } h1 { color: var(--text-dark); font-size: 28px; margin-bottom: 8px; font-weight: 700; text-align: center; } .subheading { color: var(--text-light); font-size: 16px; text-align: center; margin-bottom: 30px; } .rating-container { display: flex; flex-direction: column; gap: 25px; } .rating-question { margin-bottom: 10px; } .rating-question h3 { color: var(--text-dark); font-size: 18px; margin-bottom: 15px; font-weight: 600; } .stars { display: flex; justify-content: center; gap: 12px; } .star { position: relative; width: 48px; height: 48px; cursor: pointer; transition: transform 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275); } .star svg { position: absolute; top: 0; left: 0; width: 48px; height: 48px; fill: #e0e0e0; stroke: #d0d0d0; stroke-width: 1px; transition: all 0.3s ease; } .star svg.filled { fill: var(--primary); stroke: var(--primary-hover); opacity: 0; transform: scale(0.5); } .star.active svg.filled { opacity: 1; transform: scale(1); } .star:hover { transform: scale(1.15) rotate(5deg); } .star.pulse svg.filled { animation: pulse 0.6s ease-in-out; } @keyframes pulse { 0% { transform: scale(0.5); } 50% { transform: scale(1.2); } 100% { transform: scale(1); } } .feedback-text { text-align: center; font-size: 18px; height: 24px; color: var(--primary); font-weight: 600; margin: 5px 0 15px; opacity: 0; transform: translateY(10px); transition: all 0.3s ease; } .feedback-text.visible { opacity: 1; transform: translateY(0); } .comment-box { margin-top: 30px; opacity: 0; height: 0; overflow: hidden; transition: opacity 0.5s ease, height 0.5s ease; } .comment-box.visible { opacity: 1; height: auto; } .comment-box textarea { width: 100%; height: 120px; padding: 15px; border-radius: 12px; border: 2px solid #e0e0e0; resize: none; font-size: 16px; outline: none; transition: border 0.3s ease, box-shadow 0.3s ease; } .comment-box textarea:focus { border-color: var(--primary); box-shadow: 0 0 0 3px var(--shadow); } .comment-box label { display: block; margin-bottom: 10px; color: var(--text-dark); font-weight: 500; } .submit-btn { width: 100%; padding: 15px; margin-top: 25px; background: linear-gradient(135deg, var(--primary), var(--secondary)); color: white; border: none; border-radius: 12px; font-size: 18px; font-weight: 600; cursor: pointer; transition: all 0.3s ease; position: relative; overflow: hidden; } .submit-btn:hover { transform: translateY(-3px); box-shadow: 0 7px 14px rgba(255, 126, 95, 0.3); } .submit-btn:active { transform: translateY(0); } .submit-btn::after { content: ''; position: absolute; top: 50%; left: 50%; width: 0; height: 0; background-color: rgba(255, 255, 255, 0.2); border-radius: 50%; transform: translate(-50%, -50%); transition: width 0.6s ease, height 0.6s ease; } .submit-btn:hover::after { width: 300px; height: 300px; } .thank-you { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: var(--card-bg); border-radius: 24px; display: flex; flex-direction: column; justify-content: center; align-items: center; opacity: 0; visibility: hidden; transition: all 0.5s ease; padding: 30px; text-align: center; } .thank-you.visible { opacity: 1; visibility: visible; } .thank-you-icon { width: 80px; height: 80px; margin-bottom: 20px; animation: float 3s ease-in-out infinite; } @keyframes float { 0% { transform: translateY(0px); } 50% { transform: translateY(-10px); } 100% { transform: translateY(0px); } } .thank-you h2 { color: var(--text-dark); font-size: 28px; margin-bottom: 15px; } .thank-you p { color: var(--text-light); font-size: 18px; margin-bottom: 25px; max-width: 450px; } .dish-badges { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; margin: 20px 0; } .dish-badge { background-color: var(--background); border-radius: 20px; padding: 8px 15px; color: var(--text-dark); font-size: 14px; cursor: pointer; transition: all 0.3s ease; border: 2px solid transparent; font-weight: 500; } .dish-badge:hover { background-color: rgba(255, 126, 95, 0.1); transform: translateY(-2px); } .dish-badge.selected { background-color: rgba(255, 126, 95, 0.15); border-color: var(--primary); color: var(--primary); } .new-badge { display: inline-block; background-color: var(--primary); color: white; font-size: 10px; padding: 3px 6px; border-radius: 10px; margin-left: 5px; animation: pulse-badge 2s infinite; } @keyframes pulse-badge { 0% { transform: scale(1); } 50% { transform: scale(1.1); } 100% { transform: scale(1); } } .food-emoji { font-size: 22px; margin-right: 5px; display: inline-block; transform: translateY(2px); } @media (max-width: 600px) { .container { padding: 20px; } h1 { font-size: 24px; } .stars { gap: 8px; } .star { width: 40px; height: 40px; } .star svg { width: 40px; height: 40px; } .dish-badges { gap: 8px; } .dish-badge { font-size: 12px; padding: 6px 12px; } .submit-btn { padding: 12px; } } </style> </head> <body> <div class="container"> <h1>Savor & Share</h1> <p class="subheading">Tell us about your culinary journey at Olive & Thyme today</p> <div class="rating-container"> <div class="rating-question"> <h3>How was your overall dining experience?</h3> <div class="stars" id="experience-stars"> <div class="star" data-value="1"> <svg viewBox="0 0 24 24" class="outline"> <path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z" /> </svg> <svg viewBox="0 0 24 24" class="filled"> <path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z" /> </svg> </div> <div class="star" data-value="2"> <svg viewBox="0 0 24 24" class="outline"> <path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z" /> </svg> <svg viewBox="0 0 24 24" class="filled"> <path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z" /> </svg> </div> <div class="star" data-value="3"> <svg viewBox="0 0 24 24" class="outline"> <path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z" /> </svg> <svg viewBox="0 0 24 24" class="filled"> <path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z" /> </svg> </div> <div class="star" data-value="4"> <svg viewBox="0 0 24 24" class="outline"> <path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z" /> </svg> <svg viewBox="0 0 24 24" class="filled"> <path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z" /> </svg> </div> <div class="star" data-value="5"> <svg viewBox="0 0 24 24" class="outline"> <path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z" /> </svg> <svg viewBox="0 0 24 24" class="filled"> <path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z" /> </svg> </div> </div> <div class="feedback-text" id="experience-feedback"></div> </div> <div class="rating-question"> <h3>How would you rate the flavors and quality of your meal?</h3> <div class="stars" id="food-stars"> <div class="star" data-value="1"> <svg viewBox="0 0 24 24" class="outline"> <path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z" /> </svg> <svg viewBox="0 0 24 24" class="filled"> <path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z" /> </svg> </div> <div class="star" data-value="2"> <svg viewBox="0 0 24 24" class="outline"> <path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z" /> </svg> <svg viewBox="0 0 24 24" class="filled"> <path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z" /> </svg> </div> <div class="star" data-value="3"> <svg viewBox="0 0 24 24" class="outline"> <path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z" /> </svg> <svg viewBox="0 0 24 24" class="filled"> <path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z" /> </svg> </div> <div class="star" data-value="4"> <svg viewBox="0 0 24 24" class="outline"> <path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z" /> </svg> <svg viewBox="0 0 24 24" class="filled"> <path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z" /> </svg> </div> <div class="star" data-value="5"> <svg viewBox="0 0 24 24" class="outline"> <path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z" /> </svg> <svg viewBox="0 0 24 24" class="filled"> <path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z" /> </svg> </div> </div> <div class="feedback-text" id="food-feedback"></div> </div> <div class="rating-question"> <h3>Which dishes did you enjoy the most?</h3> <div class="dish-badges"> <div class="dish-badge"><span class="food-emoji">🍕</span>Truffle Flatbread</div> <div class="dish-badge"><span class="food-emoji">🥗</span>Garden Salad</div> <div class="dish-badge"><span class="food-emoji">🍝</span>Wild Mushroom Risotto</div> <div class="dish-badge"><span class="food-emoji">🥩</span>Herb-Crusted Lamb</div> <div class="dish-badge"><span class="food-emoji">🍤</span>Garlic Prawns</div> <div class="dish-badge"><span class="food-emoji">🍰</span>Lemon Tart</div> <div class="dish-badge"><span class="food-emoji">🍷</span>Wine Selection</div> <div class="dish-badge"><span class="food-emoji">🌶️</span>Spicy Cauliflower<span class="new-badge">NEW</span></div> </div> </div> <div class="comment-box" id="comment-section"> <label for="comment">Share more about your experience:</label> <textarea id="comment" placeholder="We'd love to hear the details of what made your experience special (or how we could improve)..."></textarea> </div> <button class="submit-btn" id="submit-btn">Submit Feedback</button> </div> <div class="thank-you" id="thank-you"> <svg class="thank-you-icon" viewBox="0 0 24 24"> <path fill="#ff7e5f" d="M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4M11,16.5L6.5,12L7.91,10.59L11,13.67L16.59,8.09L18,9.5L11,16.5Z" /> </svg> <h2>Thanks for your feedback!</h2> <p>Your insights help us craft better dining experiences. We look forward to serving you again soon.</p> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { const experienceStars = document.querySelectorAll('#experience-stars .star'); const foodStars = document.querySelectorAll('#food-stars .star'); const experienceFeedback = document.getElementById('experience-feedback'); const foodFeedback = document.getElementById('food-feedback'); const commentSection = document.getElementById('comment-section'); const submitBtn = document.getElementById('submit-btn'); const thankYou = document.getElementById('thank-you'); const dishBadges = document.querySelectorAll('.dish-badge'); const experienceFeedbackTexts = [ "We're sorry to hear that", "Below expectations", "It was okay", "Great experience!", "Absolutely fantastic!" ]; const foodFeedbackTexts = [ "We apologize for the meal", "Could use improvement", "Satisfactory flavors", "Delicious dishes!", "Culinary perfection!" ]; let experienceRating = 0; let foodRating = 0; function handleStarHover(stars) { stars.forEach(star => { star.addEventListener('mouseenter', function() { const value = parseInt(this.getAttribute('data-value')); highlightStars(stars, value); }); star.addEventListener('mouseleave', function() { const container = this.closest('.stars'); if (container.id === 'experience-stars') { highlightStars(stars, experienceRating); } else if (container.id === 'food-stars') { highlightStars(stars, foodRating); } }); }); } function highlightStars(stars, count) { stars.forEach(star => { const value = parseInt(star.getAttribute('data-value')); if (value <= count) { star.classList.add('active'); } else { star.classList.remove('active'); } }); } function handleStarClick(stars, feedbackElement, feedbackTexts, isExperience = true) { stars.forEach(star => { star.addEventListener('click', function() { const value = parseInt(this.getAttribute('data-value')); // Add pulse animation stars.forEach(s => s.classList.remove('pulse')); this.classList.add('pulse'); if (isExperience) { experienceRating = value; } else { foodRating = value; } highlightStars(stars, value); // Update feedback text feedbackElement.textContent = feedbackTexts[value - 1]; feedbackElement.classList.add('visible'); // Check if both ratings are provided checkRatings(); }); }); } function checkRatings() { if (experienceRating > 0 && foodRating > 0) { commentSection.classList.add('visible'); } } // Initialize star rating systems handleStarHover(experienceStars); handleStarHover(foodStars); handleStarClick(experienceStars, experienceFeedback, experienceFeedbackTexts, true); handleStarClick(foodStars, foodFeedback, foodFeedbackTexts, false); // Handle dish badge selection dishBadges.forEach(badge => { badge.addEventListener('click', function() { this.classList.toggle('selected'); }); }); // Handle form submission submitBtn.addEventListener('click', function(e) { e.preventDefault(); // Add submit button animation this.innerHTML = 'Thank you!'; // Show thank you message setTimeout(() => { thankYou.classList.add('visible'); }, 500); }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>B2B Rating System</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; } body { display: flex; justify-content: center; align-items: center; min-height: 700px; background-color: #f7f9fc; padding: 20px; } .rating-container { width: 100%; max-width: 650px; background-color: #ffffff; border-radius: 12px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.05); padding: 40px; transition: all 0.3s ease; } .header { margin-bottom: 30px; } h1 { color: #2c3e50; font-size: 24px; font-weight: 600; margin-bottom: 8px; line-height: 1.3; } .subheader { color: #7f8c8d; font-size: 15px; line-height: 1.5; margin-bottom: 20px; } .rating-categories { display: grid; grid-template-columns: 1fr; gap: 25px; margin-bottom: 35px; } .category { border-bottom: 1px solid #edf2f7; padding-bottom: 20px; } .category-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; } .category-title { color: #34495e; font-size: 16px; font-weight: 500; } .category-value { color: #2c3e50; font-size: 14px; font-weight: 600; min-width: 60px; text-align: right; opacity: 0; transform: translateY(5px); transition: all 0.3s ease; } .category-value.active { opacity: 1; transform: translateY(0); } .stars-container { position: relative; display: flex; align-items: center; } .stars { display: flex; gap: 5px; } .star { width: 22px; height: 22px; cursor: pointer; position: relative; display: inline-block; } .star-outline { position: absolute; top: 0; left: 0; width: 100%; height: 100%; fill: #e2e8f0; stroke: #cbd5e0; stroke-width: 1; transition: all 0.2s ease; } .star-fill { position: absolute; top: 0; left: 0; width: 100%; height: 100%; fill: #2c3e50; transform-origin: left; transform: scaleX(0); transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); } .star.hover .star-outline { fill: #edf2f7; stroke: #2c3e50; } .half-star-hover { position: absolute; width: 50%; height: 100%; left: 0; top: 0; z-index: 2; } .full-star-hover { position: absolute; width: 50%; height: 100%; right: 0; top: 0; z-index: 2; } .tooltip { position: absolute; top: -30px; left: 50%; transform: translateX(-50%) translateY(10px); background-color: #2c3e50; color: white; padding: 4px 8px; border-radius: 4px; font-size: 12px; opacity: 0; pointer-events: none; transition: all 0.2s ease; white-space: nowrap; } .tooltip::after { content: ''; position: absolute; bottom: -4px; left: 50%; transform: translateX(-50%) rotate(45deg); width: 8px; height: 8px; background-color: #2c3e50; } .stars-container:hover .tooltip { opacity: 1; transform: translateX(-50%) translateY(0); } .submit-container { margin-top: 20px; } .overall-rating { background-color: #f8fafc; border-radius: 8px; padding: 20px; margin-bottom: 30px; display: flex; flex-direction: column; align-items: center; position: relative; } .overall-rating-value { font-size: 48px; font-weight: 700; color: #2c3e50; line-height: 1; margin-bottom: 10px; opacity: 0; transform: translateY(10px); transition: all 0.5s ease; } .overall-rating-value.active { opacity: 1; transform: translateY(0); } .overall-rating-label { font-size: 14px; color: #7f8c8d; } .progress-rings { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; } .ring { stroke-dasharray: 628; stroke-dashoffset: 628; stroke-linecap: round; transition: stroke-dashoffset 1s ease; } button { width: 100%; background-color: #2c3e50; color: white; border: none; border-radius: 6px; padding: 14px 20px; font-size: 16px; font-weight: 500; cursor: pointer; transition: all 0.2s ease; position: relative; overflow: hidden; } button:hover { background-color: #34495e; } button:active { transform: translateY(1px); } button:disabled { background-color: #cbd5e0; cursor: not-allowed; } .button-content { position: relative; z-index: 1; display: flex; align-items: center; justify-content: center; gap: 8px; } .ripple { position: absolute; border-radius: 50%; background-color: rgba(255, 255, 255, 0.7); transform: scale(0); animation: ripple 0.6s linear; } @keyframes ripple { to { transform: scale(2.5); opacity: 0; } } .success-message { text-align: center; display: none; opacity: 0; transform: translateY(20px); transition: all 0.5s ease; } .success-message.active { display: block; opacity: 1; transform: translateY(0); } .success-icon { margin-bottom: 20px; width: 60px; height: 60px; background-color: #ebfbee; border-radius: 50%; display: flex; align-items: center; justify-content: center; margin-left: auto; margin-right: auto; } .success-title { color: #2c3e50; font-size: 20px; font-weight: 600; margin-bottom: 10px; } .success-text { color: #7f8c8d; font-size: 15px; line-height: 1.5; margin-bottom: 30px; } .tag { display: inline-block; padding: 4px 10px; background-color: #ebf5ff; color: #3182ce; border-radius: 4px; font-size: 12px; font-weight: 500; margin-right: 8px; margin-bottom: 8px; } /* Responsive styles */ @media (max-width: 600px) { .rating-container { padding: 25px; } h1 { font-size: 20px; } .subheader { font-size: 14px; } .overall-rating-value { font-size: 36px; } .category-title { font-size: 14px; } .star { width: 20px; height: 20px; } } </style> </head> <body> <div class="rating-container"> <div class="rating-form" id="ratingForm"> <div class="header"> <h1>Enterprise Service Evaluation</h1> <p class="subheader">Please rate your experience with our B2B solution across these critical business metrics. Your detailed feedback helps us optimize for your specific industry needs.</p> <div class="tags"> <span class="tag">Q4 2023 Review</span> <span class="tag">Enterprise Package</span> </div> </div> <div class="overall-rating"> <div class="progress-rings"> <svg width="100%" height="100%" viewBox="0 0 200 200"> <circle cx="100" cy="100" r="90" fill="none" stroke="#f1f5f9" stroke-width="4"></circle> <circle cx="100" cy="100" r="90" fill="none" stroke="#2c3e50" stroke-width="4" class="ring" transform="rotate(-90 100 100)"></circle> </svg> </div> <div class="overall-rating-value" id="overallValue">0.0</div> <div class="overall-rating-label">Overall Rating</div> </div> <div class="rating-categories"> <div class="category"> <div class="category-header"> <div class="category-title">Implementation Efficiency</div> <div class="category-value" id="value1">Not rated</div> </div> <div class="stars-container" data-category="implementation"> <div class="stars" id="stars1"> <!-- Stars inserted by JS --> </div> <div class="tooltip">How quickly were you able to implement our solution?</div> </div> </div> <div class="category"> <div class="category-header"> <div class="category-title">Technical Support Quality</div> <div class="category-value" id="value2">Not rated</div> </div> <div class="stars-container" data-category="support"> <div class="stars" id="stars2"> <!-- Stars inserted by JS --> </div> <div class="tooltip">Rate our technical support responsiveness and expertise</div> </div> </div> <div class="category"> <div class="category-header"> <div class="category-title">ROI & Business Impact</div> <div class="category-value" id="value3">Not rated</div> </div> <div class="stars-container" data-category="roi"> <div class="stars" id="stars3"> <!-- Stars inserted by JS --> </div> <div class="tooltip">Has our solution delivered measurable business value?</div> </div> </div> <div class="category"> <div class="category-header"> <div class="category-title">Integration Capabilities</div> <div class="category-value" id="value4">Not rated</div> </div> <div class="stars-container" data-category="integration"> <div class="stars" id="stars4"> <!-- Stars inserted by JS --> </div> <div class="tooltip">How well does our solution integrate with your stack?</div> </div> </div> <div class="category"> <div class="category-header"> <div class="category-title">Enterprise Feature Completeness</div> <div class="category-value" id="value5">Not rated</div> </div> <div class="stars-container" data-category="features"> <div class="stars" id="stars5"> <!-- Stars inserted by JS --> </div> <div class="tooltip">How complete is our feature set for your needs?</div> </div> </div> </div> <div class="submit-container"> <button id="submitBtn" disabled> <div class="button-content"> <span>Submit Evaluation</span> <svg width="16" height="16" viewBox="0 0 24 24" fill="none"> <path d="M5 12H19M19 12L12 5M19 12L12 19" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </div> </button> </div> </div> <div class="success-message" id="successMessage"> <div class="success-icon"> <svg width="30" height="30" viewBox="0 0 24 24" fill="none"> <path d="M5 12L10 17L19 8" stroke="#059669" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </div> <h2 class="success-title">Thank you for your evaluation</h2> <p class="success-text">Your detailed assessment helps us fine-tune our enterprise offering for your industry vertical. A member of our executive team will review your feedback within 24 hours.</p> <button id="resetBtn"> <div class="button-content"> <span>Submit Another Evaluation</span> </div> </button> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Initialize variables const ratings = { implementation: 0, support: 0, roi: 0, integration: 0, features: 0 }; let allCategories = Object.keys(ratings); let currentHoverRating = 0; let currentCategory = ''; // Create star rating elements for each category for (let i = 1; i <= 5; i++) { const starsContainer = document.getElementById(`stars${i}`); for (let j = 1; j <= 5; j++) { const star = createStarElement(j); starsContainer.appendChild(star); } } // Create star element with half-star capabilities function createStarElement(position) { const star = document.createElement('div'); star.className = 'star'; star.dataset.position = position; const starOutline = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); starOutline.setAttribute('viewBox', '0 0 24 24'); starOutline.classList.add('star-outline'); starOutline.innerHTML = '<path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z"/>'; const starFill = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); starFill.setAttribute('viewBox', '0 0 24 24'); starFill.classList.add('star-fill'); starFill.innerHTML = '<path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z"/>'; const halfStarHover = document.createElement('div'); halfStarHover.className = 'half-star-hover'; const fullStarHover = document.createElement('div'); fullStarHover.className = 'full-star-hover'; star.appendChild(starOutline); star.appendChild(starFill); star.appendChild(halfStarHover); star.appendChild(fullStarHover); return star; } // Set up event listeners for all star rating containers document.querySelectorAll('.stars-container').forEach((container, index) => { const category = container.dataset.category; const stars = container.querySelectorAll('.star'); const valueEl = document.getElementById(`value${index + 1}`); // Half-star hover effect stars.forEach(star => { const position = parseInt(star.dataset.position); star.querySelector('.half-star-hover').addEventListener('mouseenter', () => { currentHoverRating = position - 0.5; currentCategory = category; updateStarsHoverState(stars, currentHoverRating); }); star.querySelector('.full-star-hover').addEventListener('mouseenter', () => { currentHoverRating = position; currentCategory = category; updateStarsHoverState(stars, currentHoverRating); }); // Click events for both half and full stars star.querySelector('.half-star-hover').addEventListener('click', () => { setRating(category, position - 0.5, stars, valueEl); }); star.querySelector('.full-star-hover').addEventListener('click', () => { setRating(category, position, stars, valueEl); }); }); // Mouse leave event for the entire stars container container.addEventListener('mouseleave', () => { resetStarsHoverState(stars); updateStarsSelectedState(stars, ratings[category]); }); }); // Update the hover state of stars function updateStarsHoverState(stars, rating) { stars.forEach(star => { const position = parseInt(star.dataset.position); star.classList.add('hover'); const fill = star.querySelector('.star-fill'); if (position < rating) { // Full star fill.style.transform = 'scaleX(1)'; } else if (position === Math.ceil(rating) && !Number.isInteger(rating)) { // Half star fill.style.transform = 'scaleX(0.5)'; } else { // Empty star fill.style.transform = 'scaleX(0)'; } }); } // Reset hover state function resetStarsHoverState(stars) { stars.forEach(star => { star.classList.remove('hover'); }); } // Set the selected rating function setRating(category, rating, stars, valueEl) { ratings[category] = rating; updateStarsSelectedState(stars, rating); valueEl.textContent = rating % 1 === 0 ? rating.toFixed(1) : rating.toFixed(1); valueEl.classList.add('active'); updateOverallRating(); checkAllRated(); // Add ripple effect to the star const ripple = document.createElement('div'); ripple.classList.add('ripple'); stars[Math.ceil(rating) - 1].appendChild(ripple); // Clean up ripple after animation setTimeout(() => { ripple.remove(); }, 600); } // Update the selected state of stars function updateStarsSelectedState(stars, rating) { stars.forEach(star => { const position = parseInt(star.dataset.position); const fill = star.querySelector('.star-fill'); if (position <= Math.floor(rating)) { // Full star fill.style.transform = 'scaleX(1)'; } else if (position === Math.ceil(rating) && !Number.isInteger(rating)) { // Half star fill.style.transform = 'scaleX(0.5)'; } else { // Empty star fill.style.transform = 'scaleX(0)'; } }); } // Calculate and update overall rating function updateOverallRating() { let sum = 0; let count = 0; for (const category in ratings) { if (ratings[category] > 0) { sum += ratings[category]; count++; } } if (count > 0) { const overall = sum / count; const overallValueEl = document.getElementById('overallValue'); overallValueEl.textContent = overall.toFixed(1); overallValueEl.classList.add('active'); // Update the progress ring const ringEl = document.querySelector('.ring'); const circumference = 628; // 2 * π * 100 (circle radius) const offset = circumference - (overall / 5) * circumference; ringEl.style.strokeDashoffset = offset; } } // Check if all categories have been rated function checkAllRated() { const isAllRated = allCategories.every(category => ratings[category] > 0); const submitBtn = document.getElementById('submitBtn'); submitBtn.disabled = !isAllRated; } // Submit button click document.getElementById('submitBtn').addEventListener('click', function(e) { e.preventDefault(); // Create ripple effect const rect = this.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; const ripple = document.createElement('div'); ripple.classList.add('ripple'); ripple.style.left = x + 'px'; ripple.style.top = y + 'px'; this.appendChild(ripple); // Show success message setTimeout(() => { document.getElementById('ratingForm').style.display = 'none'; document.getElementById('successMessage').classList.add('active'); ripple.remove(); }, 500); }); // Reset button click document.getElementById('resetBtn').addEventListener('click', function() { // Reset all ratings for (const category in ratings) { ratings[category] = 0; } // Reset all star displays document.querySelectorAll('.stars').forEach((starsContainer) => { const stars = starsContainer.querySelectorAll('.star'); updateStarsSelectedState(stars, 0); }); // Reset category values document.querySelectorAll('.category-value').forEach((valueEl) => { valueEl.textContent = 'Not rated'; valueEl.classList.remove('active'); }); // Reset overall rating const overallValueEl = document.getElementById('overallValue'); overallValueEl.textContent = '0.0'; overallValueEl.classList.remove('active'); // Reset progress ring const ringEl = document.querySelector('.ring'); ringEl.style.strokeDashoffset = 628; // Disable submit button document.getElementById('submitBtn').disabled = true; // Hide success message and show form document.getElementById('successMessage').classList.remove('active'); setTimeout(() => { document.getElementById('ratingForm').style.display = 'block'; }, 300); }); }); </script> </body> </html>