Search code examples
htmlcssrating-system

Star rating system that submits on click without JavaScript?


I'm implementing a star rating system, but it's testing the limits of what I know about CSS selectors.

Currently I have it so that every star is a submit button that highlights when you hover over it. The current problem is that I don't know how to change the visual of the previous stars (so when you're hovering over the third one, it also highlights the first two.

Here is the current implementation:

HTML:

<div class="ratings>
  <form action="/blog/rate" class="ratings-form" method="post">
    <input id="rating_rating" name="rating[rating]" type="hidden" value="1">
    <input id="rating_post_id" name="rating[post_id]" type="hidden" value="3">
    <div id="rating-1" class="rating-star true"><input type="submit" value="★"></div>
  </form>
  <form action="/blog/rate" class="ratings-form" method="post">
    <input id="rating_rating" name="rating[rating]" type="hidden" value="2">
    ... (continued through 5) ...
</div>

CSS:

.rating-star > input[type="submit"] {
  padding: 0px 2px;
  float: left;
  color: #ccc;
  background: transparent;
  border:0 none;
  border-radius: 50px;
}

.rating-star > input[type="submit"]:hover {
  color: #faa;
}

Since the element I want to modify is a couple of levels deep in the form, it seems that I can't use ~ the sibling selector. Am I missing something or do I need JavaScript to make this effect possible?


Solution

  • Yes, this is possible, but not quite in the way you are trying to do it. The main thing you were missing is that you can use the name attribute on elements with type=submit. In order to make this work as intended, we also need to have the stars in reverse order in the HTML so that the sibling operators work correctly.

    form {
      width: 100px;
    }
    
    button {
      border: 0;
      background: transparent;
      font-size: 1.5em;
      margin: 0;
      padding: 0;
      float: right;
    }
    
    button:hover,
    button:hover + button,
    button:hover + button + button,
    button:hover + button + button + button,
    button:hover + button + button + button + button {
      color: #faa;
    }
    <form action="" method="POST">
      <input type="hidden" name="rating[post_id]" value="3">
      <button type="submit" name="rating[rating]" value="5">&#9733;</button>
      <button type="submit" name="rating[rating]" value="4">&#9733;</button>
      <button type="submit" name="rating[rating]" value="3">&#9733;</button>
      <button type="submit" name="rating[rating]" value="2">&#9733;</button>
      <button type="submit" name="rating[rating]" value="1">&#9733;</button>
    
    </form>